forked from drath/libratbag
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 87fe2e31c3 | |||
| ff7ec2a1e4 | |||
| 96c7310a6d | |||
|
|
8235b5bb60 | ||
|
|
b8d4d3ca1f | ||
|
|
e07d72e2a7 | ||
|
|
d93a8bc474 | ||
|
|
1f4efda955 | ||
|
|
03afbe49f3 | ||
|
|
f9d1574841 | ||
|
|
b0f2779270 | ||
|
|
43f76eee67 | ||
|
|
54edb7e0a2 | ||
|
|
2fb9a701e8 | ||
|
|
805e7fb77f | ||
|
|
1e20248b6d | ||
|
|
d7bbed2eb1 | ||
|
|
874c01732a | ||
|
|
c5214d2633 | ||
|
|
b61da30205 | ||
|
|
e4184c2227 | ||
|
|
78d1124c3e | ||
|
|
65d07ae4d1 | ||
|
|
ca94a8a111 | ||
|
|
7bdca904f5 | ||
|
|
ad6540e39b | ||
|
|
df3c73e958 | ||
|
|
dcc5def3d6 |
12
.copr/Makefile
Normal file
12
.copr/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
outdir ?= .
|
||||
spec ?= libratbag.spec
|
||||
|
||||
srpm:
|
||||
dnf -y install git-core rpm-build
|
||||
git archive --format=tar.gz --prefix=libratbag-snapshot/ \
|
||||
-o $(outdir)/libratbag-snapshot.tar.gz HEAD
|
||||
rpmbuild -bs $(spec) \
|
||||
--define "_sourcedir $(outdir)" \
|
||||
--define "_srcrpmdir $(outdir)" \
|
||||
--define "gitdate $$(date +%Y%m%d)" \
|
||||
--define "shortcommit $$(git rev-parse --short=7 HEAD)"
|
||||
259
.copr/libratbag.spec
Normal file
259
.copr/libratbag.spec
Normal file
@@ -0,0 +1,259 @@
|
||||
%global udevdir %(pkg-config --variable=udevdir udev)
|
||||
%global commit <full 40-char hash>
|
||||
%global shortcommit %(c=%{commit}; echo ${c:0:7})
|
||||
%global gitdate %(date +%%Y%%m%%d)
|
||||
|
||||
Name: libratbag
|
||||
Version: 0.18^%{gitdate}git%{shortcommit}
|
||||
Release: 1%{?dist}
|
||||
Summary: Programmable input device library
|
||||
License: MIT
|
||||
URL: https://github.com/libratbag/libratbag
|
||||
Source0: libratbag-snapshot.tar.gz
|
||||
|
||||
BuildRequires: git gcc gcc-c++
|
||||
BuildRequires: meson pkgconfig
|
||||
BuildRequires: libevdev-devel
|
||||
BuildRequires: libudev-devel
|
||||
BuildRequires: pkgconfig(udev) pkgconfig(glib-2.0) pkgconfig(json-glib-1.0)
|
||||
BuildRequires: check-devel
|
||||
%ifarch %{valgrind_arches}
|
||||
BuildRequires: valgrind
|
||||
%endif
|
||||
BuildRequires: systemd
|
||||
BuildRequires: python3 python3-devel python3-gobject
|
||||
BuildRequires: python3-lxml python3-evdev swig
|
||||
BuildRequires: libunistring-devel
|
||||
|
||||
%description
|
||||
libratbag is a library that allows to configure programmable
|
||||
mice.
|
||||
|
||||
%package ratbagd
|
||||
Summary: DBus daemon to access programmable input devices
|
||||
Obsoletes: libratbag < 0.9.900
|
||||
Requires: python3-evdev python3-gobject
|
||||
|
||||
%description ratbagd
|
||||
The ratbagd package contains a dbus daemon to access and configure
|
||||
programmable input devices, primarily gaming mice.
|
||||
|
||||
%package -n liblur
|
||||
Summary: Logitech Unifying Receiver library
|
||||
|
||||
%description -n liblur
|
||||
The liblur package contains libraries and tools to access and
|
||||
configure the Logitech Unifying Receivers. The functionality
|
||||
are mainly listing, pairing and un-pairing Logitech devices
|
||||
attached to a receiver.
|
||||
|
||||
%package -n liblur-devel
|
||||
Summary: Development files for liblur
|
||||
Requires: liblur%{?_isa} = %{version}-%{release}
|
||||
|
||||
%description -n liblur-devel
|
||||
The liblur-devel package contains libraries and header files for
|
||||
developing applications that use liblur.
|
||||
|
||||
%prep
|
||||
%autosetup -n libratbag-snapshot
|
||||
|
||||
# hack until rhbz#1409661 gets fixed
|
||||
%{!?__global_cxxflags: %define __global_cxxflags %{optflags}}
|
||||
|
||||
%build
|
||||
# s390x builds sometimes fails during the tests, let just disable those
|
||||
%ifarch s390x
|
||||
%meson -Dudev-dir=%{udevdir} -Ddocumentation=false -Dtests=false
|
||||
%else
|
||||
%meson -Dudev-dir=%{udevdir} -Ddocumentation=false
|
||||
%endif
|
||||
%meson_build
|
||||
|
||||
%check
|
||||
%meson_test
|
||||
|
||||
%install
|
||||
%meson_install
|
||||
|
||||
|
||||
%ldconfig_scriptlets -n liblur
|
||||
|
||||
%files ratbagd
|
||||
%license COPYING
|
||||
%{_bindir}/ratbagctl
|
||||
%{_bindir}/ratbagd
|
||||
%dir %{_datadir}/libratbag
|
||||
%{_datadir}/libratbag/*.device
|
||||
%{_mandir}/man1/ratbagctl.1*
|
||||
%{_mandir}/man8/ratbagd.8*
|
||||
%{_datadir}/dbus-1/system.d/org.freedesktop.ratbag1.conf
|
||||
%{_datadir}/dbus-1/system-services/org.freedesktop.ratbag1.service
|
||||
%{_unitdir}/ratbagd.service
|
||||
|
||||
%files -n liblur
|
||||
%license COPYING
|
||||
%{_libdir}/liblur.so.*
|
||||
%{_bindir}/lur-command
|
||||
%{_mandir}/man1/lur-command.1*
|
||||
|
||||
%files -n liblur-devel
|
||||
%{_includedir}/liblur.h
|
||||
%{_libdir}/liblur.so
|
||||
%{_libdir}/pkgconfig/liblur.pc
|
||||
|
||||
%changelog
|
||||
%changelog
|
||||
* Thu Nov 05 2026 Drath <you@example.com> - 0.18^20261105git<shortcommit>-1
|
||||
- Git snapshot with G502 X Plus device file
|
||||
|
||||
* Thu Jul 16 2026 Fedora Release Engineering <releng@fedoraproject.org> - 0.18-6
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild
|
||||
|
||||
* Fri Jan 16 2026 Fedora Release Engineering <releng@fedoraproject.org> - 0.18-5
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild
|
||||
|
||||
* Thu Jul 24 2025 Fedora Release Engineering <releng@fedoraproject.org> - 0.18-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
|
||||
|
||||
* Thu Mar 06 2025 David Abdurachmanov <davidlt@rivosinc.com> 0.18-3
|
||||
- Properly check valgrind arches
|
||||
|
||||
* Mon Jan 20 2025 Fedora Release Engineering <releng@fedoraproject.org> - 0.18-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
|
||||
|
||||
* Fri Jan 03 2025 Peter Hutterer <peter.hutterer@redhat.com> - 0.18-1
|
||||
- libratbag 0.18
|
||||
- Revert upstream change to /sbin
|
||||
|
||||
* Thu Jul 18 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.17-7
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild
|
||||
|
||||
* Wed Jun 26 2024 Marcin Juszkiewicz <marcin@juszkiewicz.com.pl> - 0.17-6
|
||||
- Backport remove of imp Python module to fix FTFBS on F40.
|
||||
|
||||
* Thu Jan 25 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.17-5
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
|
||||
|
||||
* Sun Jan 21 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.17-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
|
||||
|
||||
* Fri Sep 08 2023 Peter Hutterer <peter.hutterer@redhat.com>
|
||||
- SPDX migration: license is MIT, we're good
|
||||
|
||||
* Thu Jul 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.17-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
|
||||
|
||||
* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.17-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
|
||||
|
||||
* Wed Nov 30 2022 Peter Hutterer <peter.hutterer@redhat.com> - 0.17-1
|
||||
- libratbag 0.17
|
||||
|
||||
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.16-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
|
||||
|
||||
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.16-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
|
||||
|
||||
* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.16-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
|
||||
|
||||
* Fri Jun 25 2021 Peter Hutterer <peter.hutterer@redhat.com> 0.16-1
|
||||
- libratbag 0.16
|
||||
|
||||
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.15-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
|
||||
|
||||
* Mon Sep 28 2020 Peter Hutterer <peter.hutterer@redhat.com> 0.15-1
|
||||
- libratbag 0.15
|
||||
|
||||
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0.14-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
|
||||
|
||||
* Thu May 21 2020 Peter Hutterer <peter.hutterer@redhat.com> 0.14-1
|
||||
- libratbag 0.14
|
||||
|
||||
* Tue Feb 11 2020 Peter Hutterer <peter.hutterer@redhat.com> 0.13-1
|
||||
- libratbag 0.13
|
||||
|
||||
* Wed Jan 29 2020 Peter Hutterer <peter.hutterer@redhat.com> 0.12-1
|
||||
- libratbag 0.12
|
||||
|
||||
* Tue Nov 05 2019 Peter Hutterer <peter.hutterer@redhat.com> 0.11-1
|
||||
- libratbag 0.11
|
||||
|
||||
* Mon Sep 16 2019 Peter Hutterer <peter.hutterer@redhat.com> 0.10-2
|
||||
- Add missing Requires for ratbagctl
|
||||
|
||||
* Fri Aug 02 2019 Peter Hutterer <peter.hutterer@redhat.com> 0.10-1
|
||||
- libratbag 0.10
|
||||
|
||||
* Fri Jul 26 2019 Peter Hutterer <peter.hutterer@redhat.com> 0.9.906-1
|
||||
- libratbag 0.9.906
|
||||
|
||||
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.905-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
|
||||
|
||||
* Wed Jul 17 2019 Peter Hutterer <peter.hutterer@redhat.com> 0.9.905-3
|
||||
- Use python3-embed as dependency where available. Fixes FTBFS with python
|
||||
3.8 (#1718290)
|
||||
|
||||
* Thu Feb 28 2019 Peter Hutterer <peter.hutterer@redhat.com> 0.9.905-2
|
||||
- Fix meson options
|
||||
|
||||
* Thu Feb 28 2019 Peter Hutterer <peter.hutterer@redhat.com> 0.9.905-1
|
||||
- libratbag 0.9.905
|
||||
|
||||
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.904-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
|
||||
|
||||
* Thu Jan 24 2019 Peter Hutterer <peter.hutterer@redhat.com> 0.9.904-1
|
||||
- libratbag 0.9.904
|
||||
|
||||
* Wed Sep 05 2018 Peter Hutterer <peter.hutterer@redhat.com> 0.9.903-1
|
||||
- libratbag 0.9.903
|
||||
|
||||
* Fri Jul 20 2018 Peter Hutterer <peter.hutterer@redhat.com> 0.9.902-4
|
||||
- Add gcc to BuildRequires (#1604654)
|
||||
- Change to use the correct -Ddocumentation=false
|
||||
|
||||
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.902-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
|
||||
|
||||
* Tue Jun 19 2018 Miro Hrončok <mhroncok@redhat.com> - 0.9.902-2
|
||||
- Rebuilt for Python 3.7
|
||||
|
||||
* Mon May 21 2018 Peter Hutterer <peter.hutterer@redhat.com> 0.9.902-1
|
||||
- libratbag 0.9.902
|
||||
|
||||
* Fri Mar 23 2018 Peter Hutterer <peter.hutterer@redhat.com> 0.9.901-1
|
||||
- libratbag 0.9.901
|
||||
|
||||
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.9-5
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
||||
|
||||
* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.9-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
|
||||
|
||||
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.9-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
|
||||
|
||||
* Wed Jun 07 2017 Benjamin Tissoires <benjamin.tissoires@redhat.com> 0.9-2
|
||||
- disable tests on s390x because they seem to fail without good reasons
|
||||
|
||||
* Tue Jun 06 2017 Benjamin Tissoires <benjamin.tissoires@redhat.com> 0.9-1
|
||||
- libratbag v0.9
|
||||
- new manpage for lur-command
|
||||
|
||||
* Tue May 09 2017 Benjamin Tissoires <benjamin.tissoires@redhat.com> 0.8-1
|
||||
- libratbag v0.8
|
||||
|
||||
* Tue May 09 2017 Benjamin Tissoires <benjamin.tissoires@redhat.com> 0.7-3
|
||||
- add a hack for F24 and F25 to compile
|
||||
|
||||
* Fri May 05 2017 Benjamin Tissoires <benjamin.tissoires@redhat.com> 0.7-2
|
||||
- Remove the generation of the documentation, we don't ship it
|
||||
|
||||
* Thu May 04 2017 Benjamin Tissoires <benjamin.tissoires@redhat.com> 0.7-1
|
||||
- Initial Fedora packaging (rhbz#1309703)
|
||||
24
.github/workflows/main.yml
vendored
24
.github/workflows/main.yml
vendored
@@ -8,20 +8,24 @@ env:
|
||||
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
|
||||
PIP_PACKAGES: meson ninja libevdev pyudev pytest sphinx_rtd_theme black==25.12.0 ruff==0.15.12
|
||||
|
||||
jobs:
|
||||
build-and-dist:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
meson_args:
|
||||
- ''
|
||||
- '-Dbuildtype=plain'
|
||||
- '-Dbuildtype=release'
|
||||
- '-Ddocumentation=true'
|
||||
include:
|
||||
- name: default
|
||||
meson_args: ''
|
||||
- name: plain
|
||||
meson_args: '-Dbuildtype=plain'
|
||||
- name: release
|
||||
meson_args: '-Dbuildtype=release'
|
||||
- name: documentation
|
||||
meson_args: '-Ddocumentation=true'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/pkginstall
|
||||
with:
|
||||
apt: $UBUNTU_DEP_BUILD $UBUNTU_DEP_TEST
|
||||
@@ -41,10 +45,10 @@ jobs:
|
||||
- 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
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ always() }} # even if we fail
|
||||
with:
|
||||
name: meson test logs
|
||||
name: 'meson test logs ${{ matrix.name }}'
|
||||
path: |
|
||||
builddir/meson-logs/testlog*.txt
|
||||
builddir/meson-logs/meson-log.txt
|
||||
|
||||
2
.github/workflows/pages.yml
vendored
2
.github/workflows/pages.yml
vendored
@@ -11,7 +11,7 @@ env:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/pkginstall
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
[Device]
|
||||
Name=ASUS ROG Chakram X
|
||||
DeviceMatch=usb:0b05:1a18
|
||||
DeviceMatch=usb:0b05:1a18;usb:0b05:1a1a
|
||||
DeviceType=mouse
|
||||
Driver=asus
|
||||
|
||||
[Driver/asus]
|
||||
Profiles=3
|
||||
Buttons=5
|
||||
Profiles=5
|
||||
Buttons=14
|
||||
Leds=3
|
||||
Dpis=4
|
||||
Wireless=1
|
||||
DpiRange=100:36000@100
|
||||
Quirks=DOUBLE_DPI
|
||||
Quirks=DOUBLE_DPI;RAW_BRIGHTNESS;SEPARATE_XY_DPI;SEPARATE_LEDS;BUTTONS_SECONDARY
|
||||
ButtonMapping=f0;f1;f2;0;0;e6;e8;e9;d0;d1;d2;d3
|
||||
ButtonMappingSecondary=0;0;ea;eb;ec;ed
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Device]
|
||||
Name=ASUS ROG Keris Wireless AimPoint
|
||||
DeviceMatch=usb:0b05:1a68
|
||||
DeviceMatch=usb:0b05:1a66;usb:0b05:1a68
|
||||
DeviceType=mouse
|
||||
Driver=asus
|
||||
|
||||
|
||||
13
data/devices/asus-rog-keris.device
Normal file
13
data/devices/asus-rog-keris.device
Normal file
@@ -0,0 +1,13 @@
|
||||
[Device]
|
||||
Name=ASUS ROG Keris
|
||||
DeviceMatch=usb:0b05:195c
|
||||
DeviceType=mouse
|
||||
Driver=asus
|
||||
|
||||
[Driver/asus]
|
||||
Profiles=3
|
||||
Buttons=8
|
||||
Leds=2
|
||||
Dpis=4
|
||||
DpiRange=100:16000@100
|
||||
Quirks=DOUBLE_DPI
|
||||
12
data/devices/asus-rog-omni-receiver.device
Normal file
12
data/devices/asus-rog-omni-receiver.device
Normal file
@@ -0,0 +1,12 @@
|
||||
[Device]
|
||||
Name=ASUS ROG Omni Receiver
|
||||
DeviceMatch=usb:0b05:1ace
|
||||
DeviceType=mouse
|
||||
Driver=asus
|
||||
|
||||
# The Omni receiver is a shared USB device for multiple mice (all of them
|
||||
# enumerate with the same usb id), so the actual model is identified during
|
||||
# probe and resolved to the model-specific .device data. This file only
|
||||
# exists to get the asus driver probed on the receiver's hidraw nodes.
|
||||
[Driver/asus]
|
||||
Quirks=OMNI_RECEIVER
|
||||
@@ -11,3 +11,4 @@ Leds=3
|
||||
Dpis=2
|
||||
DpiRange=100:7200@100
|
||||
ButtonMapping=f0;f1;f2;e4;e5;e6;0;e8;e9;e1;e2
|
||||
LedModes=ON;BREATHING;ON;CYCLE
|
||||
|
||||
19
data/devices/asus-rog-strix-impact3-wireless.device
Normal file
19
data/devices/asus-rog-strix-impact3-wireless.device
Normal file
@@ -0,0 +1,19 @@
|
||||
[Device]
|
||||
Name=ASUS ROG Strix Impact III Wireless
|
||||
DeviceMatch=usb:0b05:1ad7
|
||||
DeviceType=mouse
|
||||
Driver=asus
|
||||
|
||||
# This device enumerates as usb 0b05:1ad7 behind the ASUS Omni receiver
|
||||
# (0b05:1ace). The usb id is resolved during probe: the receiver is
|
||||
# identified first (asus-rog-omni-receiver.device) and the serial number
|
||||
# signature prefix (OmniSignature) is matched against this file.
|
||||
[Driver/asus]
|
||||
Profiles=5
|
||||
Buttons=8
|
||||
Leds=1
|
||||
Dpis=4
|
||||
Wireless=1
|
||||
DpiRange=100:36000@50
|
||||
Quirks=OMNI_RECEIVER;SEPARATE_XY_DPI;LED_V2;SETTINGS_V2
|
||||
OmniSignature=20
|
||||
13
data/devices/asus-rog-strix-impact3.device
Normal file
13
data/devices/asus-rog-strix-impact3.device
Normal file
@@ -0,0 +1,13 @@
|
||||
[Device]
|
||||
Name=ASUS ROG Strix Impact III
|
||||
DeviceMatch=usb:0b05:1a88
|
||||
DeviceType=mouse
|
||||
Driver=asus
|
||||
|
||||
[Driver/asus]
|
||||
Profiles=3
|
||||
Buttons=8
|
||||
Leds=2
|
||||
Dpis=4
|
||||
DpiRange=100:12000@50
|
||||
Quirks=LED_V2;SETTINGS_V2
|
||||
12
data/devices/asus-tuf-gaming-m3-gen-ii.device
Normal file
12
data/devices/asus-tuf-gaming-m3-gen-ii.device
Normal file
@@ -0,0 +1,12 @@
|
||||
[Device]
|
||||
Name=ASUSTeK TUF GAMING M3 GEN II
|
||||
DeviceMatch=usb:0b05:1a9b
|
||||
DeviceType=mouse
|
||||
Driver=asus
|
||||
|
||||
[Driver/asus]
|
||||
Profiles=3
|
||||
Buttons=8
|
||||
Leds=1
|
||||
Dpis=4
|
||||
DpiRange=100:8000@100
|
||||
12
data/devices/asus-tuf-gaming-m4-air.device
Normal file
12
data/devices/asus-tuf-gaming-m4-air.device
Normal file
@@ -0,0 +1,12 @@
|
||||
[Device]
|
||||
Name=ASUS TUF GAMING M4 AIR
|
||||
DeviceMatch=usb:0b05:1a03
|
||||
DeviceType=mouse
|
||||
Driver=asus
|
||||
|
||||
[Driver/asus]
|
||||
Profiles=3
|
||||
Buttons=6
|
||||
Leds=0
|
||||
Dpis=4
|
||||
DpiRange=100:16000@100
|
||||
14
data/devices/asus-tuf-gaming-mini-wl-miku.device
Normal file
14
data/devices/asus-tuf-gaming-mini-wl-miku.device
Normal file
@@ -0,0 +1,14 @@
|
||||
[Device]
|
||||
Name=ASUS TUF GAMING MINI WL MOUSE MIKU
|
||||
DeviceMatch=usb:0b05:1c56;usb:0b05:1c57
|
||||
DeviceType=mouse
|
||||
Driver=asus
|
||||
|
||||
[Driver/asus]
|
||||
Profiles=5
|
||||
Buttons=8
|
||||
Leds=1
|
||||
Dpis=4
|
||||
Wireless=1
|
||||
DpiRange=100:12000@100
|
||||
Quirks=SEPARATE_XY_DPI;RAW_BRIGHTNESS
|
||||
11
data/devices/glorious-model-o-eternal.device
Normal file
11
data/devices/glorious-model-o-eternal.device
Normal file
@@ -0,0 +1,11 @@
|
||||
[Device]
|
||||
Name=Glorious Model O Eternal
|
||||
DeviceMatch=usb:3794:a000
|
||||
Driver=sinowealth
|
||||
DeviceType=mouse
|
||||
|
||||
[Driver/sinowealth/devices/1009]
|
||||
Buttons=6
|
||||
LedType=RBG
|
||||
DeviceName=Glorious Model O Eternal
|
||||
SensorType=PMW3360
|
||||
5
data/devices/logitech-MX-Master-4.device
Normal file
5
data/devices/logitech-MX-Master-4.device
Normal file
@@ -0,0 +1,5 @@
|
||||
[Device]
|
||||
DeviceMatch=bluetooth:046d:b042
|
||||
DeviceType=mouse
|
||||
Driver=hidpp20
|
||||
Name=Logitech MX Master 4
|
||||
@@ -1,5 +1,5 @@
|
||||
[Device]
|
||||
Name=Logitech MX Vertical
|
||||
DeviceMatch=bluetooth:046d:b020;usb:046d:407b;usb:046d:c08a
|
||||
DeviceMatch=bluetooth:046d:b020;usb:046d:407b;usb:046d:c08a;usb:046d:c077
|
||||
Driver=hidpp20
|
||||
DeviceType=mouse
|
||||
|
||||
@@ -3,3 +3,6 @@ Name=Logitech G502 Hero Wireless
|
||||
DeviceMatch=usb:046d:407f;usb:046d:c08d
|
||||
Driver=hidpp20
|
||||
DeviceType=mouse
|
||||
|
||||
[Driver/hidpp20]
|
||||
Quirk=INDEX_OFFSET
|
||||
|
||||
@@ -3,3 +3,6 @@ Name=Logitech G502 Hero
|
||||
DeviceMatch=usb:046d:c08b
|
||||
Driver=hidpp20
|
||||
DeviceType=mouse
|
||||
|
||||
[Driver/hidpp20]
|
||||
Quirk=INDEX_OFFSET
|
||||
|
||||
@@ -3,3 +3,6 @@ Name=Logitech G502 Proteus Spectrum
|
||||
DeviceMatch=usb:046d:c332
|
||||
Driver=hidpp20
|
||||
DeviceType=mouse
|
||||
|
||||
[Driver/hidpp20]
|
||||
Quirk=INDEX_OFFSET
|
||||
|
||||
9
data/devices/logitech-g502-x-plus.device
Normal file
9
data/devices/logitech-g502-x-plus.device
Normal file
@@ -0,0 +1,9 @@
|
||||
[Device]
|
||||
Name=Logitech G502 X PLUS
|
||||
DeviceMatch=usb:046d:4099;usb:046d:c095
|
||||
DeviceType=mouse
|
||||
Driver=hidpp20
|
||||
|
||||
[Driver/hidpp20]
|
||||
# G502X_PLUS: LED is in the 2nd slot. INDEX_OFFSET: profile index is 1-indexed.
|
||||
Quirk=G502X_PLUS;INDEX_OFFSET
|
||||
@@ -1,5 +1,8 @@
|
||||
[Device]
|
||||
Name=Logitech G502 X Wireless
|
||||
DeviceMatch=usb:046d:c098
|
||||
DeviceMatch=usb:046d:c098;usb:046d:409f
|
||||
DeviceType=mouse
|
||||
Driver=hidpp20
|
||||
|
||||
[Driver/hidpp20]
|
||||
Quirk=INDEX_OFFSET
|
||||
|
||||
@@ -3,3 +3,6 @@ Name=Logitech G502 X
|
||||
DeviceMatch=usb:046d:c099
|
||||
DeviceType=mouse
|
||||
Driver=hidpp20
|
||||
|
||||
[Driver/hidpp20]
|
||||
Quirk=INDEX_OFFSET
|
||||
|
||||
@@ -3,3 +3,6 @@ Name=Logitech G604
|
||||
DeviceMatch=usb:046d:4085;bluetooth:046d:b024
|
||||
Driver=hidpp20
|
||||
DeviceType=mouse
|
||||
|
||||
[Driver/hidpp20]
|
||||
Quirk=INDEX_OFFSET
|
||||
|
||||
8
data/devices/logitech-g705.device
Normal file
8
data/devices/logitech-g705.device
Normal file
@@ -0,0 +1,8 @@
|
||||
[Device]
|
||||
Name=Logitech G705
|
||||
DeviceMatch=usb:046d:c096;usb:046d:409d;bluetooth:046d:b02e
|
||||
Driver=hidpp20
|
||||
DeviceType=mouse
|
||||
|
||||
[Driver/hidpp20]
|
||||
Quirk=G502X_PLUS
|
||||
169
src/asus.c
169
src/asus.c
@@ -26,6 +26,7 @@
|
||||
#include "asus.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libratbag-data.h"
|
||||
#include "libratbag-private.h"
|
||||
@@ -75,15 +76,18 @@ static const unsigned char ASUS_KEY_MAPPING[] = {
|
||||
/* 5E */ KEY_KP8, KEY_KP9, 0,
|
||||
};
|
||||
|
||||
static unsigned int ASUS_POLLING_RATES[] = { 125, 250, 500, 1000 };
|
||||
static unsigned int ASUS_DEBOUNCE_TIMES[] = { 4, 8, 12, 16, 20, 24, 28, 32 };
|
||||
static const uint8_t ASUS_JOYSTICK_CODES[] = { 0xd0, 0xd1, 0xd2, 0xd3, 0xd7, 0xd8, 0xda, 0xdb };
|
||||
static const unsigned int ASUS_POLLING_RATES[] = { 125, 250, 500, 1000 };
|
||||
static const unsigned int ASUS_DEBOUNCE_TIMES[] = { 4, 8, 12, 16, 20, 24, 28, 32 };
|
||||
|
||||
/* search for ASUS button by ratbag types */
|
||||
const struct asus_button *
|
||||
asus_find_button_by_action(struct ratbag_button_action action)
|
||||
asus_find_button_by_action(struct ratbag_button_action action, bool is_joystick)
|
||||
{
|
||||
const struct asus_button *asus_button;
|
||||
ARRAY_FOR_EACH(ASUS_BUTTON_MAPPING, asus_button) {
|
||||
if (is_joystick != asus_code_is_joystick(asus_button->asus_code))
|
||||
continue;
|
||||
if ((action.type == RATBAG_BUTTON_ACTION_TYPE_BUTTON && asus_button->button == action.action.button) ||
|
||||
(action.type == RATBAG_BUTTON_ACTION_TYPE_SPECIAL && asus_button->special == action.action.special))
|
||||
return asus_button;
|
||||
@@ -113,6 +117,15 @@ asus_find_key_code(unsigned int linux_code)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool
|
||||
asus_code_is_joystick(uint8_t asus_code) {
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH(ASUS_JOYSTICK_CODES); i++) {
|
||||
if (ASUS_JOYSTICK_CODES[i] == asus_code)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
asus_get_linux_key_code(uint8_t asus_code) {
|
||||
if (asus_code > ARRAY_LENGTH(ASUS_KEY_MAPPING)) {
|
||||
@@ -126,15 +139,37 @@ asus_query(struct ratbag_device *device,
|
||||
union asus_request *request, union asus_response *response)
|
||||
{
|
||||
int rc;
|
||||
uint32_t quirks = ratbag_device_data_asus_get_quirks(device->data);
|
||||
uint8_t omni_tx_buf[ASUS_PACKET_SIZE];
|
||||
uint8_t omni_rx_buf[ASUS_PACKET_SIZE];
|
||||
|
||||
rc = ratbag_hidraw_output_report(device, request->raw, ASUS_PACKET_SIZE);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (quirks & ASUS_QUIRK_OMNI_RECEIVER) {
|
||||
/* devices behind the Omni receiver use report ID 0x03 and a
|
||||
* 64-byte report, the payload is shifted by one byte */
|
||||
memset(omni_tx_buf, 0, sizeof(omni_tx_buf));
|
||||
omni_tx_buf[0] = 0x03;
|
||||
memcpy(omni_tx_buf + 1, request->raw, ASUS_PACKET_SIZE - 1);
|
||||
|
||||
memset(response, 0, sizeof(union asus_response));
|
||||
rc = ratbag_hidraw_read_input_report(device, response->raw, ASUS_PACKET_SIZE, NULL);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
rc = ratbag_hidraw_output_report(device, omni_tx_buf, ASUS_PACKET_SIZE);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
memset(response, 0, sizeof(union asus_response));
|
||||
rc = ratbag_hidraw_read_input_report(device, omni_rx_buf, ASUS_PACKET_SIZE, NULL);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
memcpy(response->raw, omni_rx_buf + 1, ASUS_PACKET_SIZE - 1);
|
||||
} else {
|
||||
rc = ratbag_hidraw_output_report(device, request->raw, ASUS_PACKET_SIZE);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
memset(response, 0, sizeof(union asus_response));
|
||||
rc = ratbag_hidraw_read_input_report(device, response->raw, ASUS_PACKET_SIZE, NULL);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* invalid state, disconnected or sleeping */
|
||||
if (response->data.code == ASUS_STATUS_ERROR) {
|
||||
@@ -216,6 +251,11 @@ asus_get_profile_data(struct ratbag_device *device, struct asus_profile_data *da
|
||||
else
|
||||
data->profile_id = response.data.results[8];
|
||||
|
||||
if (response.data.results[9])
|
||||
data->dpi_preset = response.data.results[9] - 1;
|
||||
else
|
||||
data->dpi_preset = -1;
|
||||
|
||||
data->version_primary_major = response.data.results[13];
|
||||
data->version_primary_minor = response.data.results[12];
|
||||
data->version_primary_build = response.data.results[11];
|
||||
@@ -246,12 +286,13 @@ asus_set_profile(struct ratbag_device *device, unsigned int index)
|
||||
|
||||
/* read button bindings */
|
||||
int
|
||||
asus_get_binding_data(struct ratbag_device *device, union asus_binding_data *data)
|
||||
asus_get_binding_data(struct ratbag_device *device, union asus_binding_data *data, unsigned int group)
|
||||
{
|
||||
int rc;
|
||||
union asus_response response;
|
||||
union asus_request request = {
|
||||
.data.cmd = ASUS_CMD_GET_BUTTON_DATA,
|
||||
.data.params[0] = (uint8_t)group,
|
||||
};
|
||||
|
||||
rc = asus_query(device, &request, &response);
|
||||
@@ -289,7 +330,7 @@ asus_set_button_action(struct ratbag_device *device, uint8_t asus_code_src,
|
||||
}
|
||||
|
||||
int
|
||||
asus_get_resolution_data(struct ratbag_device *device, union asus_resolution_data *data)
|
||||
asus_get_resolution_data(struct ratbag_device *device, union asus_resolution_data *data, bool sep_xy_dpi)
|
||||
{
|
||||
int rc;
|
||||
uint32_t quirks = ratbag_device_data_asus_get_quirks(device->data);
|
||||
@@ -298,6 +339,7 @@ asus_get_resolution_data(struct ratbag_device *device, union asus_resolution_dat
|
||||
unsigned int i;
|
||||
union asus_request request = {
|
||||
.data.cmd = ASUS_CMD_GET_SETTINGS,
|
||||
.data.params[0] = sep_xy_dpi ? 2 : 0,
|
||||
};
|
||||
|
||||
rc = asus_query(device, &request, &response);
|
||||
@@ -319,13 +361,51 @@ asus_get_resolution_data(struct ratbag_device *device, union asus_resolution_dat
|
||||
break;
|
||||
|
||||
case 4: /* 4 DPI presets */
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
data->data4.dpi[i] = data->data4.dpi[i] * 50 + 50;
|
||||
if (quirks & ASUS_QUIRK_DOUBLE_DPI)
|
||||
data->data4.dpi[i] *= 2;
|
||||
if (sep_xy_dpi) { /* separate X & Y values */
|
||||
if (quirks & ASUS_QUIRK_SETTINGS_V2) {
|
||||
/* new layout: data starts at offset 4, each preset
|
||||
* is x lo/hi, y lo/hi */
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
uint16_t x = data->raw[4 + i * 4] |
|
||||
(data->raw[5 + i * 4] << 8);
|
||||
uint16_t y = data->raw[6 + i * 4] |
|
||||
(data->raw[7 + i * 4] << 8);
|
||||
data->data_xy.dpi[i].x = x * 50 + 50;
|
||||
data->data_xy.dpi[i].y = y * 50 + 50;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
data->data_xy.dpi[i].x = data->data_xy.dpi[i].x * 50 + 50;
|
||||
data->data_xy.dpi[i].y = data->data_xy.dpi[i].y * 50 + 50;
|
||||
if (quirks & ASUS_QUIRK_DOUBLE_DPI) {
|
||||
data->data_xy.dpi[i].x *= 2;
|
||||
data->data_xy.dpi[i].y *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (quirks & ASUS_QUIRK_SETTINGS_V2) {
|
||||
/* new layout: data starts at offset 4, dpi presets
|
||||
* are 2 bytes each, rate/debounce/snapping are
|
||||
* single bytes at offset 12/14/16 */
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
uint16_t dpi = data->raw[4 + i * 2] |
|
||||
(data->raw[5 + i * 2] << 8);
|
||||
data->data4.dpi[i] = dpi * 50 + 50;
|
||||
}
|
||||
data->data4.rate = ASUS_POLLING_RATES[data->raw[12] & 0x07];
|
||||
data->data4.response = ASUS_DEBOUNCE_TIMES[data->raw[14]];
|
||||
data->data4.snapping = data->raw[16];
|
||||
} else {
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
data->data4.dpi[i] = data->data4.dpi[i] * 50 + 50;
|
||||
if (quirks & ASUS_QUIRK_DOUBLE_DPI)
|
||||
data->data4.dpi[i] *= 2;
|
||||
}
|
||||
data->data4.rate = ASUS_POLLING_RATES[data->data4.rate];
|
||||
data->data4.response = ASUS_DEBOUNCE_TIMES[data->data4.response];
|
||||
}
|
||||
}
|
||||
data->data4.rate = ASUS_POLLING_RATES[data->data4.rate];
|
||||
data->data4.response = ASUS_DEBOUNCE_TIMES[data->data4.response];
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -348,10 +428,12 @@ asus_set_dpi(struct ratbag_device *device, unsigned int index, unsigned int dpi)
|
||||
if (quirks & ASUS_QUIRK_DOUBLE_DPI)
|
||||
idpi /= 2;
|
||||
|
||||
idpi = (idpi - 50) / 50;
|
||||
union asus_request request = {
|
||||
.data.cmd = ASUS_CMD_SET_SETTING,
|
||||
.data.params[0] = index,
|
||||
.data.params[2] = (idpi - 50) / 50,
|
||||
.data.params[2] = idpi & 0xff,
|
||||
.data.params[3] = (idpi >> 8) & 0xff,
|
||||
};
|
||||
|
||||
rc = asus_query(device, &request, &response);
|
||||
@@ -440,12 +522,13 @@ asus_set_angle_snapping(struct ratbag_device *device, bool is_enabled)
|
||||
}
|
||||
|
||||
int
|
||||
asus_get_led_data(struct ratbag_device *device, union asus_led_data *data)
|
||||
asus_get_led_data(struct ratbag_device *device, union asus_led_data *data, unsigned int led)
|
||||
{
|
||||
int rc;
|
||||
union asus_response response;
|
||||
union asus_request request = {
|
||||
.data.cmd = ASUS_CMD_GET_LED_DATA,
|
||||
.data.params[0] = led,
|
||||
};
|
||||
|
||||
rc = asus_query(device, &request, &response);
|
||||
@@ -480,3 +563,49 @@ asus_set_led(struct ratbag_device *device,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ASUS Omni receiver: identify the mouse behind the shared receiver.
|
||||
*
|
||||
* All mice connected to an Omni receiver share the same USB id
|
||||
* (0b05:1ace), so the model is queried with a signature request
|
||||
* (03 12 12 02). The response carries a 12 byte ASCII serial number at
|
||||
* offset 5 and the model is derived from its prefix.
|
||||
*
|
||||
* The serial number is matched against the OmniSignature field of the
|
||||
* .device files, so supporting a new model does not require any code
|
||||
* changes. On success the usb id of the identified model is returned in
|
||||
* id, so that the caller can resolve the mouse-specific .device data.
|
||||
*/
|
||||
int
|
||||
asus_omni_identify(struct ratbag_device *device, struct input_id *id)
|
||||
{
|
||||
int rc;
|
||||
union asus_request request = {
|
||||
.data.cmd = 0x1212,
|
||||
.data.params[0] = 0x02,
|
||||
};
|
||||
union asus_response response;
|
||||
char signature[13];
|
||||
|
||||
rc = asus_query(device, &request, &response);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* signature is 12 ASCII bytes at offset 5 of the raw report,
|
||||
* which is offset 4 after the report id is stripped */
|
||||
memcpy(signature, response.raw + 4, 12);
|
||||
signature[12] = '\0';
|
||||
|
||||
rc = ratbag_device_data_omni_signature_match(device->ratbag, signature, id);
|
||||
if (rc) {
|
||||
log_debug(device->ratbag,
|
||||
"Unknown ASUS Omni device serial '%s'. Please add an "
|
||||
"OmniSignature entry to the .device file of the model.\n",
|
||||
signature);
|
||||
return rc;
|
||||
}
|
||||
|
||||
log_info(device->ratbag,
|
||||
"ASUS Omni device identified (serial %s)\n", signature);
|
||||
return 0;
|
||||
}
|
||||
|
||||
47
src/asus.h
47
src/asus.h
@@ -9,6 +9,13 @@
|
||||
#define ASUS_QUIRK_DOUBLE_DPI 1 << 0
|
||||
#define ASUS_QUIRK_STRIX_PROFILE 1 << 1
|
||||
#define ASUS_QUIRK_BATTERY_V2 1 << 2
|
||||
#define ASUS_QUIRK_RAW_BRIGHTNESS 1 << 3
|
||||
#define ASUS_QUIRK_SEPARATE_XY_DPI 1 << 4
|
||||
#define ASUS_QUIRK_SEPARATE_LEDS 1 << 5
|
||||
#define ASUS_QUIRK_BUTTONS_SECONDARY 1 << 6
|
||||
#define ASUS_QUIRK_OMNI_RECEIVER 1 << 7 /* device is behind an ASUS Omni receiver, transport uses report ID 0x03 */
|
||||
#define ASUS_QUIRK_LED_V2 1 << 8 /* LED response is per-zone with data at offset 4, brightness is 0-100 */
|
||||
#define ASUS_QUIRK_SETTINGS_V2 1 << 9 /* settings/DPI response data starts at offset 4, rate/debounce/snapping are single bytes */
|
||||
|
||||
#define ASUS_PACKET_SIZE 64
|
||||
#define ASUS_BUTTON_ACTION_TYPE_KEY 0 /* keyboard key */
|
||||
@@ -18,6 +25,7 @@
|
||||
|
||||
/* maximum number of buttons across all ASUS devices */
|
||||
#define ASUS_MAX_NUM_BUTTON 17
|
||||
#define ASUS_MAX_NUM_BUTTON_GROUP 2
|
||||
|
||||
/* maximum number of DPI presets across all ASUS devices */
|
||||
/* for 4 DPI devices: 0 - red, 1 - purple, 2 - blue (default), 3 - green */
|
||||
@@ -26,6 +34,7 @@
|
||||
|
||||
/* maximum number of LEDs across all ASUS devices */
|
||||
#define ASUS_MAX_NUM_LED 3
|
||||
#define ASUS_MAX_NUM_LED_MODES 7
|
||||
|
||||
/* base request */
|
||||
|
||||
@@ -57,6 +66,7 @@ union asus_response {
|
||||
|
||||
struct asus_profile_data {
|
||||
unsigned int profile_id;
|
||||
int dpi_preset;
|
||||
uint8_t version_primary_major;
|
||||
uint8_t version_primary_minor;
|
||||
uint8_t version_primary_build;
|
||||
@@ -90,6 +100,7 @@ struct _asus_dpi2_data {
|
||||
uint16_t rate; /* polling rate */
|
||||
uint16_t response; /* button response */
|
||||
uint16_t snapping; /* angle snapping (on/off) */
|
||||
uint16_t pad2;
|
||||
} __attribute__((packed)); /* struct for storing 2 DPI presets and extra settings */
|
||||
|
||||
struct _asus_dpi4_data {
|
||||
@@ -98,11 +109,23 @@ struct _asus_dpi4_data {
|
||||
uint16_t rate;
|
||||
uint16_t response;
|
||||
uint16_t snapping;
|
||||
uint16_t pad2;
|
||||
} __attribute__((packed)); /* struct for storing 4 DPI presets and extra settings */
|
||||
|
||||
struct _asus_dpi_xy {
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
};
|
||||
|
||||
struct _asus_dpi_xy_data {
|
||||
uint32_t pad;
|
||||
struct _asus_dpi_xy dpi[4];
|
||||
} __attribute__((packed)); /* struct for storing 4 DPI presets with separate X & Y */
|
||||
|
||||
union asus_resolution_data {
|
||||
struct _asus_dpi2_data data2; /* data for 2 DPI presets */
|
||||
struct _asus_dpi4_data data4; /* data for 4 DPI presets */
|
||||
struct _asus_dpi_xy_data data_xy; /* data for 4 DPI presets with separate X & Y */
|
||||
uint8_t raw[sizeof(struct _asus_dpi4_data)];
|
||||
};
|
||||
|
||||
@@ -153,10 +176,18 @@ static const struct asus_button ASUS_BUTTON_MAPPING[] = {
|
||||
{ 0xed, RATBAG_BUTTON_ACTION_TYPE_NONE, 0, 0 }, /* side button D */
|
||||
{ 0xee, RATBAG_BUTTON_ACTION_TYPE_NONE, 0, 0 }, /* side button E */
|
||||
{ 0xef, RATBAG_BUTTON_ACTION_TYPE_NONE, 0, 0 }, /* side button F */
|
||||
{ 0xd0, RATBAG_BUTTON_ACTION_TYPE_NONE, 0, 0 }, /* joystick up */
|
||||
{ 0xd1, RATBAG_BUTTON_ACTION_TYPE_NONE, 0, 0 }, /* joystick down */
|
||||
{ 0xd2, RATBAG_BUTTON_ACTION_TYPE_NONE, 0, 0 }, /* joystick forward */
|
||||
{ 0xd3, RATBAG_BUTTON_ACTION_TYPE_NONE, 0, 0 }, /* joystick backward */
|
||||
{ 0xd7, RATBAG_BUTTON_ACTION_TYPE_SPECIAL, 0, RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_DOWN }, /* joystick axis -Y */
|
||||
{ 0xd8, RATBAG_BUTTON_ACTION_TYPE_SPECIAL, 0, RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_UP }, /* joystick axis +Y */
|
||||
{ 0xda, RATBAG_BUTTON_ACTION_TYPE_SPECIAL, 0, RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_RIGHT }, /* joystick axis -X */
|
||||
{ 0xdb, RATBAG_BUTTON_ACTION_TYPE_SPECIAL, 0, RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_LEFT }, /* joystick axis +X */
|
||||
};
|
||||
|
||||
const struct asus_button *
|
||||
asus_find_button_by_action(struct ratbag_button_action action);
|
||||
asus_find_button_by_action(struct ratbag_button_action action, bool is_joystick);
|
||||
|
||||
const struct asus_button *
|
||||
asus_find_button_by_code(uint8_t asus_code);
|
||||
@@ -164,6 +195,9 @@ asus_find_button_by_code(uint8_t asus_code);
|
||||
int
|
||||
asus_find_key_code(unsigned int linux_code);
|
||||
|
||||
bool
|
||||
asus_code_is_joystick(uint8_t asus_code);
|
||||
|
||||
/*
|
||||
* @param asus_code ASUS key code.
|
||||
* @return Linux key code (as defined defined in linux/input-event-codes.h) or
|
||||
@@ -191,6 +225,11 @@ asus_setup_led(struct ratbag_device *device, struct ratbag_led *led);
|
||||
int
|
||||
asus_query(struct ratbag_device *device, union asus_request *request, union asus_response *response);
|
||||
|
||||
/* ASUS Omni receiver: identify the mouse behind the shared receiver and
|
||||
* return the usb id that matches its own .device file. */
|
||||
int
|
||||
asus_omni_identify(struct ratbag_device *device, struct input_id *id);
|
||||
|
||||
/* commit */
|
||||
|
||||
int
|
||||
@@ -207,7 +246,7 @@ asus_set_profile(struct ratbag_device *device, unsigned int index);
|
||||
/* button bindings */
|
||||
|
||||
int
|
||||
asus_get_binding_data(struct ratbag_device *device, union asus_binding_data *data);
|
||||
asus_get_binding_data(struct ratbag_device *device, union asus_binding_data *data, unsigned int group);
|
||||
|
||||
int
|
||||
asus_set_button_action(struct ratbag_device *device, uint8_t asus_code_src,
|
||||
@@ -216,7 +255,7 @@ asus_set_button_action(struct ratbag_device *device, uint8_t asus_code_src,
|
||||
/* resolution settings */
|
||||
|
||||
int
|
||||
asus_get_resolution_data(struct ratbag_device *device, union asus_resolution_data *data);
|
||||
asus_get_resolution_data(struct ratbag_device *device, union asus_resolution_data *data, bool sep_xy_dpi);
|
||||
|
||||
int
|
||||
asus_set_dpi(struct ratbag_device *device, unsigned int index, unsigned int dpi);
|
||||
@@ -233,7 +272,7 @@ asus_set_angle_snapping(struct ratbag_device *device, bool is_enabled);
|
||||
/* LED settings */
|
||||
|
||||
int
|
||||
asus_get_led_data(struct ratbag_device *device, union asus_led_data *data);
|
||||
asus_get_led_data(struct ratbag_device *device, union asus_led_data *data, unsigned int led);
|
||||
|
||||
int
|
||||
asus_set_led(struct ratbag_device *device,
|
||||
|
||||
@@ -46,17 +46,9 @@ static int ASUS_CONFIG_BUTTON_MAPPING[] = {
|
||||
0xe6, /* DPI */
|
||||
0xe8, /* wheel up */
|
||||
0xe9, /* wheel down */
|
||||
-1, /* placeholder */
|
||||
-1, /* placeholder */
|
||||
-1, /* placeholder */
|
||||
-1, /* placeholder */
|
||||
-1, /* placeholder */
|
||||
-1, /* placeholder */
|
||||
-1, /* placeholder */
|
||||
-1, /* placeholder */
|
||||
-1, /* placeholder */
|
||||
};
|
||||
|
||||
/* LedModes configuration property defaults */
|
||||
static unsigned int ASUS_LED_MODE[] = {
|
||||
RATBAG_LED_ON,
|
||||
RATBAG_LED_BREATHING,
|
||||
@@ -69,12 +61,13 @@ static unsigned int ASUS_LED_MODE[] = {
|
||||
|
||||
struct asus_data {
|
||||
uint8_t is_ready;
|
||||
int button_mapping[ASUS_MAX_NUM_BUTTON];
|
||||
int button_indices[ASUS_MAX_NUM_BUTTON];
|
||||
int button_mapping[ASUS_MAX_NUM_BUTTON * ASUS_MAX_NUM_BUTTON_GROUP];
|
||||
int button_indices[ASUS_MAX_NUM_BUTTON * ASUS_MAX_NUM_BUTTON_GROUP];
|
||||
int led_modes[ASUS_MAX_NUM_LED_MODES];
|
||||
};
|
||||
|
||||
static int
|
||||
asus_driver_load_profile(struct ratbag_device *device, struct ratbag_profile *profile)
|
||||
asus_driver_load_profile(struct ratbag_device *device, struct ratbag_profile *profile, int dpi_preset)
|
||||
{
|
||||
int rc;
|
||||
const struct _asus_binding *asus_binding;
|
||||
@@ -84,18 +77,28 @@ asus_driver_load_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
struct ratbag_led *led;
|
||||
struct ratbag_resolution *resolution;
|
||||
union asus_binding_data binding_data;
|
||||
union asus_binding_data binding_data_secondary;
|
||||
union asus_led_data led_data;
|
||||
union asus_resolution_data resolution_data;
|
||||
union asus_resolution_data xy_resolution_data;
|
||||
unsigned int dpi_count = ratbag_device_get_profile(device, 0)->num_resolutions;
|
||||
unsigned int led_count = ratbag_device_get_num_leds(device);
|
||||
uint32_t quirks = ratbag_device_data_asus_get_quirks(device->data);
|
||||
struct asus_data *drv_data = ratbag_get_drv_data(device);
|
||||
|
||||
/* get buttons */
|
||||
|
||||
log_debug(device->ratbag, "Loading buttons data\n");
|
||||
rc = asus_get_binding_data(device, &binding_data);
|
||||
rc = asus_get_binding_data(device, &binding_data, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (quirks & ASUS_QUIRK_BUTTONS_SECONDARY) {
|
||||
rc = asus_get_binding_data(device, &binding_data_secondary, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
ratbag_profile_for_each_button(profile, button) {
|
||||
int asus_index = drv_data->button_indices[button->index];
|
||||
if (asus_index == -1) {
|
||||
@@ -103,7 +106,11 @@ asus_driver_load_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
continue;
|
||||
}
|
||||
|
||||
asus_binding = &binding_data.data.binding[asus_index];
|
||||
if (asus_index < ASUS_MAX_NUM_BUTTON) {
|
||||
asus_binding = &binding_data.data.binding[asus_index];
|
||||
} else {
|
||||
asus_binding = &binding_data_secondary.data.binding[asus_index % ASUS_MAX_NUM_BUTTON];
|
||||
}
|
||||
|
||||
/* disabled */
|
||||
if (asus_binding->action == ASUS_BUTTON_CODE_DISABLED) {
|
||||
@@ -144,31 +151,59 @@ asus_driver_load_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
/* get DPIs */
|
||||
|
||||
log_debug(device->ratbag, "Loading resolutions data\n");
|
||||
rc = asus_get_resolution_data(device, &resolution_data);
|
||||
rc = asus_get_resolution_data(device, &resolution_data, false);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (quirks & ASUS_QUIRK_SEPARATE_XY_DPI) {
|
||||
rc = asus_get_resolution_data(device, &xy_resolution_data, true);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
switch (dpi_count) {
|
||||
case 2: /* 2 DPI presets */
|
||||
profile->hz = resolution_data.data2.rate;
|
||||
profile->angle_snapping = resolution_data.data2.snapping;
|
||||
profile->debounce = resolution_data.data2.response;
|
||||
ratbag_profile_for_each_resolution(profile, resolution)
|
||||
ratbag_resolution_set_resolution(
|
||||
resolution,
|
||||
resolution_data.data2.dpi[resolution->index],
|
||||
resolution_data.data2.dpi[resolution->index]);
|
||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||
if (quirks & ASUS_QUIRK_SEPARATE_XY_DPI) {
|
||||
ratbag_resolution_set_cap(resolution, RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION);
|
||||
ratbag_resolution_set_resolution(
|
||||
resolution,
|
||||
xy_resolution_data.data_xy.dpi[resolution->index].x,
|
||||
xy_resolution_data.data_xy.dpi[resolution->index].y);
|
||||
} else {
|
||||
ratbag_resolution_set_resolution(
|
||||
resolution,
|
||||
resolution_data.data2.dpi[resolution->index],
|
||||
resolution_data.data2.dpi[resolution->index]);
|
||||
}
|
||||
if (dpi_preset != -1 && (unsigned int)dpi_preset == resolution->index)
|
||||
resolution->is_active = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: /* 4 DPI presets */
|
||||
profile->hz = resolution_data.data4.rate;
|
||||
profile->angle_snapping = resolution_data.data4.snapping;
|
||||
profile->debounce = resolution_data.data4.response;
|
||||
ratbag_profile_for_each_resolution(profile, resolution)
|
||||
ratbag_resolution_set_resolution(
|
||||
resolution,
|
||||
resolution_data.data4.dpi[resolution->index],
|
||||
resolution_data.data4.dpi[resolution->index]);
|
||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||
if (quirks & ASUS_QUIRK_SEPARATE_XY_DPI) {
|
||||
ratbag_resolution_set_cap(resolution, RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION);
|
||||
ratbag_resolution_set_resolution(
|
||||
resolution,
|
||||
xy_resolution_data.data_xy.dpi[resolution->index].x,
|
||||
xy_resolution_data.data_xy.dpi[resolution->index].y);
|
||||
} else {
|
||||
ratbag_resolution_set_resolution(
|
||||
resolution,
|
||||
resolution_data.data4.dpi[resolution->index],
|
||||
resolution_data.data4.dpi[resolution->index]);
|
||||
}
|
||||
if (dpi_preset != -1 && (unsigned int)dpi_preset == resolution->index)
|
||||
resolution->is_active = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -177,16 +212,44 @@ asus_driver_load_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
|
||||
/* get LEDs */
|
||||
|
||||
log_debug(device->ratbag, "Loading LEDs data\n");
|
||||
rc = asus_get_led_data(device, &led_data);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (!(quirks & (ASUS_QUIRK_SEPARATE_LEDS | ASUS_QUIRK_LED_V2)) && led_count) {
|
||||
log_debug(device->ratbag, "Loading LEDs data\n");
|
||||
rc = asus_get_led_data(device, &led_data, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
ratbag_profile_for_each_led(profile, led) {
|
||||
asus_led = &led_data.data.led[led->index];
|
||||
led->mode = ASUS_LED_MODE[asus_led->mode];
|
||||
/* convert brightness from 0-4 to 0-256 */
|
||||
led->brightness = asus_led->brightness * 64;
|
||||
if (quirks & (ASUS_QUIRK_SEPARATE_LEDS | ASUS_QUIRK_LED_V2)) {
|
||||
log_debug(device->ratbag, "Loading LED %d data\n", led->index);
|
||||
rc = asus_get_led_data(device, &led_data, led->index);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (quirks & ASUS_QUIRK_LED_V2) {
|
||||
/* new layout: a single zone per response with data at
|
||||
* offset 4, brightness is 0-100 percent */
|
||||
led->mode = drv_data->led_modes[led_data.raw[4]];
|
||||
led->brightness = led_data.raw[5] * 255 / 100;
|
||||
led->color.red = led_data.raw[6];
|
||||
led->color.green = led_data.raw[7];
|
||||
led->color.blue = led_data.raw[8];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (quirks & ASUS_QUIRK_SEPARATE_LEDS)
|
||||
asus_led = &led_data.data.led[0];
|
||||
else
|
||||
asus_led = &led_data.data.led[led->index];
|
||||
|
||||
led->mode = drv_data->led_modes[asus_led->mode];
|
||||
if (quirks & ASUS_QUIRK_RAW_BRIGHTNESS) {
|
||||
led->brightness = asus_led->brightness;
|
||||
} else {
|
||||
/* convert brightness from 0-4 to 0-256 */
|
||||
led->brightness = asus_led->brightness * 64;
|
||||
}
|
||||
led->color.red = asus_led->r;
|
||||
led->color.green = asus_led->g;
|
||||
led->color.blue = asus_led->b;
|
||||
@@ -203,6 +266,7 @@ asus_driver_save_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
struct ratbag_led *led;
|
||||
struct ratbag_resolution *resolution;
|
||||
struct asus_data *drv_data = ratbag_get_drv_data(device);
|
||||
uint32_t quirks = ratbag_device_data_asus_get_quirks(device->data);
|
||||
|
||||
/* set buttons */
|
||||
ratbag_profile_for_each_button(profile, button) {
|
||||
@@ -218,6 +282,7 @@ asus_driver_save_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
const struct asus_button *asus_button;
|
||||
uint8_t asus_code_src;
|
||||
uint8_t asus_code_dst;
|
||||
bool is_joystick;
|
||||
|
||||
rc = drv_data->button_mapping[asus_index];
|
||||
if (rc == -1) {
|
||||
@@ -250,7 +315,18 @@ asus_driver_save_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
case RATBAG_BUTTON_ACTION_TYPE_BUTTON:
|
||||
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL:
|
||||
/* ratbag action to ASUS code */
|
||||
asus_button = asus_find_button_by_action(button->action);
|
||||
is_joystick = asus_code_is_joystick(asus_code_src);
|
||||
if (is_joystick) {
|
||||
asus_button = asus_find_button_by_action(button->action, true);
|
||||
if (asus_button != NULL) { /* found button to bind to */
|
||||
rc = asus_set_button_action(
|
||||
device, asus_code_src, asus_button->asus_code,
|
||||
ASUS_BUTTON_ACTION_TYPE_BUTTON);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
asus_button = asus_find_button_by_action(button->action, false);
|
||||
if (asus_button != NULL) /* found button to bind to */
|
||||
rc = asus_set_button_action(
|
||||
device, asus_code_src, asus_button->asus_code,
|
||||
@@ -306,15 +382,23 @@ asus_driver_save_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
|
||||
log_debug(device->ratbag, "LED %d changed\n", led->index);
|
||||
uint8_t led_mode = 0;
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH(ASUS_LED_MODE); i++) {
|
||||
if (ASUS_LED_MODE[i] == led->mode) {
|
||||
for (unsigned int i = 0; i < ASUS_MAX_NUM_LED_MODES; i++) {
|
||||
if (drv_data->led_modes[i] == (int) led->mode) {
|
||||
led_mode = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert brightness from 0-256 to 0-4 */
|
||||
uint8_t led_brightness = (uint8_t)round((double)led->brightness / 64.0);
|
||||
uint8_t led_brightness;
|
||||
if (quirks & ASUS_QUIRK_RAW_BRIGHTNESS) {
|
||||
led_brightness = led->brightness;
|
||||
} else if (quirks & ASUS_QUIRK_LED_V2) {
|
||||
/* convert brightness from 0-255 to 0-100 percent */
|
||||
led_brightness = (uint8_t)round((double)led->brightness * 100.0 / 255.0);
|
||||
} else {
|
||||
/* convert brightness from 0-256 to 0-4 */
|
||||
led_brightness = (uint8_t)round((double)led->brightness / 64.0);
|
||||
}
|
||||
rc = asus_set_led(device, led->index, led_mode, led_brightness, led->color);
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -365,7 +449,7 @@ asus_driver_load_profiles(struct ratbag_device *device)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = asus_driver_load_profile(device, profile);
|
||||
rc = asus_driver_load_profile(device, profile, profile_data.dpi_preset);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
@@ -447,17 +531,51 @@ asus_driver_probe(struct ratbag_device *device)
|
||||
struct ratbag_button *button;
|
||||
struct ratbag_resolution *resolution;
|
||||
struct ratbag_led *led;
|
||||
uint32_t quirks = ratbag_device_data_asus_get_quirks(device->data);
|
||||
|
||||
rc = ratbag_open_hidraw(device);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = asus_get_profile_data(device, &profile_data);
|
||||
if (rc) {
|
||||
ratbag_close_hidraw(device);
|
||||
return -ENODEV;
|
||||
/* The Omni receiver is a shared USB device for multiple mice, so the
|
||||
* actual model has to be identified and resolved to its own .device
|
||||
* data before anything else. Wrong hidraw nodes (keyboard, media
|
||||
* control, etc.) fail the identification and are rejected here. */
|
||||
if (quirks & ASUS_QUIRK_OMNI_RECEIVER) {
|
||||
struct ratbag_device_data *data;
|
||||
struct input_id id = device->ids;
|
||||
|
||||
rc = asus_omni_identify(device, &id);
|
||||
if (rc) {
|
||||
log_debug(device->ratbag,
|
||||
"Omni device is not a supported mouse\n");
|
||||
ratbag_close_hidraw(device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = ratbag_device_data_new_for_id(device->ratbag, &id);
|
||||
if (!data) {
|
||||
log_error(device->ratbag,
|
||||
"No device data for Omni mouse %04x:%04x\n",
|
||||
id.vendor, id.product);
|
||||
ratbag_close_hidraw(device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ratbag_device_data_unref(device->data);
|
||||
device->data = data;
|
||||
device->devicetype = ratbag_device_data_get_device_type(device->data);
|
||||
free(device->name);
|
||||
device->name = strdup_safe(ratbag_device_data_get_name(device->data));
|
||||
log_info(device->ratbag,
|
||||
"ASUS Omni receiver identified device: %s\n",
|
||||
device->name);
|
||||
|
||||
quirks = ratbag_device_data_asus_get_quirks(device->data);
|
||||
}
|
||||
|
||||
rc = asus_get_profile_data(device, &profile_data);
|
||||
|
||||
/* create device state data */
|
||||
drv_data = zalloc(sizeof(*drv_data));
|
||||
ratbag_set_drv_data(device, drv_data);
|
||||
@@ -469,23 +587,37 @@ asus_driver_probe(struct ratbag_device *device)
|
||||
button_count = ratbag_device_data_asus_get_button_count(device->data);
|
||||
led_count = ratbag_device_data_asus_get_led_count(device->data);
|
||||
const int *bm = ratbag_device_data_asus_get_button_mapping(device->data);
|
||||
const int *led_modes = ratbag_device_data_asus_get_led_modes(device->data);
|
||||
|
||||
/* merge ButtonMapping configuration property with defaults */
|
||||
for (unsigned int i = 0; i < ASUS_MAX_NUM_BUTTON; i++) {
|
||||
drv_data->button_mapping[i] = bm[i] != -1 ? bm[i] : ASUS_CONFIG_BUTTON_MAPPING[i];
|
||||
for (unsigned int i = 0; i < ASUS_MAX_NUM_BUTTON * ASUS_MAX_NUM_BUTTON_GROUP; i++) {
|
||||
if (bm[i] != -1) {
|
||||
drv_data->button_mapping[i] = bm[i];
|
||||
} else {
|
||||
if (i < ARRAY_LENGTH(ASUS_CONFIG_BUTTON_MAPPING)) {
|
||||
drv_data->button_mapping[i] = ASUS_CONFIG_BUTTON_MAPPING[i];
|
||||
} else {
|
||||
drv_data->button_mapping[i] = -1;
|
||||
}
|
||||
}
|
||||
drv_data->button_indices[i] = -1;
|
||||
}
|
||||
|
||||
/* merge LedModes configuration property with defaults */
|
||||
for (unsigned int i = 0; i < ASUS_MAX_NUM_LED_MODES; i++)
|
||||
drv_data->led_modes[i] = (led_modes[i] != -1) ? led_modes[i] : (int) ASUS_LED_MODE[i];
|
||||
|
||||
/* setup a lookup table for all defined buttons */
|
||||
unsigned int button_index = 0;
|
||||
ARRAY_FOR_EACH(ASUS_BUTTON_MAPPING, asus_button) {
|
||||
/* search for this button in the ButtonMapping by it's ASUS code */
|
||||
for (unsigned int i = 0; i < ASUS_MAX_NUM_BUTTON; i++) {
|
||||
for (unsigned int i = 0; i < ASUS_MAX_NUM_BUTTON * ASUS_MAX_NUM_BUTTON_GROUP; i++) {
|
||||
if (drv_data->button_mapping[i] == (int)asus_button->asus_code) {
|
||||
/* add button to indices array */
|
||||
drv_data->button_indices[button_index] = (int)i;
|
||||
log_debug(device->ratbag, "Button %d is mapped to 0x%02x\n",
|
||||
button_index, (uint8_t)drv_data->button_mapping[i]);
|
||||
log_debug(device->ratbag, "Button %d is mapped to 0x%02x at position %d group %d\n",
|
||||
button_index, (uint8_t)drv_data->button_mapping[i],
|
||||
i % ASUS_MAX_NUM_BUTTON, i / ASUS_MAX_NUM_BUTTON);
|
||||
button_index++;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -411,7 +411,13 @@ hidpp20drv_read_led_8071(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
|
||||
hidpp20_rgb_effects_get_device_info(drv_data->dev, &device_info);
|
||||
cluster_info = drv_data->led_infos.color_leds_8071[led->index];
|
||||
profile = &drv_data->profiles->profiles[led->profile->index];
|
||||
h_led = &profile->leds[led->index];
|
||||
if (drv_data->dev->quirks & HIDPP20_QUIRK_G502X_PLUS) {
|
||||
// On G502X+ the second slot controls the user configurable LED.
|
||||
// (Note: There is only 1 reported LED, it just happens to use 2nd index though)
|
||||
h_led = &profile->leds[1];
|
||||
} else {
|
||||
h_led = &profile->leds[led->index];
|
||||
}
|
||||
|
||||
switch (h_led->mode) {
|
||||
case HIDPP20_LED_ON:
|
||||
@@ -579,10 +585,12 @@ hidpp20drv_update_button_8100(struct ratbag_button *button)
|
||||
}
|
||||
profile->buttons[button->index].subany.type = type;
|
||||
profile->buttons[button->index].subany.subtype = subtype;
|
||||
if (subtype == HIDPP20_BUTTON_HID_TYPE_KEYBOARD)
|
||||
if (subtype == HIDPP20_BUTTON_HID_TYPE_KEYBOARD) {
|
||||
profile->buttons[button->index].keyboard_keys.modifier_flags = 0;
|
||||
profile->buttons[button->index].keyboard_keys.key = code;
|
||||
else
|
||||
} else {
|
||||
profile->buttons[button->index].consumer_control.consumer_control = code;
|
||||
}
|
||||
break;
|
||||
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL:
|
||||
code = hidpp20_onboard_profiles_get_code_from_special(action->action.special);
|
||||
@@ -689,7 +697,13 @@ hidpp20drv_update_led_8070_8071(struct ratbag_led *led, struct ratbag_profile* p
|
||||
|
||||
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
|
||||
h_profile = &drv_data->profiles->profiles[profile->index];
|
||||
h_led = &(h_profile->leds[led->index]);
|
||||
if (drv_data->dev->quirks & HIDPP20_QUIRK_G502X_PLUS) {
|
||||
// On G502X+ the second slot controls the user configurable LED.
|
||||
// (Note: There is only 1 reported LED, it just happens to use 2nd index though)
|
||||
h_led = &(h_profile->leds[1]);
|
||||
} else {
|
||||
h_led = &(h_profile->leds[led->index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!h_led)
|
||||
@@ -1420,7 +1434,7 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
|
||||
case HIDPP_PAGE_COLOR_LED_EFFECTS: {
|
||||
/* The 8070 feature implemented in the G602 doesn't follow the spec,
|
||||
* so we ignore it */
|
||||
if (ratbag_device_data_hidpp20_get_quirk(device->data) == HIDPP20_QUIRK_G602)
|
||||
if (ratbag_device_data_hidpp20_get_quirks(device->data) & HIDPP20_QUIRK_G602)
|
||||
break;
|
||||
|
||||
log_debug(ratbag, "device has color effects\n");
|
||||
@@ -1694,14 +1708,15 @@ hidpp20drv_probe(struct ratbag_device *device)
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev->quirk = ratbag_device_data_hidpp20_get_quirk(device->data);
|
||||
dev->quirks = ratbag_device_data_hidpp20_get_quirks(device->data);
|
||||
|
||||
drv_data->dev = dev;
|
||||
|
||||
log_debug(device->ratbag, "'%s' is using protocol v%d.%d\n", ratbag_device_get_name(device), dev->proto_major, dev->proto_minor);
|
||||
|
||||
if(dev->quirk != HIDPP20_QUIRK_NONE)
|
||||
log_debug(device->ratbag, "'%s' is quirked (%s)\n", ratbag_device_get_name(device), hidpp20_get_quirk_string(dev->quirk));
|
||||
/* quirks is a bitmask; log each flag that is set */
|
||||
for (uint32_t q = dev->quirks; q != 0; q &= q - 1)
|
||||
log_debug(device->ratbag, "'%s' is quirked (%s)\n", ratbag_device_get_name(device), hidpp20_get_quirk_string(q & ~(q - 1)));
|
||||
|
||||
/* add some defaults that will be overwritten by the device */
|
||||
drv_data->num_profiles = 1;
|
||||
|
||||
@@ -110,6 +110,8 @@ hidpp20_get_quirk_string(enum hidpp20_quirk quirk)
|
||||
CASE_RETURN_STRING(HIDPP20_QUIRK_NONE);
|
||||
CASE_RETURN_STRING(HIDPP20_QUIRK_G305);
|
||||
CASE_RETURN_STRING(HIDPP20_QUIRK_G602);
|
||||
CASE_RETURN_STRING(HIDPP20_QUIRK_G502X_PLUS);
|
||||
CASE_RETURN_STRING(HIDPP20_QUIRK_INDEX_OFFSET);
|
||||
}
|
||||
|
||||
abort();
|
||||
@@ -1530,7 +1532,7 @@ hidpp20_adjustable_dpi_get_dpi_list(struct hidpp20_device *device,
|
||||
.msg.parameters[0] = sensor->index,
|
||||
};
|
||||
|
||||
if (device->quirk == HIDPP20_QUIRK_G602) {
|
||||
if (device->quirks & HIDPP20_QUIRK_G602) {
|
||||
msg.msg.parameters[0] = 1;
|
||||
i = 0;
|
||||
}
|
||||
@@ -1546,7 +1548,7 @@ hidpp20_adjustable_dpi_get_dpi_list(struct hidpp20_device *device,
|
||||
get_unaligned_be_u16(&msg.msg.parameters[i]) != 0) {
|
||||
uint16_t value = get_unaligned_be_u16(&msg.msg.parameters[i]);
|
||||
|
||||
if (device->quirk == HIDPP20_QUIRK_G602 && i == 2)
|
||||
if ((device->quirks & HIDPP20_QUIRK_G602) && i == 2)
|
||||
value += 0xe000;
|
||||
|
||||
if (value > 0xe000) {
|
||||
@@ -1578,7 +1580,7 @@ hidpp20_adjustable_dpi_get_dpi(struct hidpp20_device *device,
|
||||
.msg.parameters[0] = sensor->index,
|
||||
};
|
||||
|
||||
if (device->quirk == HIDPP20_QUIRK_G602)
|
||||
if (device->quirks & HIDPP20_QUIRK_G602)
|
||||
msg.msg.parameters[0] = 1;
|
||||
|
||||
rc = hidpp20_request_command(device, &msg);
|
||||
@@ -1660,7 +1662,7 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device,
|
||||
.msg.parameters[0] = sensor->index,
|
||||
};
|
||||
|
||||
if (device->quirk == HIDPP20_QUIRK_G602)
|
||||
if (device->quirks & HIDPP20_QUIRK_G602)
|
||||
msg.msg.parameters[0] = 1;
|
||||
|
||||
set_unaligned_be_u16(&msg.msg.parameters[1], dpi);
|
||||
@@ -1802,6 +1804,7 @@ int hidpp20_adjustable_report_rate_set_report_rate(struct hidpp20_device *device
|
||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G303 0x02
|
||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900 0x03
|
||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G915 0x04
|
||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G502X 0x05
|
||||
#define HIDPP20_ONBOARD_PROFILES_MACRO_TYPE_G402 0x01
|
||||
|
||||
#define HIDPP20_USER_PROFILES_G402 0x0000
|
||||
@@ -1831,7 +1834,8 @@ union hidpp20_internal_profile {
|
||||
} name;
|
||||
struct hidpp20_internal_led leds[2]; /* G303, g502, g900 only */
|
||||
struct hidpp20_internal_led alt_leds[2];
|
||||
uint8_t free[2];
|
||||
uint8_t custom_animation_index; // G502X Plus, G705
|
||||
uint8_t free; // unused
|
||||
uint16_t crc;
|
||||
} __attribute__((packed)) profile;
|
||||
};
|
||||
@@ -2220,7 +2224,8 @@ hidpp20_onboard_profiles_validate(struct hidpp20_device *device,
|
||||
if ((info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G402) &&
|
||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G303) &&
|
||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900) &&
|
||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G915)) {
|
||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G915) &&
|
||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G502X)) {
|
||||
hidpp_log_error(&device->base,
|
||||
"Profile layout not supported: 0x%02x.\n",
|
||||
info->profile_format_id);
|
||||
@@ -2273,6 +2278,10 @@ hidpp20_onboard_profiles_allocate(struct hidpp20_device *device,
|
||||
|
||||
active_profile_index = rc;
|
||||
|
||||
/* Apply quirk for devices that return 1-indexed profile */
|
||||
if ((device->quirks & HIDPP20_QUIRK_INDEX_OFFSET) && active_profile_index > 0)
|
||||
active_profile_index--;
|
||||
|
||||
profiles = zalloc(sizeof(struct hidpp20_profiles));
|
||||
profiles->profiles = zalloc(info.profile_count * sizeof(struct hidpp20_profile));
|
||||
profiles->sector_size = info.sector_size;
|
||||
@@ -2793,7 +2802,7 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
|
||||
profiles->sector_size,
|
||||
data);
|
||||
|
||||
if (rc && device->quirk == HIDPP20_QUIRK_G305) {
|
||||
if (rc && (device->quirks & HIDPP20_QUIRK_G305)) {
|
||||
/* The G305 has a bug where it throws an ERR_INVALID_ARGUMENT
|
||||
if the sector has not been written to yet. If this happens
|
||||
we will read the ROM profiles.*/
|
||||
@@ -2959,6 +2968,18 @@ hidpp20_onboard_profiles_write_profile(struct hidpp20_device *device,
|
||||
|
||||
memcpy(pdata->profile.name.txt, profile->name, sizeof(profile->name));
|
||||
|
||||
// Mice like G502X can store custom animations onboard.
|
||||
// ratbag does not support this, so we set it to disable it to ensure
|
||||
// that the actual lighting matches the user's settings.
|
||||
if (device->quirks & HIDPP20_QUIRK_G502X_PLUS)
|
||||
{
|
||||
// Note(sewer56): There are two known mice which use this field;
|
||||
// G502X PLUS and G705. [And I only own one of these.] But it's not known how
|
||||
// prevalent this is elsewhere, so in the interest of defensive programming;
|
||||
// we're not setting this on unknown mice.
|
||||
pdata->profile.custom_animation_index = 0x00;
|
||||
}
|
||||
|
||||
rc = hidpp20_onboard_profiles_write_sector(device, sector, sector_size, data, true);
|
||||
if (rc < 0) {
|
||||
hidpp_log_error(&device->base, "failed to write profile\n");
|
||||
|
||||
@@ -51,10 +51,13 @@ struct hidpp20_feature {
|
||||
uint8_t type;
|
||||
};
|
||||
|
||||
/* Combinable flags so a device can have several at once (stored as a bitmask). */
|
||||
enum hidpp20_quirk {
|
||||
HIDPP20_QUIRK_NONE,
|
||||
HIDPP20_QUIRK_G305,
|
||||
HIDPP20_QUIRK_G602,
|
||||
HIDPP20_QUIRK_NONE = 0,
|
||||
HIDPP20_QUIRK_G305 = (1 << 0),
|
||||
HIDPP20_QUIRK_G602 = (1 << 1),
|
||||
HIDPP20_QUIRK_G502X_PLUS = (1 << 2), // G502X+ uses 2nd LED slot instead of 1st.
|
||||
HIDPP20_QUIRK_INDEX_OFFSET = (1 << 3), // Device returns 1-indexed profile, decrement by 1.
|
||||
};
|
||||
|
||||
struct hidpp20_device {
|
||||
@@ -64,7 +67,7 @@ struct hidpp20_device {
|
||||
unsigned proto_minor;
|
||||
unsigned feature_count;
|
||||
struct hidpp20_feature *feature_list;
|
||||
enum hidpp20_quirk quirk;
|
||||
uint32_t quirks; /* bitmask of enum hidpp20_quirk */
|
||||
unsigned int led_ext_caps;
|
||||
};
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ enum driver {
|
||||
|
||||
struct data_hidpp20 {
|
||||
int index;
|
||||
enum hidpp20_quirk quirk;
|
||||
uint32_t quirks; /* bitmask of enum hidpp20_quirk */
|
||||
int led_count;
|
||||
int report_rate;
|
||||
int button_count;
|
||||
@@ -100,12 +100,14 @@ struct data_steelseries {
|
||||
struct data_asus {
|
||||
int profile_count;
|
||||
int button_count;
|
||||
int button_mapping[ASUS_MAX_NUM_BUTTON];
|
||||
int button_mapping[ASUS_MAX_NUM_BUTTON * ASUS_MAX_NUM_BUTTON_GROUP];
|
||||
int led_count;
|
||||
int dpi_count;
|
||||
int is_wireless;
|
||||
struct dpi_range *dpi_range;
|
||||
uint32_t quirks;
|
||||
int led_modes[ASUS_MAX_NUM_LED_MODES];
|
||||
char *omni_signature; /* serial number prefix of mice behind an Omni receiver */
|
||||
};
|
||||
|
||||
struct ratbag_device_data {
|
||||
@@ -175,6 +177,20 @@ init_data_hidpp10(struct ratbag *ratbag,
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
hidpp20_quirk_from_string(const char *str)
|
||||
{
|
||||
if (streq(str, "G305"))
|
||||
return HIDPP20_QUIRK_G305;
|
||||
if (streq(str, "G602"))
|
||||
return HIDPP20_QUIRK_G602;
|
||||
if (streq(str, "G502X_PLUS"))
|
||||
return HIDPP20_QUIRK_G502X_PLUS;
|
||||
if (streq(str, "INDEX_OFFSET"))
|
||||
return HIDPP20_QUIRK_INDEX_OFFSET;
|
||||
return HIDPP20_QUIRK_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
init_data_hidpp20(struct ratbag *ratbag,
|
||||
GKeyFile *keyfile,
|
||||
@@ -183,7 +199,6 @@ init_data_hidpp20(struct ratbag *ratbag,
|
||||
const char *group = "Driver/hidpp20";
|
||||
GError *error = NULL;
|
||||
int num;
|
||||
char *str;
|
||||
|
||||
data->hidpp20.button_count = -1;
|
||||
data->hidpp20.index = -1;
|
||||
@@ -217,14 +232,13 @@ init_data_hidpp20(struct ratbag *ratbag,
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
|
||||
str = g_key_file_get_string(keyfile, group, "Quirk", NULL);
|
||||
data->hidpp20.quirk = HIDPP20_QUIRK_NONE;
|
||||
if (str) {
|
||||
if (streq(str, "G305"))
|
||||
data->hidpp20.quirk = HIDPP20_QUIRK_G305;
|
||||
else if(streq(str, "G602"))
|
||||
data->hidpp20.quirk = HIDPP20_QUIRK_G602;
|
||||
}
|
||||
/* Quirks are a bitmask: "Quirk" takes a ;-separated list. */
|
||||
data->hidpp20.quirks = HIDPP20_QUIRK_NONE;
|
||||
|
||||
gsize quirks_count = 0;
|
||||
_cleanup_(g_strfreevp) char **quirks = g_key_file_get_string_list(keyfile, group, "Quirk", &quirks_count, NULL);
|
||||
for (gsize i = 0; quirks && i < quirks_count; i++)
|
||||
data->hidpp20.quirks |= hidpp20_quirk_from_string(quirks[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -375,8 +389,10 @@ init_data_asus(struct ratbag *ratbag,
|
||||
data->asus.dpi_range = NULL;
|
||||
data->asus.is_wireless = -1;
|
||||
data->asus.quirks = 0;
|
||||
for (unsigned int i = 0; i < ASUS_MAX_NUM_BUTTON; i++)
|
||||
for (unsigned int i = 0; i < ASUS_MAX_NUM_BUTTON * ASUS_MAX_NUM_BUTTON_GROUP; i++)
|
||||
data->asus.button_mapping[i] = -1;
|
||||
for (unsigned int i = 0; i < ASUS_MAX_NUM_LED_MODES; i++)
|
||||
data->asus.led_modes[i] = -1;
|
||||
|
||||
int profiles = g_key_file_get_integer(keyfile, group, "Profiles", &error);
|
||||
if (!error && profiles >= 0)
|
||||
@@ -388,11 +404,20 @@ init_data_asus(struct ratbag *ratbag,
|
||||
data->asus.button_count = buttons;
|
||||
g_clear_error(&error);
|
||||
|
||||
gsize button_mapping_count = 0;
|
||||
_cleanup_(g_strfreevp) char **button_mapping = g_key_file_get_string_list(keyfile, group, "ButtonMapping", &button_mapping_count, &error);
|
||||
if (!error && button_mapping) {
|
||||
for (unsigned int i = 0; i < button_mapping_count; i++) {
|
||||
data->asus.button_mapping[i] = strtoul(button_mapping[i], NULL, 16);
|
||||
gsize btn_map_count = 0;
|
||||
_cleanup_(g_strfreevp) char **btn_map = g_key_file_get_string_list(keyfile, group, "ButtonMapping", &btn_map_count, &error);
|
||||
if (!error && btn_map) {
|
||||
for (unsigned int i = 0; i < btn_map_count; i++) {
|
||||
data->asus.button_mapping[i] = strtoul(btn_map[i], NULL, 16);
|
||||
}
|
||||
}
|
||||
g_clear_error(&error);
|
||||
|
||||
gsize btn_map_2nd_count = 0;
|
||||
_cleanup_(g_strfreevp) char **btn_map_2nd = g_key_file_get_string_list(keyfile, group, "ButtonMappingSecondary", &btn_map_2nd_count, &error);
|
||||
if (!error && btn_map_2nd) {
|
||||
for (unsigned int i = 0; i < btn_map_2nd_count; i++) {
|
||||
data->asus.button_mapping[i + ASUS_MAX_NUM_BUTTON] = strtoul(btn_map_2nd[i], NULL, 16);
|
||||
}
|
||||
}
|
||||
g_clear_error(&error);
|
||||
@@ -417,6 +442,9 @@ init_data_asus(struct ratbag *ratbag,
|
||||
data->asus.is_wireless = wireless;
|
||||
g_clear_error(&error);
|
||||
|
||||
data->asus.omni_signature = g_key_file_get_string(keyfile, group, "OmniSignature", &error);
|
||||
g_clear_error(&error);
|
||||
|
||||
gsize quirks_count = 0;
|
||||
_cleanup_(g_strfreevp) char **quirks = g_key_file_get_string_list(keyfile, group, "Quirks", &quirks_count, &error);
|
||||
if (!error && quirks) {
|
||||
@@ -425,8 +453,39 @@ init_data_asus(struct ratbag *ratbag,
|
||||
data->asus.quirks |= ASUS_QUIRK_DOUBLE_DPI;
|
||||
} else if (streq(quirks[i], "STRIX_PROFILE")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_STRIX_PROFILE;
|
||||
} else if (streq(quirks[i], "RAW_BRIGHTNESS")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_RAW_BRIGHTNESS;
|
||||
} else if (streq(quirks[i], "SEPARATE_XY_DPI")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_SEPARATE_XY_DPI;
|
||||
} else if (streq(quirks[i], "SEPARATE_LEDS")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_SEPARATE_LEDS;
|
||||
} else if (streq(quirks[i], "BUTTONS_SECONDARY")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_BUTTONS_SECONDARY;
|
||||
} else if (streq(quirks[i], "OMNI_RECEIVER")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_OMNI_RECEIVER;
|
||||
} else if (streq(quirks[i], "LED_V2")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_LED_V2;
|
||||
} else if (streq(quirks[i], "SETTINGS_V2")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_SETTINGS_V2;
|
||||
} else {
|
||||
log_debug(ratbag, "%s is invalid quirk. Ignoring...\n", quirks[i]);
|
||||
log_error(ratbag, "%s is invalid quirk. Ignoring...\n", quirks[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_clear_error(&error);
|
||||
|
||||
gsize led_modes_count = 0;
|
||||
_cleanup_(g_strfreevp) char **led_modes = g_key_file_get_string_list(keyfile, group, "LedModes", &led_modes_count, &error);
|
||||
if (!error && led_modes) {
|
||||
for (unsigned int i = 0; i < led_modes_count; i++) {
|
||||
if (streq(led_modes[i], "ON")) {
|
||||
data->asus.led_modes[i] = RATBAG_LED_ON;
|
||||
} else if (streq(led_modes[i], "BREATHING")) {
|
||||
data->asus.led_modes[i] = RATBAG_LED_BREATHING;
|
||||
} else if (streq(led_modes[i], "CYCLE")) {
|
||||
data->asus.led_modes[i] = RATBAG_LED_CYCLE;
|
||||
} else {
|
||||
log_error(ratbag, "%s is invalid LED mode. Ignoring...\n", led_modes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -704,7 +763,79 @@ out:
|
||||
return data;
|
||||
}
|
||||
|
||||
int
|
||||
ratbag_device_data_omni_signature_match(struct ratbag *ratbag,
|
||||
const char *signature,
|
||||
struct input_id *id)
|
||||
{
|
||||
struct dirent **files;
|
||||
const char *datadir;
|
||||
int n, nfiles;
|
||||
size_t best_len = 0;
|
||||
int rc = -ENODEV;
|
||||
|
||||
datadir = getenv("LIBRATBAG_DATA_DIR");
|
||||
if (!datadir)
|
||||
datadir = LIBRATBAG_DATA_DIR;
|
||||
|
||||
n = scandir(datadir, &files, filter_device_files, alphasort);
|
||||
if (n <= 0) {
|
||||
log_error(ratbag, "Unable to locate device files in %s: %s\n",
|
||||
datadir, n == 0 ? "No files found" : strerror(errno));
|
||||
return rc;
|
||||
}
|
||||
|
||||
nfiles = n;
|
||||
while (n--) {
|
||||
_cleanup_(g_key_file_freep) GKeyFile *keyfile = NULL;
|
||||
_cleanup_(g_error_freep) GError *error = NULL;
|
||||
_cleanup_(g_strfreevp) char **match_strv = NULL;
|
||||
_cleanup_free_ char *omni_signature = NULL;
|
||||
_cleanup_(freep) char *file = NULL;
|
||||
size_t len;
|
||||
unsigned int vendor, product;
|
||||
|
||||
if (xasprintf(&file, "%s/%s", datadir, files[n]->d_name) == -1)
|
||||
goto out;
|
||||
|
||||
keyfile = g_key_file_new();
|
||||
if (!g_key_file_load_from_file(keyfile, file, G_KEY_FILE_NONE, &error)) {
|
||||
log_error(ratbag, "Failed to parse keyfile %s: %s\n",
|
||||
file, error->message);
|
||||
continue;
|
||||
}
|
||||
|
||||
omni_signature = g_key_file_get_string(keyfile, "Driver/asus",
|
||||
"OmniSignature", NULL);
|
||||
if (!omni_signature)
|
||||
continue;
|
||||
|
||||
len = strlen(omni_signature);
|
||||
if (len <= best_len || strncmp(signature, omni_signature, len) != 0)
|
||||
continue;
|
||||
|
||||
match_strv = g_key_file_get_string_list(keyfile, GROUP_DEVICE,
|
||||
"DeviceMatch", NULL, NULL);
|
||||
if (!match_strv)
|
||||
continue;
|
||||
|
||||
/* the device must have a usb id to be resolvable */
|
||||
if (sscanf(match_strv[0], "usb:%x:%x", &vendor, &product) != 2)
|
||||
continue;
|
||||
|
||||
id->vendor = vendor;
|
||||
id->product = product;
|
||||
best_len = len;
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
while (nfiles--)
|
||||
free(files[nfiles]);
|
||||
free(files);
|
||||
|
||||
return rc;
|
||||
}
|
||||
/* HID++ 1.0 */
|
||||
|
||||
int
|
||||
@@ -789,12 +920,12 @@ ratbag_device_data_hidpp20_get_report_rate(const struct ratbag_device_data *data
|
||||
return data->hidpp20.report_rate;
|
||||
}
|
||||
|
||||
enum hidpp20_quirk
|
||||
ratbag_device_data_hidpp20_get_quirk(const struct ratbag_device_data *data)
|
||||
uint32_t
|
||||
ratbag_device_data_hidpp20_get_quirks(const struct ratbag_device_data *data)
|
||||
{
|
||||
assert(data->drivertype == HIDPP20);
|
||||
|
||||
return data->hidpp20.quirk;
|
||||
return data->hidpp20.quirks;
|
||||
}
|
||||
|
||||
/* SinoWealth */
|
||||
@@ -895,6 +1026,13 @@ ratbag_device_data_asus_get_led_count(const struct ratbag_device_data *data)
|
||||
return data->asus.led_count;
|
||||
}
|
||||
|
||||
const int *
|
||||
ratbag_device_data_asus_get_led_modes(const struct ratbag_device_data *data)
|
||||
{
|
||||
assert(data->drivertype == ASUS);
|
||||
return data->asus.led_modes;
|
||||
}
|
||||
|
||||
int
|
||||
ratbag_device_data_asus_get_dpi_count(const struct ratbag_device_data *data)
|
||||
{
|
||||
|
||||
@@ -90,8 +90,8 @@ ratbag_device_data_hidpp20_get_led_count(const struct ratbag_device_data *data);
|
||||
int
|
||||
ratbag_device_data_hidpp20_get_report_rate(const struct ratbag_device_data *data);
|
||||
|
||||
enum hidpp20_quirk
|
||||
ratbag_device_data_hidpp20_get_quirk(const struct ratbag_device_data *data);
|
||||
uint32_t
|
||||
ratbag_device_data_hidpp20_get_quirks(const struct ratbag_device_data *data);
|
||||
|
||||
/* SinoWealth */
|
||||
|
||||
@@ -140,6 +140,19 @@ ratbag_device_data_steelseries_get_quirk(const struct ratbag_device_data *data);
|
||||
|
||||
/* ASUS */
|
||||
|
||||
/**
|
||||
* Find the usb id of the device whose OmniSignature matches the serial
|
||||
* number of a mouse behind an Omni receiver. The longest matching prefix
|
||||
* wins. The bustype of id is left untouched, only vendor and product are
|
||||
* set.
|
||||
*
|
||||
* @return 0 on success or -ENODEV if no .device file matches
|
||||
*/
|
||||
int
|
||||
ratbag_device_data_omni_signature_match(struct ratbag *ratbag,
|
||||
const char *signature,
|
||||
struct input_id *id);
|
||||
|
||||
/**
|
||||
* @return Number of profiles
|
||||
*/
|
||||
@@ -164,6 +177,12 @@ ratbag_device_data_asus_get_button_mapping(const struct ratbag_device_data *data
|
||||
int
|
||||
ratbag_device_data_asus_get_led_count(const struct ratbag_device_data *data);
|
||||
|
||||
/**
|
||||
* @return Array of LED modes
|
||||
*/
|
||||
const int *
|
||||
ratbag_device_data_asus_get_led_modes(const struct ratbag_device_data *data);
|
||||
|
||||
/**
|
||||
* @return Number of DPI presets
|
||||
*/
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
$1 = (unsigned int *) malloc(($2 + 1) * sizeof(unsigned int));
|
||||
for (i = 0; i < $2; i++) {
|
||||
PyObject *s = PyList_GetItem($input, i);
|
||||
if (!PyInt_Check(s)) {
|
||||
if (!PyLong_Check(s)) {
|
||||
free($1);
|
||||
PyErr_SetString(PyExc_ValueError, "List items must be integers");
|
||||
return NULL;
|
||||
}
|
||||
$1[i] = PyInt_AsLong(s);
|
||||
$1[i] = PyLong_AsLong(s);
|
||||
}
|
||||
$1[i] = 0;
|
||||
}
|
||||
@@ -34,7 +34,7 @@
|
||||
%typemap(argout) (unsigned int *resolutions, size_t nres) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < $2; i++) {
|
||||
PyList_SetItem($input, i, PyInt_FromLong($1[i]));
|
||||
PyList_SetItem($input, i, PyLong_FromLong($1[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,24 +61,24 @@
|
||||
|
||||
/* uintXX_t mapping: Python -> C */
|
||||
%typemap(in) uint8_t {
|
||||
$1 = (uint8_t) PyInt_AsLong($input);
|
||||
$1 = (uint8_t) PyLong_AsLong($input);
|
||||
}
|
||||
%typemap(in) uint16_t {
|
||||
$1 = (uint16_t) PyInt_AsLong($input);
|
||||
$1 = (uint16_t) PyLong_AsLong($input);
|
||||
}
|
||||
%typemap(in) uint32_t {
|
||||
$1 = (uint32_t) PyInt_AsLong($input);
|
||||
$1 = (uint32_t) PyLong_AsLong($input);
|
||||
}
|
||||
|
||||
/* uintXX_t mapping: C -> Python */
|
||||
%typemap(out) uint8_t {
|
||||
$result = PyInt_FromLong((long) $1);
|
||||
$result = PyLong_FromLong((long) $1);
|
||||
}
|
||||
%typemap(out) uint16_t {
|
||||
$result = PyInt_FromLong((long) $1);
|
||||
$result = PyLong_FromLong((long) $1);
|
||||
}
|
||||
%typemap(out) uint32_t {
|
||||
$result = PyInt_FromLong((long) $1);
|
||||
$result = PyLong_FromLong((long) $1);
|
||||
}
|
||||
|
||||
/* Parse the header file to generate wrappers */
|
||||
|
||||
@@ -108,11 +108,14 @@ def check_profile_type_str(string: str):
|
||||
def check_section_asus(section: configparser.SectionProxy):
|
||||
permitted_keys = (
|
||||
"ButtonMapping",
|
||||
"ButtonMappingSecondary",
|
||||
"Buttons",
|
||||
"DpiRange",
|
||||
"Dpis",
|
||||
"Leds",
|
||||
"LedModes",
|
||||
"Profiles",
|
||||
"OmniSignature",
|
||||
"Quirks",
|
||||
"Wireless",
|
||||
)
|
||||
@@ -129,6 +132,13 @@ def check_section_asus(section: configparser.SectionProxy):
|
||||
quirks = (
|
||||
"DOUBLE_DPI",
|
||||
"STRIX_PROFILE",
|
||||
"RAW_BRIGHTNESS",
|
||||
"SEPARATE_XY_DPI",
|
||||
"SEPARATE_LEDS",
|
||||
"BUTTONS_SECONDARY",
|
||||
"OMNI_RECEIVER",
|
||||
"LED_V2",
|
||||
"SETTINGS_V2",
|
||||
)
|
||||
for quirk in section["Quirks"].split(";"):
|
||||
assert quirk in quirks
|
||||
@@ -136,6 +146,18 @@ def check_section_asus(section: configparser.SectionProxy):
|
||||
# No such section - not an error.
|
||||
pass
|
||||
|
||||
try:
|
||||
led_modes = (
|
||||
"ON",
|
||||
"BREATHING",
|
||||
"CYCLE",
|
||||
)
|
||||
for led_mode in section["LedModes"].split(";"):
|
||||
assert led_mode in led_modes
|
||||
except KeyError:
|
||||
# No such section - not an error.
|
||||
pass
|
||||
|
||||
|
||||
def check_section_hidpp10(section: configparser.SectionProxy):
|
||||
permitted = [
|
||||
|
||||
Reference in New Issue
Block a user