1
0
forked from drath/libratbag

Compare commits

..

14 Commits
v0.18 ... dm5

Author SHA1 Message Date
Thomas H.P. Andersen
e28a6a92d6 sinowealth: add definition for repeated clicks 2020-10-05 01:49:34 +02:00
Thomas H.P. Andersen
381de107be sinowealth: add .device option for led RGB vs RBG 2020-10-05 01:49:34 +02:00
Marian Beermann
f474776a4d sinowealth: working button remapping 2020-10-05 01:40:36 +02:00
Marian Beermann
fd99aa29a7 sinowealth: SINOWEALTH_BUTTON_TPYE_SWITCH_DPI 2020-10-05 01:40:36 +02:00
Marian Beermann
53bc81f6fe sinowealth: use macro action with keycode_from_macro() 2020-10-05 01:40:36 +02:00
Marian Beermann
ff215126b2 sinowealth: fix button_data being discarded 2020-10-05 01:40:36 +02:00
Thomas H.P. Andersen
78793296a2 WIP: sinowealth: button write support
Seems like it should work - but it does not...
2020-10-05 01:40:36 +02:00
Thomas H.P. Andersen
a6cb7f8301 sinowealth: revamp button reading 2020-10-05 01:40:36 +02:00
Thomas H.P. Andersen
9cb444bb07 sinowealth: use enum for sensor 2020-10-05 01:40:36 +02:00
Thomas H.P. Andersen
121a843071 WIP: sinowealth: read button mapping 2020-10-05 01:40:36 +02:00
Thomas H.P. Andersen
62a620c056 sinowealth: use commonly available breathing mode
The DM5 does not have the RGB_BREATHING1 mode, but
does have the RGB_BREATHING7 mode. This changes the
driver to map to the commonly available mode.
2020-10-05 01:40:36 +02:00
Thomas H.P. Andersen
9d30ec5437 sinowealth: read device-specific from .device file
This moves device-specific specifications to the
.device files. The number of LEDs and buttons varies
as well as sensor (dpi specs)
2020-10-05 01:40:36 +02:00
Thomas H.P. Andersen
e570e29a1e sinowealth: parse led color as RGB
This was parsed as RBG but this is not the layout used on the
DM5. The RBG-parsing seems intentional, so this might need to
flip on either device or firmware version.
2020-10-05 01:40:36 +02:00
Thomas H.P. Andersen
1f79d8e6e2 add device file for Dream Machines DM5 Blink 2020-10-05 01:40:36 +02:00
226 changed files with 4870 additions and 12835 deletions

269
.circleci/config.yml Normal file
View File

@@ -0,0 +1,269 @@
libratbag_references:
build_dependencies: &build_dependencies
FEDORA_DEP_BUILD: gcc gcc-c++ meson dbus-daemon glib2-devel json-glib-devel libevdev-devel libudev-devel libunistring-devel python3-devel python3-evdev swig
FEDORA_DEP_TEST: check-devel python3-gobject python3-lxml valgrind diffutils
FEDORA_DEP_DOC: python3-sphinx python3-sphinx_rtd_theme
UBUNTU_DEP_BUILD: gcc g++ meson pkg-config systemd libevdev-dev libglib2.0-dev libjson-glib-dev libsystemd-dev libudev-dev libunistring-dev python3-dev python3-evdev swig
UBUNTU_DEP_TEST: check python3-gi python3-lxml valgrind
ARCH_DEP_BUILD: meson swig glib2 libevdev libudev.so libunistring json-glib python python-evdev python-gobject
ARCH_DEP_TEST: check valgrind python-lxml
default_settings: &default_settings
working_directory: ~/libratbag
environment:
LANG: C.UTF-8
build_default: &build_default
name: Build
command: |
rm -rf build
meson build ${MESON_PARAMS}
meson configure build
ninja -v -C build ${NINJA_ARGS}
environment:
MESON_PARAMS: --prefix=/usr
build_buildtype_plain: &build_buildtype_plain
run:
<<: *build_default
name: Build with buildtype plain
environment:
MESON_PARAMS: --prefix=/usr -Dbuildtype=plain
build_buildtype_release: &build_buildtype_release
run:
<<: *build_default
name: Build with buildtype release
environment:
MESON_PARAMS: --prefix=/usr -Dbuildtype=release
build_and_test: &build_and_test
run:
<<: *build_default
name: Build and test
environment:
NINJA_ARGS: test
build_with_docs: &build_with_docs
run:
<<: *build_default
name: Build with documentation
environment:
MESON_PARAMS: -Ddocumentation=true
install: &install
run:
name: Installing
command: ninja -C build install
check_install: &check_install
run:
name: Checking installation
command: |
PREFIX=/usr/local/
diff -u <(cd data/devices; ls *.device) <(cd $PREFIX/share/libratbag; ls *.device)
check_uninstall: &check_uninstall
run:
name: Checking if any files are left after uninstall
command: |
PREFIX=/root/test_install
meson build_install --prefix=$PREFIX
ninja -C build_install install
ninja -C build_install uninstall
if [ -d $PREFIX ]
then
tree $PREFIX
exit 1
fi
export_logs: &export_logs
store_artifacts:
path: ~/libratbag/build/meson-logs
start_dbus: &start_dbus
run:
name: Start dbus daemon
command: |
mkdir /run/dbus
/usr/bin/dbus-daemon --system --fork
save_date: &save_date
run:
name: Save date
command: date +%F > /tmp/date
fedora_save_cache: &fedora_save_cache
save_cache:
key: fedora-cache-v1-{{ checksum "/tmp/date" }}
paths:
- /var/cache/dnf
fedora_fetch_cache: &fedora_fetch_cache
restore_cache:
keys:
- fedora-cache-v1
fedora_install: &fedora_install
run:
name: Install prerequisites
command: |
echo keepcache=1 >> /etc/dnf/dnf.conf
dnf install -y git ${FEDORA_DEP_BUILD} ${FEDORA_DEP_TEST}
sed -i 's/systemd//' /etc/nsswitch.conf
fedora_settings: &fedora_settings
<<: *default_settings
steps:
- *save_date
- *fedora_fetch_cache
- *fedora_install
- checkout
- *start_dbus
- *build_and_test
- *install
- *check_install
- *check_uninstall
- *build_buildtype_plain
- *build_buildtype_release
- *export_logs
- *fedora_save_cache
environment:
*build_dependencies
arch_save_cache: &arch_save_cache
save_cache:
key: arch-cache-v1-{{ checksum "/tmp/date" }}
paths:
- /var/cache/pacman/pkg
arch_fetch_cache: &arch_fetch_cache
restore_cache:
keys:
- arch-cache-v1
arch_settings: &arch_settings
<<: *default_settings
steps:
- *save_date
- *arch_fetch_cache
- run:
name: Install prerequisites
command: pacman -Syu --noconfirm --noprogressbar --needed base-devel git tree ${ARCH_DEP_BUILD} ${ARCH_DEP_TEST}
- *start_dbus
- checkout
- *build_and_test
- *install
- *check_install
- *check_uninstall
- *export_logs
- *arch_save_cache
environment:
*build_dependencies
ubuntu_settings: &ubuntu_settings
<<: *default_settings
steps:
- run:
name: Install prerequisites
command: |
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y git ${UBUNTU_DEP_BUILD} ${UBUNTU_DEP_TEST}
- checkout
- *start_dbus
- *build_and_test
- *install
- *check_install
- *check_uninstall
- *build_buildtype_plain
- *build_buildtype_release
- *export_logs
environment:
*build_dependencies
doc_build: &doc_build
<<: *default_settings
steps:
- *fedora_fetch_cache
- *fedora_install
- run:
name: Install documentation build-deps
command: dnf install -y ${FEDORA_DEP_DOC}
- checkout
- *build_with_docs
- *export_logs
- store_artifacts:
path: ~/libratbag/build/doc/html
- persist_to_workspace:
root: build
paths:
- doc/html/*
environment:
*build_dependencies
docs_deploy: &docs_deploy
<<: *default_settings
steps:
- *fedora_fetch_cache
- run:
name: Install prerequisites
command: dnf install -y git tree
- checkout
- attach_workspace:
at: build
- run:
name: Setup the deploy SSH key
command: |
ssh-add -L | tail -n1 > ~/.ssh/deploy.pub
cat <<EOF > ~/.ssh/config
Host github.com
IdentityFile /root/.ssh/deploy.pub
IdentitiesOnly yes
EOF
- run:
name: Clone doc repository
command: |
cd ~
git clone ssh://git@github.com/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_PROJECT_REPONAME}.github.io
- run:
name: Copy the doc, commit and push
command: |
set +e
cd ~/${CIRCLE_PROJECT_REPONAME}.github.io
\cp -r ~/${CIRCLE_PROJECT_REPONAME}/build/doc/html/* .
if ! git diff-index --quiet HEAD --; then
git config --global user.email "libratbag@librabtag.github.io"
git config --global user.name "The libratbag crew"
git add .
git commit -m "update docs from ${CIRCLE_SHA1}"
git push
fi
version: 2
jobs:
fedora_32:
<<: *fedora_settings
docker:
- image: fedora:32
arch:
<<: *arch_settings
docker:
- image: archlinux
ubuntu_20_04:
<<: *ubuntu_settings
docker:
- image: ubuntu:20.04
doc_build:
<<: *doc_build
docker:
- image: fedora:32
doc_deploy:
<<: *docs_deploy
docker:
- image: fedora:32
workflows:
version: 2
compile_and_test:
jobs:
- ubuntu_20_04
- arch
- fedora_32
- doc_build
- doc_deploy:
requires:
- doc_build
filters:
branches:
only: master

3
.flake8 Normal file
View File

@@ -0,0 +1,3 @@
[flake8]
ignore = E402,E501
exclude = .git,__pycache__,build,data,piper/piper.py

View File

@@ -1,39 +0,0 @@
# A Github Action to build a repository with meson
name: "Setup and run meson"
description: "Setup and run meson"
inputs:
builddir:
description: "The build directory"
default: "builddir"
srcdir:
description: "The source directory"
default: "."
meson_args:
description: "Arguments passed to meson setup"
default: ""
meson_skip_test:
description: "Set to a nonempty string to skip meson test"
default: ""
meson_test_args:
description: "Arguments passed to meson test"
default: ""
meson_precmd:
description: "Set to 'sudo' to run with sudo"
default: ""
ninja_args:
description: "Arguments passed to ninja"
default: ""
ninja_precmd:
description: "Set to 'sudo' to run with sudo"
default: ""
runs:
using: "composite"
steps:
- run: |
${{inputs.meson_precmd}} meson setup ${{inputs.builddir}} ${{inputs.srcdir}} ${{inputs.meson_args}}
${{inputs.meson_precmd}} meson configure ${{inputs.builddir}}
${{inputs.ninja_precmd}} ninja -C ${{inputs.builddir}} ${{inputs.ninja_args}}
if [[ -z "${{inputs.meson_skip_test}}" ]]; then
${{inputs.meson_precmd}} meson test -C ${{inputs.builddir}} --print-errorlogs ${{inputs.meson_test_args}};
fi
shell: bash

View File

@@ -1,17 +0,0 @@
name: "Install packages"
description: "Install a set of packages from sources"
inputs:
apt:
description: "The package list to install with apt"
pip:
description: "The package list to install with pip"
pip_precmd:
description: "Set to the string 'sudo' to run through sudo"
default: ""
runs:
using: "composite"
steps:
- run: sudo ${{ github.action_path }}/install-apt.sh ${{ inputs.apt }}
shell: bash
- run: ${{inputs.pip_precmd}} ${{ github.action_path }}/install-pip.sh ${{ inputs.pip }}
shell: bash

View File

@@ -1,14 +0,0 @@
#!/bin/bash -x
# If called without arguments, just skip the rest
if [[ -z "$@" ]]; then
exit
fi
# Don't care about these bits
echo 'path-exclude=/usr/share/doc/*' > /etc/dpkg/dpkg.cfg.d/99-exclude-cruft
echo 'path-exclude=/usr/share/locale/*' >> /etc/dpkg/dpkg.cfg.d/99-exclude-cruft
echo 'path-exclude=/usr/share/man/*' >> /etc/dpkg/dpkg.cfg.d/99-exclude-cruft
apt-get update
apt-get install -yq --no-install-suggests --no-install-recommends $@

View File

@@ -1,9 +0,0 @@
#!/bin/bash -x
# If called without arguments, just skip the rest
if [[ -z "$@" ]]; then
exit
fi
python -m pip install --upgrade pip
python -m pip install --upgrade "$@"

View File

@@ -1,50 +0,0 @@
name: linux
on: [ push, pull_request ]
env:
UBUNTU_DEP_BUILD: |
gcc g++ pkg-config systemd libevdev-dev libglib2.0-dev
libjson-glib-dev libsystemd-dev libudev-dev libunistring-dev
python3-dev python3-evdev swig python3-sphinx
UBUNTU_DEP_TEST: check python3-gi python3-lxml valgrind
PIP_PACKAGES: meson ninja libevdev pyudev pytest sphinx_rtd_theme black ruff
jobs:
build-and-dist:
runs-on: ubuntu-20.04
strategy:
matrix:
meson_args:
- ''
- '-Dbuildtype=plain'
- '-Dbuildtype=release'
- '-Ddocumentation=true'
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/pkginstall
with:
apt: $UBUNTU_DEP_BUILD $UBUNTU_DEP_TEST
pip: $PIP_PACKAGES
- name: meson test ${{matrix.meson_args}}
uses: ./.github/actions/meson
with:
meson_args: --prefix=$PWD/_instdir ${{matrix.meson_args}}
ninja_args: install
- name: check installation of data files
run: diff -u <(cd data/devices; ls *.device) <(cd _instdir/share/libratbag; ls *.device)
- name: ninja uninstall
uses: ./.github/actions/meson
with:
meson_args: --prefix=$PWD/_instdir
ninja_args: uninstall
- name: check if any files are left after uninstall
run: (test -d _instdir && tree _instdir && exit 1) || exit 0
# Capture all the meson logs, even if we failed
- uses: actions/upload-artifact@v3
if: ${{ always() }} # even if we fail
with:
name: meson test logs
path: |
builddir/meson-logs/testlog*.txt
builddir/meson-logs/meson-log.txt

View File

@@ -1,31 +0,0 @@
name: pages
on:
push:
branches:
- master
env:
UBUNTU_DEP_BUILD: gcc g++ pkg-config systemd libevdev-dev libglib2.0-dev libjson-glib-dev libsystemd-dev libudev-dev libunistring-dev python3-dev python3-evdev python3-pip swig python3-sphinx python3-sphinx-rtd-theme
PIP_PACKAGES: meson ninja
jobs:
deploy:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/pkginstall
with:
apt: $UBUNTU_DEP_BUILD
pip: $PIP_PACKAGES
- name: Build docs
uses: ./.github/actions/meson
with:
meson_args: -Ddocumentation=true -Dtests=false
meson_skip_test: yes
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./builddir/doc/html/
allow_empty_commit: true

View File

@@ -45,10 +45,6 @@ And to build or re-build after code-changes, run:
ninja -C builddir
sudo ninja -C builddir install
To remove/uninstall simply run:
sudo ninja -C builddir uninstall
Note: `builddir` is the build output directory and can be changed to any
other directory name. To set configure-time options, use e.g.
@@ -173,3 +169,5 @@ libratbag is licensed under the MIT license.
> Software is furnished to do so, subject to the following conditions: [...]
See the COPYING file for the full license information.
[![Build Status](https://circleci.com/gh/libratbag/libratbag.svg?style=shield&circle-token=d7c782e10d2d934b176da754f11b5105ea074f4a)](https://circleci.com/gh/libratbag/libratbag)

View File

@@ -1,12 +0,0 @@
[Device]
Name=ASUS ROG GX860 Buzzard Mouse
DeviceMatch=usb:0b05:1816
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=10
Leds=0
Dpis=2
DpiRange=100:8200@100

View File

@@ -1,14 +0,0 @@
# ASUS ROG Chakram, but corded
[Device]
Name=ASUS ROG Chakram Core
DeviceMatch=usb:0b05:1958
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=5
Leds=3
Dpis=4
DpiRange=100:16000@100
Quirks=DOUBLE_DPI;STRIX_PROFILE

View File

@@ -1,14 +0,0 @@
[Device]
Name=ASUS ROG Chakram X
DeviceMatch=usb:0b05:1a18
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=5
Leds=3
Dpis=4
Wireless=1
DpiRange=100:36000@100
Quirks=DOUBLE_DPI

View File

@@ -1,14 +0,0 @@
[Device]
Name=ASUS ROG Chakram
DeviceMatch=usb:0b05:18e3;usb:0b05:18e5
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=5
Leds=3
Dpis=4
Wireless=1
DpiRange=100:16000@100
Quirks=DOUBLE_DPI;STRIX_PROFILE

View File

@@ -1,13 +0,0 @@
[Device]
Name=ASUS ROG Gladius II Origin PNK LTD
DeviceMatch=usb:0b05:18cd
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=8
Leds=3
Dpis=2
DpiRange=100:12000@100
Quirks=DOUBLE_DPI

View File

@@ -1,14 +0,0 @@
# "ASUS ROG Gladius II" without "DPI target button"
[Device]
Name=ASUS ROG Gladius II Origin
DeviceMatch=usb:0b05:1877
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=8
Leds=3
Dpis=2
DpiRange=100:12000@100
Quirks=DOUBLE_DPI

View File

@@ -1,13 +0,0 @@
[Device]
Name=ASUS ROG Gladius II
DeviceMatch=usb:0b05:1845
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=9
Leds=3
Dpis=2
DpiRange=100:12000@100
ButtonMapping=f0;f1;f2;e4;e5;e6;e7;e8;e9

View File

@@ -1,13 +0,0 @@
[Device]
Name=ASUS ROG Harpe Wireless
DeviceMatch=usb:0b05:1a92
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=5
Buttons=5
Leds=1
Dpis=4
Wireless=1
DpiRange=100:36000@50

View File

@@ -1,13 +0,0 @@
[Device]
Name=ASUS ROG Keris Wireless AimPoint
DeviceMatch=usb:0b05:1a68
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=5
Buttons=7
Leds=1
Dpis=4
Wireless=1
DpiRange=100:36000@50

View File

@@ -1,14 +0,0 @@
[Device]
Name=ASUS ROG Keris Wireless
DeviceMatch=usb:0b05:195e;usb:0b05:1960
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=8
Leds=2
Dpis=4
Wireless=1
DpiRange=100:16000@100
Quirks=DOUBLE_DPI

View File

@@ -1,13 +0,0 @@
[Device]
Name=ASUS ROG Pugio
DeviceMatch=usb:0b05:1846
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=10
Leds=3
Dpis=2
DpiRange=100:7200@100
ButtonMapping=f0;f1;f2;e4;e5;e6;0;e8;e9;e1;e2

View File

@@ -1,14 +0,0 @@
[Device]
Name=ASUS ROG Spatha X
DeviceMatch=usb:0b05:1979;usb:0b05:1977
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=5
Buttons=14
Leds=3
Dpis=4
Wireless=1
DpiRange=100:19000@50
ButtonMapping=f0;f1;f2;e4;e5;e6;e8;e9;ea;eb;ec;ed;ee;ef

View File

@@ -1,14 +0,0 @@
[Device]
Name=ASUS ROG Strix Carry
DeviceMatch=usb:0b05:18b4
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=8
Leds=0
Dpis=2
Wireless=1
DpiRange=100:7200@100
Quirks=STRIX_PROFILE

View File

@@ -1,12 +0,0 @@
[Device]
Name=ASUS ROG Strix Impact
DeviceMatch=usb:0b05:1847
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=1
Buttons=6
Leds=1
Dpis=2
DpiRange=100:5000@100

View File

@@ -1,13 +0,0 @@
[Device]
Name=ASUS ROG Strix Impact II Wireless
DeviceMatch=usb:0b05:1947;usb:0b05:1949
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=8
Leds=3
Dpis=4
Wireless=1
DpiRange=100:16000@100

View File

@@ -1,12 +0,0 @@
[Device]
Name=ASUS ROG Strix Impact II
DeviceMatch=usb:0b05:18e1
DeviceType=mouse
Driver=asus
[Driver/asus]
Profiles=3
Buttons=8
Leds=3
Dpis=4
DpiRange=200:6200@100

227
data/devices/data-parse-test.py Executable file
View File

@@ -0,0 +1,227 @@
#!/usr/bin/env python3
#
# Copyright © 2017 Red Hat, Inc.
#
# 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 (including the next
# paragraph) 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.
#
# Device data verification script
#
import argparse
import configparser
import re
def assertIn(element, l):
if element not in l:
raise AssertionError('{} must be in {}'.format(element, l))
def assertNotIn(element, l):
if element in l:
raise AssertionError('{} must not be in {}'.format(element, l))
def check_match_str(string):
bustypes = ['usb', 'bluetooth']
matches = string.split(';')
for match in matches:
if not match: # empty string if trailing ;
continue
parts = match.split(':')
assert(len(parts) == 3)
assertIn(parts[0], bustypes)
vid = parts[1]
assert(vid == '{:04x}'.format(int(vid, 16)))
pid = parts[2]
assert(pid == '{:04x}'.format(int(pid, 16)))
def check_ledtypes_str(string):
permitted_types = ['logo', 'side', 'battery', 'dpi', 'switches']
types = string.split(';')
for t in types:
if not t: # emtpy string if trailing ;
continue
assertIn(t, permitted_types)
def check_section_device(section):
required_keys = ['Name', 'Driver', 'DeviceMatch']
permitted_keys = required_keys + ['LedTypes']
for key in section.keys():
assertIn(key, permitted_keys)
for r in required_keys:
assertIn(r, section)
try:
check_ledtypes_str(section['LedTypes'])
except KeyError:
pass
check_match_str(section['DeviceMatch'])
def check_dpi_range_str(string):
import re
m = re.search('^([0-9]+):([0-9]+)@([0-9.]+)$', string)
assert(m is not None)
min = int(m.group(1))
max = int(m.group(2))
steps = float(m.group(3))
assert(min >= 0 and min <= 400)
assert(max >= 2000 and max <= 12000)
assert(steps > 0 and steps <= 100)
if int(steps) == steps:
steps = int(steps)
assert(string == '{}:{}@{}'.format(min, max, steps))
def check_dpi_list_str(string):
entries = string.split(';')
# Remove possible empty last entry if trailing with a ;
if not entries[len(entries) - 1]:
entries = entries[:-1]
for idx, entry in enumerate(entries):
dpi = int(entry)
assert(dpi >= 0 and dpi <= 12000)
if idx > 0:
prev = entries[idx - 1]
prev_dpi = int(prev)
assert(dpi > prev_dpi)
def check_profile_type_str(string):
types = ['G9', 'G500', 'G700']
assertIn(string, types)
def check_section_hidpp10(section):
permitted = ['Profiles', 'ProfileType', 'DpiRange', 'DpiList', 'DeviceIndex', 'Leds']
for key in section.keys():
assertIn(key, permitted)
try:
nprofiles = int(section['Profiles'])
# 10 is arbitrarily chosen
assert(nprofiles > 0 and nprofiles < 10)
except KeyError:
pass
try:
index = int(section['DeviceIndex'], 16)
assert(index > 0 and index <= 0xff)
except KeyError:
pass
try:
check_dpi_range_str(section['DpiRange'])
assertNotIn('DpiList', section.keys())
except KeyError:
pass
try:
check_dpi_list_str(section['DpiList'])
assertNotIn('DpiRange', section.keys())
except KeyError:
pass
try:
check_profile_type_str(section['ProfileType'])
except KeyError:
pass
try:
leds = int(section['Leds'])
# 10 is arbitrarily chosen
assert(leds > 0 and leds < 10)
except KeyError:
pass
def check_section_hidpp20(section):
permitted = ['DeviceIndex', 'Leds', 'Quirk']
for key in section.keys():
assertIn(key, permitted)
try:
index = int(section['DeviceIndex'], 16)
assert(index > 0 and index <= 0xff)
except KeyError:
pass
def check_section_driver(driver, section):
if driver == 'hidpp10':
check_section_hidpp10(section)
elif driver == 'hidpp20':
check_section_hidpp20(section)
else:
assert('Unsupported driver section {}'.format(driver))
def validate_data_file_name(path):
# Matching any of the characters in the regular expression will throw an
# error. Currently only tests the square brackets [], parentheses, and curly
# braces.
illegal_characters_regex = '([\[\]\{\}\(\)])'
found_characters = re.findall(illegal_characters_regex, path)
if found_characters:
raise AssertionError("data file name '{}' contains illegal characters: '{}'".format(path, ''.join(found_characters)))
def parse_data_file(path):
print('Parsing file {}'.format(path))
data = configparser.ConfigParser(strict=True)
# Don't convert to lowercase
data.optionxform = lambda option: option
data.read(path)
assertIn('Device', data.sections())
check_section_device(data['Device'])
driver = data['Device']['Driver']
driver_section = 'Driver/{}'.format(driver)
permitted_sections = ['Device', driver_section]
for s in data.sections():
assertIn(s, permitted_sections)
if data.has_section(driver_section):
check_section_driver(driver, data[driver_section])
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Device data-file checker")
parser.add_argument('file', nargs='+')
args = parser.parse_args()
for path in args.file:
validate_data_file_name(path)
parse_data_file(path)

View File

@@ -15,8 +15,10 @@ DeviceMatch=usb:12ab:00f2
# The libratbag driver backend
Driver=hidpp10
# The type of this Device: either 'mouse', 'keyboard' or 'other'
DeviceType=mouse
# The types of the LEDs, in the indexed order they appear in, separated by a
# semicolon.
# Allowed values: logo, side, battery, dpi
LedTypes=logo;side
# Only one group of driver-specific properties is permitted and it must be
# [Driver/<drivername>]. It is a bug do have any other [Driver/foo] group in
@@ -50,60 +52,3 @@ Leds=1
# The HID++ 2.0 device index
# Should be unset unless required
# DeviceIndex=1
[Driver/asus]
# Number of profiles
Profiles=3
# Number of buttons
Buttons=8
# Number of LEDs
Leds=3
# Number of DPI presets
Dpis=2
# Set if device is wireless
# Wireless=1
# DPI range in format min:max@step
DpiRange=100:16000@100
# Button mapping
# ButtonMapping=f0;f1;f2;e4;e5;e6;e8;e9
# Device quirks
# Quirk=DOUBLE_DPI;STRIX_PROFILE
# Replace `FEED` in the group name with firmware version of the device.
# To find the right value, see the output of ratbagd and search a message like:
# "ratbag error: Device with firmware version FEED is not supported"
# Official software utility configuration file key: `PSD` (converted from
# ASCII codes).
[Driver/sinowealth/devices/FEED]
# Number of buttons.
# Official software utility configuration file key: `KM` (divided by 2).
# Default: 0.
Buttons=6
# Device name.
DeviceName=CoolVendor CoolMouse
# The order of LED pins on the mouse.
# Change this to `RBG` if LED colors are weird.
# Use `None` if there are no LEDs on the mouse.
# Permitted values: ("RGB", "RBG", "None").
LedType=RGB
# Number of profiles, called "modes" in official software utilities.
# If you are unsure what the "mode" thing is about, don't set this field.
# Official software utility configuration file key: `MDNUM` (divided by 3).
# Default: 1.
Profiles=1
# Sensor type.
# This field is unused, only used for book-keeping purposes.
# Official software utility configuration file key: `Sensor`.
SensorType=PMW3289

View File

@@ -0,0 +1,10 @@
[Device]
Name=Dream Machines DM5 Blink
DeviceMatch=usb:258a:0027
Driver=sinowealth
[Driver/sinowealth]
Buttons=8
Leds=1
LedType=RGB
DpiRange=100:16000@100

View File

@@ -24,7 +24,6 @@
import argparse
import os
import pathlib
import sys
import configparser
@@ -35,22 +34,22 @@ def parse_data_file(path):
data.optionxform = lambda option: option
data.read(path)
matches = data["Device"]["DeviceMatch"]
return matches.split(";")
matches = data['Device']['DeviceMatch']
return matches.split(';')
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Device duplicate match checker")
parser.add_argument("directory")
parser = argparse.ArgumentParser(description='Device duplicate match checker')
parser.add_argument('file', nargs='+')
args = parser.parse_args()
device_matches = {}
duplicates = False
for path in pathlib.Path(args.directory).glob("*.device"):
for path in args.file:
matches = parse_data_file(path)
fname = os.path.basename(path)
for m in matches:
if m in device_matches:
print(f"Duplicate DeviceMatch={m} in {fname} and {device_matches[m]}")
print('Duplicate DeviceMatch={} in {} and {}'.format(m, fname, device_matches[m]))
duplicates = True
device_matches[m] = fname

View File

@@ -2,4 +2,3 @@
Name=Etekcity Scroll Alpha
DeviceMatch=usb:1ea7:4011
Driver=etekcity
DeviceType=mouse

View File

@@ -1,11 +1,9 @@
[Device]
Name=Glorious Model D
DeviceMatch=usb:258a:0033
DeviceType=mouse
Driver=sinowealth
[Driver/sinowealth/devices/V102]
[Driver/sinowealth]
Buttons=6
DeviceName=Glorious Model D
LedType=RBG
SensorType=PMW3360
Leds=2
DpiRange=100:12000@100

View File

@@ -1,11 +1,10 @@
[Device]
Name=Glorious Model O/O-
Name=Glorious Model O
DeviceMatch=usb:258a:0036
DeviceType=mouse
Driver=sinowealth
[Driver/sinowealth/devices/V103]
[Driver/sinowealth]
Buttons=6
DeviceName=Glorious Model O/O- (updated firmware)
Leds=2
LedType=RBG
SensorType=PMW3360
DpiRange=100:12000@100

View File

@@ -3,4 +3,3 @@
Name=G.Skill MX-780
DeviceMatch=usb:28da:3101
Driver=gskill
DeviceType=mouse

View File

@@ -3,4 +3,3 @@
Name=Logitech M325
DeviceMatch=usb:046d:400a
Driver=hidpp20
DeviceType=mouse

View File

@@ -1,6 +0,0 @@
# Logitech M500s
[Device]
Name=Logitech M500s
DeviceMatch=usb:046d:c093
DeviceType=mouse
Driver=hidpp20

View File

@@ -1,6 +0,0 @@
# Logitech M545
[Device]
Name=Logitech M545
DeviceMatch=usb:046d:4052
DeviceType=mouse
Driver=hidpp20

View File

@@ -3,4 +3,3 @@
Name=Logitech M570
DeviceMatch=usb:046d:1028
Driver=hidpp10
DeviceType=mouse

View File

@@ -3,4 +3,3 @@
Name=Logitech M585/M590
DeviceMatch=usb:046d:406b;bluetooth:046d:b01b
Driver=hidpp20
DeviceType=mouse

View File

@@ -3,4 +3,3 @@
Name=Logitech M705
DeviceMatch=usb:046d:101b
Driver=hidpp10
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech M720
DeviceMatch=usb:046d:405e;bluetooth:046d:b015
Driver=hidpp20
DeviceType=mouse

View File

@@ -1,6 +0,0 @@
# Logitech MX Anywhere 3
[Device]
Name=Logitech MX Anywhere 3
DeviceMatch=bluetooth:046d:b025;usb:046d:4090
DeviceType=mouse
Driver=hidpp20

View File

@@ -1,6 +0,0 @@
# Logitech MX Anywhere 3S
[Device]
Name=Logitech MX Anywhere 3S
DeviceMatch=bluetooth:046d:b037
DeviceType=mouse
Driver=hidpp20

View File

@@ -1,5 +1,4 @@
[Device]
Name=Logitech MX Anywhere 2
DeviceMatch=usb:046d:404a;usb:046d:4072;usb:046d:4063;bluetooth:046d:b013;bluetooth:046d:b018;bluetooth:046d:b01f
DeviceMatch=usb:046d:404a;bluetooth:046d:b013;bluetooth:046d:b018;bluetooth:046d:b01f
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech MX Anywhere 2S
DeviceMatch=bluetooth:046d:b01a;usb:046d:406a
Driver=hidpp20
DeviceType=mouse

View File

@@ -1,6 +0,0 @@
# Logitech MX Anywhere 3B
[Device]
Driver=hidpp20
Name=Logitech MX Anywhere 3B
DeviceType=mouse
DeviceMatch=bluetooth:046d:b02d

View File

@@ -3,4 +3,3 @@
Name=Logitech MX Ergo
DeviceMatch=bluetooth:046d:b01d;usb:046d:406f
Driver=hidpp20
DeviceType=mouse

View File

@@ -3,4 +3,3 @@
Name=Logitech MX Master 2S
DeviceMatch=bluetooth:046d:b019;usb:046d:4069
Driver=hidpp20
DeviceType=mouse

View File

@@ -3,4 +3,3 @@
Name=Logitech MX Master 3
DeviceMatch=bluetooth:046d:b023;usb:046d:4082
Driver=hidpp20
DeviceType=mouse

View File

@@ -1,5 +0,0 @@
[Device]
DeviceMatch=bluetooth:046d:b035
DeviceType=mouse
Driver=hidpp20
Name=Logitech MX Master 3S for Business

View File

@@ -1,5 +0,0 @@
[Device]
DeviceMatch=bluetooth:046d:b034
DeviceType=mouse
Driver=hidpp20
Name=Logitech MX Master 3S

View File

@@ -3,4 +3,3 @@
Name=Logitech MX Master
DeviceMatch=usb:046d:4041;bluetooth:046d:b012;usb:046d:4060;bluetooth:046d:b017;bluetooth:046d:b01e;usb:046d:4071
Driver=hidpp20
DeviceType=mouse

View File

@@ -1,5 +1,4 @@
[Device]
Name=Logitech MX Vertical
DeviceMatch=bluetooth:046d:b020;usb:046d:407b;usb:046d:c08a
DeviceMatch=bluetooth:046d:b020;usb:046d:407b
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=MX518
DeviceMatch=usb:046d:c08e
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech Marathon M705
DeviceMatch=usb:046d:406d
Driver=hidpp20
DeviceType=mouse

View File

@@ -3,4 +3,3 @@
Name=Logitech T650
DeviceMatch=usb:046d:4101
Driver=hidpp20
DeviceType=mouse

View File

@@ -3,4 +3,3 @@
Name=Logitech Wireless Touchpad
DeviceMatch=usb:046d:4011
Driver=hidpp20
DeviceType=mouse

View File

@@ -1,8 +1,8 @@
[Device]
Name=Logitech G Powerplay
DeviceMatch=usb:046d:405f
LedTypes=logo
Driver=hidpp20
DeviceType=other
[Driver/hidpp20]
DeviceIndex=7

View File

@@ -1,5 +0,0 @@
[Device]
DeviceMatch=usb:046d:c339
DeviceType=keyboard
Driver=hidpp20
Name=Logitech G PRO Keyboard

View File

@@ -1,8 +1,8 @@
[Device]
Name=Logitech G Pro Wireless
DeviceMatch=usb:046d:4079;usb:046d:c088
LedTypes=logo;battery;dpi;
Driver=hidpp20
DeviceType=mouse
[Driver/hidpp20]
DeviceIndex=1

View File

@@ -1,5 +0,0 @@
[Device]
Name=Logitech G Pro X Wireless Superlight
DeviceMatch=usb:046d:4093;usb:046d:c094
DeviceType=mouse
Driver=hidpp20

View File

@@ -2,4 +2,4 @@
Name=Logitech Gaming Mouse G Pro
DeviceMatch=usb:046d:c085;usb:046d:c08c
Driver=hidpp20
DeviceType=mouse
LedTypes=logo;side

View File

@@ -1,6 +1,6 @@
# G102, G103 and G203 (USB)
[Device]
Name=Logitech Gaming Mouse G102/G103/G203
DeviceMatch=usb:046d:c084;usb:046d:c092;usb:046d:c09d
DeviceMatch=usb:046d:c084;usb:046d:c092
Driver=hidpp20
DeviceType=mouse
LedTypes=logo;side;

View File

@@ -3,4 +3,3 @@
Name=Logitech G300
DeviceMatch=usb:046d:c246
Driver=logitech_g300
DeviceType=mouse

View File

@@ -3,4 +3,4 @@
Name=Logitech Gaming Mouse G302
DeviceMatch=usb:046d:c07f
Driver=hidpp20
DeviceType=mouse
LedTypes=logo;side;

View File

@@ -1,5 +0,0 @@
[Device]
Name=Logitech G303 Shroud Edition
DeviceMatch=usb:046d:c097
DeviceType=mouse
Driver=hidpp20

View File

@@ -3,4 +3,4 @@
Name=Logitech Gaming Mouse G303
DeviceMatch=usb:046d:c080
Driver=hidpp20
DeviceType=mouse
LedTypes=logo;side;

View File

@@ -2,7 +2,6 @@
Name=Logitech Gaming Mouse G305
DeviceMatch=usb:046d:4074
Driver=hidpp20
DeviceType=mouse
[Driver/hidpp20]
Leds=0

View File

@@ -2,5 +2,5 @@
[Device]
Name=Logitech G402 Gaming Mouse
DeviceMatch=usb:046d:c07e
LedTypes=logo
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech G403 Hero
DeviceMatch=usb:046d:c08f
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech G403 Wireless
DeviceMatch=usb:046d:405d;usb:046d:c082
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech G403
DeviceMatch=usb:046d:c083
Driver=hidpp20
DeviceType=mouse

View File

@@ -1,5 +0,0 @@
[Device]
DeviceMatch=usb:046d:c33a
DeviceType=keyboard
Driver=hidpp20
Name=Logitech G413

View File

@@ -3,7 +3,6 @@
Name=Logitech G5
DeviceMatch=usb:046d:c049
Driver=hidpp10
DeviceType=mouse
[Driver/hidpp10]
DpiList=400;800;1600;2000

View File

@@ -2,7 +2,6 @@
Name=G5
DeviceMatch=usb:046d:c041
Driver=hidpp10
DeviceType=mouse
[Driver/hidpp10]
DpiList=400;800;1600;2000

View File

@@ -2,7 +2,6 @@
Name=Logitech G500
DeviceMatch=usb:046d:c068
Driver=hidpp10
DeviceType=mouse
[Driver/hidpp10]
DpiRange=0:5700@23.53

View File

@@ -2,7 +2,6 @@
Name=Logitech G500s
DeviceMatch=usb:046d:c24e
Driver=hidpp10
DeviceType=mouse
[Driver/hidpp10]
DpiRange=0:8200@50

View File

@@ -2,4 +2,3 @@
Name=Logitech G502 Hero Wireless
DeviceMatch=usb:046d:407f;usb:046d:c08d
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech G502 Hero
DeviceMatch=usb:046d:c08b
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech G502 Proteus Core
DeviceMatch=usb:046d:c07d
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech G502 Proteus Spectrum
DeviceMatch=usb:046d:c332
Driver=hidpp20
DeviceType=mouse

View File

@@ -1,5 +0,0 @@
[Device]
Name=Logitech G502 X Wireless
DeviceMatch=usb:046d:c098
DeviceType=mouse
Driver=hidpp20

View File

@@ -1,5 +0,0 @@
[Device]
Name=Logitech G502 X
DeviceMatch=usb:046d:c099
DeviceType=mouse
Driver=hidpp20

View File

@@ -1,5 +1,5 @@
[Device]
Name=Logitech G513
DeviceMatch=usb:046d:c33c
LedTypes=switches
Driver=hidpp20
DeviceType=keyboard

View File

@@ -3,4 +3,3 @@
Name=Logitech G600
DeviceMatch=usb:046d:c24a
Driver=logitech_g600
DeviceType=mouse

View File

@@ -3,7 +3,6 @@
Name=Logitech G602
DeviceMatch=usb:046d:402c
Driver=hidpp20
DeviceType=mouse
[Driver/hidpp20]
DeviceIndex=1

View File

@@ -3,4 +3,3 @@
Name=Logitech G603
DeviceMatch=usb:046d:406c;bluetooth:046d:b01c
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech G604
DeviceMatch=usb:046d:4085;bluetooth:046d:b024
Driver=hidpp20
DeviceType=mouse

View File

@@ -1,8 +0,0 @@
[Device]
Name=Logitech G635
DeviceMatch=usb:046d:0a89
DeviceType=mouse
Driver=hidpp20
[Driver/hidpp20]
Buttons=0

View File

@@ -4,7 +4,6 @@
Name=Logitech G7
DeviceMatch=usb:046d:c51a
Driver=hidpp10
DeviceType=mouse
[Driver/hidpp10]
Profiles=1

View File

@@ -4,7 +4,6 @@
Name=Logitech G700
DeviceMatch=usb:046d:c531
Driver=hidpp10
DeviceType=mouse
[Driver/hidpp10]
DpiRange=0:5700@23.53

View File

@@ -4,7 +4,6 @@
Name=Logitech G700
DeviceMatch=usb:046d:c06b
Driver=hidpp10
DeviceType=mouse
[Driver/hidpp10]
DpiRange=0:5700@23.53

View File

@@ -4,7 +4,6 @@
Name=Logitech G700s
DeviceMatch=usb:046d:c07c
Driver=hidpp10
DeviceType=mouse
[Driver/hidpp10]
DpiRange=0:8200@50

View File

@@ -2,4 +2,4 @@
Name=Logitech G703 Hero
DeviceMatch=usb:046d:4086;usb:046d:c090
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,4 @@
Name=Logitech G703
DeviceMatch=usb:046d:c087;usb:046d:4070
Driver=hidpp20
DeviceType=mouse

View File

@@ -1,8 +0,0 @@
[Device]
Name=Logitech G733 Gaming Headset
DeviceMatch=usb:046d:0ab5;usb:046d:0afe
DeviceType=mouse
Driver=hidpp20
[Driver/hidpp20]
Buttons=0

View File

@@ -1,5 +1,5 @@
[Device]
Name=Logitech G815
DeviceMatch=usb:046d:c33f
LedTypes=logo;switches
Driver=hidpp20
DeviceType=keyboard

View File

@@ -3,8 +3,8 @@
[Device]
Name=Logitech G9
DeviceMatch=usb:046d:c048
LedTypes=dpi
Driver=hidpp10
DeviceType=mouse
[Driver/hidpp10]
DpiList=200;400;600;800;1000;1200;1400;1600;1800;2000;2200;2400;2600;2800;3000;3200

View File

@@ -3,4 +3,3 @@
Name=Logitech G900
DeviceMatch=usb:046d:c081;usb:046d:4053
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech G903 Hero
DeviceMatch=usb:046d:c091;usb:046d:4087
Driver=hidpp20
DeviceType=mouse

View File

@@ -2,4 +2,3 @@
Name=Logitech G903
DeviceMatch=usb:046d:c086;usb:046d:4067
Driver=hidpp20
DeviceType=mouse

Some files were not shown because too many files have changed in this diff Show More