57 Commits

Author SHA1 Message Date
Filipe Laíns
55925db29e meson: bump project version to 0.9.906
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 13:29:12 +02:00
Peter Hutterer
87d4aed3ad Drop the cpp requirement and linker tests
This is a leftover from libratbag-as-a-library and obsolete now that ratbagd
is our only product. Our buildtest now is simply: "does ratbagd build?" and we
certainly shouldn't require a C++ compiler.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-07-17 07:20:36 +02:00
Peter Hutterer
7de944aaa0 Use python3-embed as dependency on Python 3.8
Python 3.8 no longer links to libpython, resulting in undefined references to
Python API.

But it provides a python3-embed.pc now, so let's try using that first and only
fall back on the normal case if that fails.

See https://github.com/mesonbuild/meson/issues/5629
2019-07-17 06:05:36 +02:00
Filipe Laíns
488774d3ba data: add logitech-g403-hero.device
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
Filipe Laíns
0673af2991 data: add logitech-g403-wireless.device
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
Filipe Laíns
0e84b63921 data: remove -over-USB from .device name and follow the layout of other .device files
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
Filipe Laíns
6e34f314f8 data: add logitech-g903-hero.device
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
Filipe Laíns
e3268f2ce6 data: add device PID to logitech-g903.device
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
Filipe Laíns
47623654d0 data: add logitech-g703-hero.device
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
Filipe Laíns
94423769b9 data: add device PID to logitech-g703.device
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
Filipe Laíns
4efe8f4830 data: add device PID to logitech-g603.device
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
Filipe Laíns
ac06e7d0c8 data: start using the device PID in logitech-g602.device
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
Filipe Laíns
f534cb55b0 data: remove logitech-gpowerplay-wireless.device
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
aTosser
bb3f386cca data: remove logitech-lightspeed.device
No longer required as G900 WPID already included in logitech-g900.device

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
aTosser
6393338d0f data: start using the device PID in logitech-g-pro-wireless.device
Changed PID for wireless PID. Necessary post Linux 5.2

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:49:01 +10:00
Filipe Laíns
b225e4bd80 hidpp20: simplify hidpp20_onboard_profiles_initialize
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-17 09:47:00 +10:00
Filipe Laíns
635257d6b8 hidpp20: improve debug messages
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-10 16:39:44 +02:00
Filipe Laíns
b31a8c5355 hidpp20: fall back to firmware profiles on a profile by profile basis
currently if any use profile is not valid we fallback to the firmware
profiles. this is quite annoying because the user might have only one
valid profile. this patch will keep valid profiles and only fallback to
firmware profiles on a profile by profile basis.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-10 16:39:44 +02:00
Ian Santopietro
412f3fef87 data: fix incorrect PID in MX Anywhere 2 2019-07-08 17:56:06 +02:00
Filipe Laíns
8f88573a08 hidpp20: fix reading onboard profiles (8100)
when we read the memory from the device we already align the offset so
that it matches the end of the sector. for ex, for a 255 sector size the
offset will be set to 255-16.
when we copy the memory (using memcpy) we just copy the bytes that will
finish filling the buffer, ignoring that the offset was aligned. we need
to copy the full 16 bytes, otherwise it will fail when sector_size does
not align with 16.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-08 10:33:53 +02:00
Filipe Laíns
c1265bc98a hidpp10: fix segfault for the c531 (and possibly other 27MHz receivers)
hidpp10_read_memory will return the HID++ error if the request fails.
right now, the error code from hidpp10_read_memory is transparently
passed through hidpp10_onboard_profiles_read_macro. This is problematic
because hidpp10_onboard_profiles_parse_macro only aborts on rc < 0 and
HID++ error are > 0.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-05 07:54:09 +10:00
Filipe Laíns
723d394c02 data: add Logitech Marathon M705
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-03 08:51:29 +10:00
Filipe Laíns
808f423600 data: add ID to MX Ergo
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-02 14:14:50 +02:00
Filipe Laíns
ae9c639a74 data: add Logitech MX518
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-02 14:14:28 +02:00
Filipe Laíns
932cbf0a5c logitech: don't show hidden features
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-02 09:55:11 +02:00
Yigit Guneli
486842b6cb data: add Logitech MX Ergo
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-06-28 18:47:08 +01:00
Ian Santopietro
2ae8233eeb data: add other Bluetooth PID to MX Anywhere 2
My MX Anywhere 2 has a different PID from the one supplied in the default .device file. This adds the PID to the device file to ensure mice with this PID get detected too.
2019-06-28 18:46:00 +01:00
Peter Hutterer
cdd70105b5 data: add a README for devices, remove the svg one
We don't ship SVGs here anymore, so let's remove that README. And instead add
one to the devices directory.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-06-17 09:44:41 +10:00
FFY00
6babb7b307 data: add other ID to MX Master 2019-05-31 18:24:25 +10:00
Pedro Vanzella
26843861c0 Add battery voltage reporting for newer mice 2019-05-29 13:50:41 +02:00
FFY00
2eed8dbb92 steelseries: only print firmware version on successful read 2019-05-28 07:57:22 +10:00
FFY00
a13ee32c61 steelseries: fix bug where we were wrongly dellocating dpi_{range,list}
_cleanup_ is deallocating the pointer returned by
ratbag_device_data_steelseries_get_dpi_{range,list}(). Deallocating
dpi_list results in a wrong step value, and a wrong step value then
results in a wrong step count when we try to set the dpi.

Fixes #436 and #702
2019-05-27 00:25:39 +01:00
Peter Hutterer
dbe98ed5b9 circleci: update to fedora 30
And install dbus-daemon manually, until we figure out how to correctly start
the new dbus-broker this will at least help us pass the tests.

And disable nss-systemd so we don't suffer from timeouts as dbus-daemon waits
for that to time out, see c425780220 for details.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-05-24 02:49:20 +01:00
Peter Hutterer
c425780220 circleci: drop libnss-systemd from Ubuntu
This is installed by software-properties-common, but since we don't
start our container with systemd, it effectively points to nowhere, adding
nothing but a delay of several minutes.

That delay affects dbus-daemon on startup and on configuration reload, it
takes several minutes to do either. ratbagctl.test installs a custom dbus
config file to be able to connect to ratbagd.devel, that config file triggers
a reload in the dbus-daemon. Since that reload takes longer than any of our
timeouts, the tests eventually fail.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-05-24 09:32:50 +10:00
Peter Hutterer
1e9839cb67 circle CI: switch to ubuntu 19.04
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-05-24 09:32:50 +10:00
FFY00
bbeaef749e meson: add 'sphinx-build' to sphinx executable name list 2019-05-24 07:16:19 +10:00
Peter Hutterer
240231b065 Error out if NDEBUG is defined
At some point meson #defined NDEBUG depending on the build type, thus
disabling asserts. libratbag relies on those, so let's error out if NDEBUG is
defined.

Related #685
2019-05-07 09:24:28 +02:00
Benjamin Tissoires
6f27053ab0 driver-hidpp20: re-enable changing the report rate
Fixes bf127d4c68

Related: #692

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2019-04-29 10:29:59 +10:00
Benjamin Tissoires
fc16a8dc7c ratabgc: handle the None value from the macro
Not sure why ratbagctl doesn't complain about it, but ratbag-command does

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2019-04-29 10:29:59 +10:00
Benjamin Tissoires
6256e9046f ratbagc: Fix a missing macro enum conversion
An overlook from 10305a123c

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2019-04-29 10:29:59 +10:00
Benjamin Tissoires
563550c473 driver-hidpp20: use the correct active dpi index
There is no guarantees the current value of dpi_index will be correct.
On my G502 the profiles are read in reverse order meaning that setting the
dpi_index can be applied to a wrong value.

Look for the correct libratbag dpi index before setting it.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2019-04-29 10:29:59 +10:00
Benjamin Tissoires
a04f2d1c24 data: update G900 and G403 for kernel v5.2+
kernel v5.2 should solve #380, finally

Fixes #380


Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2019-04-24 14:46:07 +01:00
Daniel Caujolle-Bert
d86933d746 Add MX-Anywhere-2S bluetooth IDs. 2019-04-10 12:03:45 +01:00
FFY00
55f7d75567 steelseries: fix regression in v2 led
Fixes #683
2019-04-09 12:16:48 +01:00
Rene Kjellerup
6ee1c0a591 devices: add other ID for Logitech G Pro
Fixes #684
2019-04-05 22:39:33 +01:00
Peter Hutterer
94d32930e2 ratbagd: use libunistring to convert profile names to utf-8
Where a profile name is not UTF8 compatible, let's try to convert it from
latin-1. If that fails, we just escape anything that's not ascii and move on.

Fixes #617

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-03-15 08:25:00 +01:00
Peter Hutterer
2b2d8e8980 ratbagctl: get the special name list from the enum
For two dicts x and y the merged dict can be created as {**x, **y}. We use
that to take the enum names and covert them to lowercase with hyphens instead
of underscores.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-03-12 16:33:05 +01:00
Peter Hutterer
10305a123c tools: convert our enum equivalents to python enums
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-03-12 16:33:05 +01:00
Peter Hutterer
11db35edba Fix flake8 warnings (#678)
The only notable one here is the regex that had an escape sequence

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-03-12 06:49:54 +01:00
Peter Hutterer
836922b133 ratbagd: fix property update notifications
Don't send property updates for props that don't exist anymore.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-03-08 08:39:11 +01:00
FFY00
4d00a815a4 revert "data: add Logitech G100s (#670)"
This reverts commit 0e28d82a16.
2019-03-05 22:15:42 +01:00
Filipe Laíns
0e28d82a16 data: add Logitech G100s (#670) 2019-03-05 16:57:39 +01:00
Peter Hutterer
336440cddb Install the device files in the top-level datadir
Now that the SVGs are gone, we don't need the subfolder anymore

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-03-05 09:06:05 +01:00
Peter Hutterer
b2a3d39122 libratbag: improve debugging to help with new devices
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-03-05 13:29:11 +10:00
Peter Hutterer
4b7b9d2e48 meson.build: rename the logind dep for consistency with the rest
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-03-04 20:17:06 +10:00
Andy Fitzsimon
57097ceddb updated logo look and feel
Rough update but headed in the right direction

* Simplified silhouette of bag
* Reduced number of rats inside the Rat Bag to two 
* Eyes are still small and potentially still not printable at small scale
* Introduced rough stylized logotype based on Google's Sedgwick Ave Display font
* Reduced total file size by a heap
2019-03-04 10:44:59 +10:00
FFY00
c7ce1a96a7 data: rename logitech-g900-wireless to logitech-lightspeed 2019-03-04 10:33:58 +10:00
49 changed files with 563 additions and 626 deletions

View File

@@ -34,7 +34,7 @@ libratbag_references:
name: Checking installation
command: |
PREFIX=/usr/local/
diff -u <(cd data/devices; ls *.device) <(cd $PREFIX/share/libratbag/devices; ls *.device)
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
@@ -66,7 +66,7 @@ fedora_prep_cache: &fedora_prep_cache
steps:
- run:
name: Initializing Fedora dnf cache
command: dnf install -y --downloadonly libsolv tree git gcc gcc-c++ meson check-devel libudev-devel libevdev-devel valgrind python3-gobject python3-evdev glib2-devel python3-lxml
command: dnf install -y --downloadonly libsolv tree git gcc gcc-c++ meson check-devel libudev-devel libevdev-devel valgrind python3-gobject python3-evdev glib2-devel python3-lxml libunistring-devel dbus-daemon
- persist_to_workspace:
root: /var/cache/
paths:
@@ -82,8 +82,8 @@ fedora_install: &fedora_install
command: |
echo keepcache=1 >> /etc/dnf/dnf.conf
dnf upgrade -y libsolv
dnf install -y tree git gcc gcc-c++ meson check-devel libudev-devel libevdev-devel valgrind python3-gobject python3-evdev glib2-devel python3-lxml python3-devel swig
dnf install -y tree git gcc gcc-c++ meson check-devel libudev-devel libevdev-devel valgrind python3-gobject python3-evdev glib2-devel python3-lxml python3-devel swig libunistring-devel dbus-daemon
sed -i 's/systemd//' /etc/nsswitch.conf
fedora_settings: &fedora_settings
<<: *default_settings
@@ -107,9 +107,10 @@ ubuntu_settings: &ubuntu_settings
command: |
apt-get update
apt-get install -y software-properties-common
apt-get remove -y libnss-systemd
add-apt-repository universe
apt-get update
apt-get install -y tree git gcc g++ pkg-config meson check libudev-dev libevdev-dev libsystemd-dev valgrind python3-gi python3-evdev libglib2.0-dev python3-lxml python3-dev swig systemd
apt-get install -y tree git gcc g++ pkg-config meson check libudev-dev libevdev-dev libsystemd-dev valgrind python3-gi python3-evdev libglib2.0-dev python3-lxml python3-dev swig systemd libunistring-dev
- checkout
- *start_dbus
- *build_and_test
@@ -183,23 +184,23 @@ jobs:
fedora_cache:
<<: *fedora_prep_cache
docker:
- image: fedora:28
- image: fedora:30
fedora_latest:
<<: *fedora_settings
docker:
- image: fedora:28
ubuntu_17_10:
- image: fedora:30
ubuntu_19_04:
<<: *ubuntu_settings
docker:
- image: ubuntu:artful
- image: ubuntu:19.04
doc_build:
<<: *doc_build
docker:
- image: fedora:28
- image: fedora:30
doc_deploy:
<<: *docs_deploy
docker:
- image: fedora:28
- image: fedora:30
workflows:
@@ -208,7 +209,7 @@ workflows:
jobs:
# - fedora_rawhide
- fedora_cache
- ubuntu_17_10
- ubuntu_19_04
- fedora_latest:
requires:
- fedora_cache

View File

@@ -1,17 +0,0 @@
libratbag data files
====================
This directory contains the SVG files for each theme. In general, device SVGs
should approximate the device to make it immediately recognizable. Detail work
not required, the graphic is an illustration only.
For theme-specific requirements, consult the README in the subdirectories.
Technique
---------
The simplest approach is to find a photo of the device and import it into
inkscape. Put it on the lowest layer, create a new layer "Device" above it
and start tracing the outlines and edges of the device. Fill in the shapes
and your device should resemble the underlying photo. Delete the photo
layer, add leaders and button labels and you're done.

11
data/devices/README.md Normal file
View File

@@ -0,0 +1,11 @@
libratbag data files
====================
This directory contains the data files for each supported device. libratbag
reads these files to identify the backend driver for any given device. If a
device is not listed, libratbag will not support it.
See the device.example file for instructions on the various options.
See the libratbag wiki for more information:
https://github.com/libratbag/libratbag/wiki/Adding-a-device/

View File

@@ -26,9 +26,9 @@
#
import argparse
import os
import configparser
def assertIn(element, l):
if element not in l:
raise AssertionError('{} must be in {}'.format(element, l))
@@ -61,7 +61,7 @@ def check_ledtypes_str(string):
types = string.split(';')
for t in types:
if not t: # emtpy string if trailing ;
if not t: # emtpy string if trailing ;
continue
assertIn(t, permitted_types)
@@ -88,7 +88,7 @@ def check_section_device(section):
def check_dpi_range_str(string):
import re
m = re.search('^([0-9]+):([0-9]+)@([0-9\.]+)$', string)
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))

View File

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

View File

@@ -1,4 +1,4 @@
[Device]
Name=Logitech MX Anywhere 2S
DeviceMatch=usb:046d:406a
DeviceMatch=bluetooth:046d:b01a;usb:046d:406a
Driver=hidpp20

View File

@@ -0,0 +1,5 @@
# Logitech MX Ergo
[Device]
Name=Logitech MX Ergo
DeviceMatch=bluetooth:046d:b01d;usb:046d:406f
Driver=hidpp20

View File

@@ -1,5 +1,5 @@
# Logitech MX Master
[Device]
Name=Logitech MX Master
DeviceMatch=usb:046d:4041;bluetooth:046d:b012;usb:046d:4060
DeviceMatch=usb:046d:4041;bluetooth:046d:b012;usb:046d:4060;bluetooth:046d:b017
Driver=hidpp20

View File

@@ -0,0 +1,4 @@
[Device]
Name=MX518
DeviceMatch=usb:046d:c08e
Driver=hidpp20

View File

@@ -0,0 +1,4 @@
[Device]
Name=Logitech Marathon M705
DeviceMatch=usb:046d:406d
Driver=hidpp20

View File

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

View File

@@ -1,5 +1,5 @@
[Device]
Name=Logitech Gaming Mouse G Pro
DeviceMatch=usb:046d:c085
DeviceMatch=usb:046d:c085;usb:046d:c08c
Driver=hidpp20
LedTypes=logo;side

View File

@@ -0,0 +1,4 @@
[Device]
Name=Logitech G403 Hero
DeviceMatch=usb:046d:c08f
Driver=hidpp20

View File

@@ -0,0 +1,4 @@
[Device]
Name=Logitech G403 Wireless
DeviceMatch=usb:046d:405d;usb:046d:c082
Driver=hidpp20

View File

@@ -1,5 +1,4 @@
# Logitech G403
[Device]
Name=Logitech G403
DeviceMatch=usb:046d:c082;usb:046d:c083
DeviceMatch=usb:046d:c083
Driver=hidpp20

View File

@@ -1,5 +0,0 @@
# Logitech G502 HERO over USB
[Device]
Name=Logitech G502 HERO
DeviceMatch=usb:046d:c08b
Driver=hidpp20

View File

@@ -0,0 +1,4 @@
[Device]
Name=Logitech G502 Hero
DeviceMatch=usb:046d:c08b
Driver=hidpp20

View File

@@ -1,4 +1,3 @@
# Logitech G502 Proteus Core over USB
[Device]
Name=Logitech G502 Proteus Core
DeviceMatch=usb:046d:c07d

View File

@@ -1,4 +1,3 @@
# Logitech G502 Proteus Spectrum over USB
[Device]
Name=Logitech G502 Proteus Spectrum
DeviceMatch=usb:046d:c332

View File

@@ -1,7 +1,7 @@
# Logitech G602 over wireless USB
[Device]
Name=Logitech G602
DeviceMatch=usb:046d:c537
DeviceMatch=usb:046d:402c
Driver=hidpp20
[Driver/hidpp20]

View File

@@ -1,5 +1,5 @@
# Logitech G603
[Device]
Name=Logitech G603
DeviceMatch=bluetooth:046d:b01c
DeviceMatch=usb:046d:406c;bluetooth:046d:b01c
Driver=hidpp20

View File

@@ -0,0 +1,5 @@
[Device]
Name=Logitech G703 Hero
DeviceMatch=usb:046d:4086;usb:046d:c090
Driver=hidpp20

View File

@@ -1,5 +1,5 @@
[Device]
Name=Logitech G703
DeviceMatch=usb:046d:c087
DeviceMatch=usb:046d:c087;usb:046d:4070
Driver=hidpp20

View File

@@ -1,8 +0,0 @@
# Logitech G900, G903, G603 and G403 over wireless USB
[Device]
Name=Logitech G900, G903, G603, G403
DeviceMatch=usb:046d:c539
Driver=hidpp20
[Driver/hidpp20]
DeviceIndex=1

View File

@@ -1,5 +1,5 @@
# Logitech G900 over USB
# Logitech G900
[Device]
Name=Logitech G900
DeviceMatch=usb:046d:c081
DeviceMatch=usb:046d:c081;usb:046d:4053
Driver=hidpp20

View File

@@ -0,0 +1,4 @@
[Device]
Name=Logitech G903 Hero
DeviceMatch=usb:046d:c091;usb:046d:4087
Driver=hidpp20

View File

@@ -1,5 +1,4 @@
# Logitech G903 over USB
[Device]
Name=Logitech G903
DeviceMatch=usb:046d:c086
DeviceMatch=usb:046d:c086;usb:046d:4067
Driver=hidpp20

View File

@@ -1,8 +0,0 @@
# Logitech G PowerPlay mouse pad + wireless USB receiver.
[Device]
Name=Logitech G PowerPlay mouse pad.
DeviceMatch=usb:046d:c53a
Driver=hidpp20
[Driver/hidpp20]
DeviceIndex=1

View File

@@ -1,182 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg class="ratbag-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path class="ratbag-bag" d="M38.8 22.1a48.4 48.4 0 0 1 22.7 0s9-8.9 5-11.2c-6-3.2-3.9.8-16.3 3.5 15.5-7.5 5.4-5.7-16.3-3.5-5.3.5 5 11.2 5 11.2zm20.7 2.8c5.7 17.1-.8 4.7-2-.1-4 22.1-3.7 7.7-3-.6-5-.5-10.7-.4-15.7 1.3a47 47 0 0 0-17 32.7c0 13.3 5 7.9 28.4 7.9 28.8 0 28.4 5.4 28.4-7.9 0-9.8-9-25.9-19-33.3z" />
<path class="ratbag-rats" fill="#fff" d="M35.8 62.3c3.3 3.4-1 2.4-1.9.1-5.6 1.9-16.9.7-3.8-16.3.5-.4.6.5.4 1-4 6.8-7.5 15.5.3 13.2-1-8.2 3.2-14.1 6.8-19.7 1.1-1.4 2.3-4.3 2.8-5.5-3-2.1-.8-2 1.2-1.5 1.7-1.6 3.5-2.5 6.6-3 1.7 2.5-2.7 8.2-2.7 8.2 0 2.3.1 3.7.4 4.9 3 6.5 1.2 7.3-1.4 2.9-.3.1.3 2.6-1.4 7.9.5 5.9-2.5 7-2.5 7 7.3 2.2 1 3-1 .5-.8-.5-2.9-.1-3.8.3zm15-9c.1-1.7 1.4-4 1.8-.4 2 2.1 7.5-3.4 13.3-2.2 3.7.8 5 3.3 4.5 7.4 11.7 3.8 4.3 7.9-4.6 6.9 11.8-2.5 9.3-4.1 3.5-5-.4.8-4.6 1.6-5.5 1.5-3.9 1.5-6.7 2.2-3.2-.2l-4.5-.4c-3.9 2.8-2.9 2.4-1.7-.3-2-1.4-6 1.9-6.3-.1 0-.6 1.6-5.9 2.6-7.2z"/>
<path class="ratbag-eyes" d="M51 56.9c.6.4-1 1.2-1 1.2s.1-1.6 1-1.2zm-7-22.6c-.8-.4 1-1.2 1-1.2s-.3 1.7-1 1.2z"/>
<path class="ratbag-logotype" d="M81.3 89.3c-.6.9-2.3 1.1-2.7 0 0-1.3.6-2.5.5-3.8-.5.5-1 1.6-1.6 2.3-1 1-1.8 2.4-3.4 2.3-1.3-.2-2.8-.7-3.3-2-1.3-1.8-.8-4-.5-6 .7-2.8 2.6-5.3 5.2-6.7 1.3-.4 3.2-.2 4 1.2 0 2.3-1.5 4.9-3.8 4.9-2.6-.7 1.4-3 .7-4.2-1.4-.3-1.8 1.8-2.4 2.8-.8 2-1.5 4.3-1 6.4 1.6 3.5 5-2.8 2.5-1.4-1 .7-2.9 0-1.5-1.2 1-1 2.4-1.3 3.6-2.1 5.6-2.2 3.5.3 3.7 7.5zm-18.3-6c-.1.6 2-.1 2.3.3.4.4-.4-2.2-.6-2.6zm3.6-8c1.2 4.7 2 9 3.4 13.2-.2 1-1.6 1.7-2.6 1.5-1.4-1.2-.2-2.8-1.6-4-.3-.4-3.7-.5-3.8.5l-1.4 3.2c-.6.6-2.9.9-2.5-.4.5-1.4 1-2.8 1.8-4l3.4-9.6c.5-1.3 2.3-1.2 3.3-.4zm-10.5 9.5c-.4-.8-1.3-1.5-2.3-1.4-.8-.3-.6.5-.7 1 0 1.1-.2 2.2-.4 3.3 1-.3 1.9-1 2.7-1.7.4-.2.7-.7.7-1.2zm-6.3 5.8c-1.3 0-1.2-2 0-2 0-3.5.3-7 1-10.3.6-.7 1.6-1 2.4-1.2 1 .4 1 1.4.6 2.2-.4.9 0 1.4.8.7.8-.6 1-1.6 1-2.5-.8-1.9-4.3-.3-4.8-.4-1.2-.6.3-1.5 1-1.7.8-.4 1.7-.9 2.7-.7 1.2 0 2.7-.1 3.6 1 .8 1.2.1 2.8-.6 4-.3.7-1.6 1.3-1.7 1.8 6.4 1.1.8 9.4-6 9zm-1.6-13.4c-2.1.6-.9 3.4-1.4 5-.4 2.7-.9 5.5-.8 8.3-1.3 1.3-3.5-.3-2.9-2 0-2.8.1-5.7.6-8.5.4-1.2.6-2.9-1.1-2-2 .3-2.2-2.5 0-2.2 3 .2.7-3.6 2.5-4.8 1.8-1 3.6 1 2.5 2.7.1.5-.6 1.7.4 1.5 2-.8 2.4 3 .2 2zm-12.3 5.2c-1 .6.6 1.1 1 1.5 1 1 .2-.8 0-1.2-.9-1.7-.4-2-1-.3zm3-7.2l2 9.9c.3 1.5 1.6 3.7 0 4.7-1.4.8-2.4-.5-3.3-1.4-.9-.7-1.9-1.2-2.6-2.1-1-.3-1.9 2.8-2.9 3.8-.8 0-3 .2-1.8-1 .5-1.8 1.2-3.5 1.8-5.3-1.3-1 .3-2 1-2.6a52 52 0 0 0 2.4-5.6c.7-1 2.6-1.3 3.3-.4zm-16.4 2.9v2.4c1.6-.4 4-2.4 2.2-4-1.5-1.4-2.5 0-2.2 1.6zm6.7 3.3c2 1.2.6 3.8.5 5.6-.2 2-2.5 4.1-4.3 2.3-1.2-1.1-3.7-4.3-4.1-1-.5 2.5-3.3 1.7-2.8-.6.3-2.3 1-4.6 1.2-7-.3-2.4-1-4.8-.3-7.2 1-2.7 4.4-2.5 6.4-1.3 2.3.9 3.8 3.7 2.3 6-.5 2-3.1 3.1-3.7 4.6 1.2 2 3.6 2.9 3.4-.3.3-.5.8-1 1.4-1z" />
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="180.65305mm"
height="180.65305mm"
viewBox="0 0 180.65305 180.65305"
version="1.1"
id="svg8"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="logo.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-156.7648"
inkscape:cy="473.25323"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="false"
inkscape:measure-start="0,0"
inkscape:measure-end="0,0"
inkscape:window-width="2560"
inkscape:window-height="1376"
inkscape:window-x="2560"
inkscape:window-y="27"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-to-guides="true">
<inkscape:grid
type="xygrid"
id="grid1058"
originx="-15.590431"
originy="-49.255695" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="rat right"
style="display:inline;opacity:1"
transform="translate(-15.59043,-80.129979)">
<path
sodipodi:nodetypes="sssssssssssssssccssscss"
inkscape:connector-curvature="0"
id="path1039"
d="m 181.70318,102.59719 c -3.2499,1.24415 -5.70487,5.21773 -6.1731,8.64054 -0.46127,3.37194 1.06674,8.17528 5.17162,8.92716 1.88245,0.3448 5.75552,3.71382 1.56778,2.91866 -4.41092,-0.83753 -9.60561,-1.81767 -12.03434,-5.88833 -2.51189,-4.21004 -6.0824,-2.70094 -9.60946,-1.97697 -3.61649,0.74233 -3.34262,3.70961 -0.59483,4.79149 1.76651,0.69552 -4.7698,1.02182 -6.46586,-0.31589 -0.99074,-0.7814 -4.3093,0.86964 -6.03067,0.70651 -4.14705,-0.39301 -8.0988,0.0723 -12.42874,-0.59505 -2.75134,-0.42408 -6.23873,1.52773 -5.40472,-2.94355 0.41316,-2.21506 -1.53788,-7.95327 -0.25583,-12.08908 1.43935,-4.64326 2.78762,-6.554728 6.29989,-9.291599 2.96282,-2.308725 9.62529,-5.456849 13.27656,-6.171955 5.94327,-1.163997 13.69394,2.401773 15.47361,3.054918 2.51726,0.923848 7.67473,-3.278929 11.1961,-3.200515 2.07518,-1.437388 4.50939,-5.479552 6.03783,0.452639 3.26133,0.136438 5.00967,-0.06864 9.09359,2.312711 2.76398,1.611684 4.87236,1.538272 5.34391,2.873448 0.62005,1.755647 -2.69292,5.296383 -3.28547,5.288623 -0.8492,-0.0111 -0.81394,0.0819 -2.0197,0.17649 -0.32445,1.41613 -2.05245,1.97075 -5.1013,1.61048 -1.43172,-0.16918 -2.7495,0.21878 -4.05687,0.71927 z"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1045"
d="m 119.43296,119.1374 c -3.19754,-3.4816 -3.91548,-3.31073 -5.87228,-7.17694 -1.51881,-4.76902 -1.2579,-3.59102 -4.44899,-11.00554 2.31432,2.99141 3.84563,6.48437 5.56001,9.87162 2.19923,4.34517 4.03074,4.88595 7.22829,8.36756"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="cccsc" />
<path
transform="translate(-4.1666665e-8,1.0416667e-6)"
style="display:inline;fill:#ffffff;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="m 183.59605,92.870943 c 0.70159,-0.65481 2.47893,-0.65481 2.89988,-0.187088 0.42095,0.467721 -1.82412,1.028987 -2.89988,0.187088 z"
id="path833"
inkscape:connector-curvature="0">
<animate
values="orange;red;orange"
dur="7s"
repeatCount="indefinite"
attributeName="fill" />
</path>
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="rat left"
style="display:inline;opacity:1"
transform="translate(-15.59043,-80.129979)">
<path
sodipodi:nodetypes="ccsccccccc"
inkscape:connector-curvature="0"
id="path1298"
d="m 86.198873,115.45536 c -0.640498,-1.90396 -0.324058,-5.87792 -2.548937,-9.26118 1.761266,-3.58236 5.461967,-1.0306 3.345989,-4.71668 -1.27974,-2.229332 -5.394303,-0.5453 -6.437336,0.67341 -2.968786,0.40847 -6.280299,-3.592034 -8.586349,-4.613758 -3.902419,-1.141693 -9.722226,-2.223874 -12.939723,-3.303186 -2.646277,1.694635 -1.446947,6.207524 -1.598912,7.088294 1.30852,3.28167 1.243822,1.80143 2.493275,5.51481 2.008262,2.23089 4.855928,4.59155 5.686271,9.4289 7.349678,-0.38854 9.558907,-0.59389 20.585722,-0.81061 z"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccsc"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 108.49567,117.83325 c -0.24901,-4.72058 -0.43574,-9.98729 -1.82782,-14.09082 -4.0267,-10.295998 -4.72401,-12.496029 -0.0129,-13.556767 -2.07044,-0.256651 -5.41881,-0.421857 -5.48281,2.489527 0.517,3.746632 1.94024,7.284981 3.15986,10.88015 1.56453,4.61189 1.00424,9.35889 1.25325,14.07947"
id="path955"
inkscape:connector-curvature="0" />
<path
transform="translate(-4.1666665e-8,1.0416667e-6)"
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 71.938542,102.84868 c -0.902446,-0.17526 -1.969377,-1.68007 -1.548427,-2.12186 0.867434,-0.27642 1.714682,0.92977 1.548427,2.12186 z"
id="path833-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc">
<animate
values="green;yellow;green"
dur="3s"
repeatCount="indefinite"
attributeName="fill" />
</path>
</g>
<g
inkscape:label="sack"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
transform="translate(-15.59043,-80.129979)">
<rect
ry="0.44884709"
y="172.18915"
x="1150"
height="4.8108511"
width="6.0803819"
id="rect1075"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.16499996;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
style="display:inline;opacity:1"
id="g1316"
transform="translate(-11.599497,6.3500003)">
<path
sodipodi:nodetypes="cccccczzcczc"
inkscape:connector-curvature="0"
id="path815"
d="m 71.911001,151.04073 c -13.545552,17.75365 -48.518606,24.46129 -42.445015,52.8882 4.987974,25.22201 13.988429,29.44417 56.008367,27.90906 47.288497,0.24745 47.307997,0.7217 90.436597,0.28592 14.07598,2.60143 28.63685,-20.8018 23.94043,-35.61574 -4.77259,-20.1552 -28.81931,-24.18426 -36.25354,-41.43822 -7.52218,-23.58108 1.99039,-35.03297 22.19568,-25.38895 20.20529,9.64403 26.03755,-15.82001 -11.10418,-15.33498 -37.14173,0.48503 -66.18409,-5.57956 -84.958574,-4.07459 -15.461428,0.81842 -41.712504,-2.86861 -44.765236,21.70932 2.422297,6.71408 19.985082,-12.15526 27.605897,-5.44801 7.620815,6.70724 20.413185,4.32379 -0.660426,24.50799 z"
style="display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:3.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccc"
style="display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 79.716618,142.54753 c 0,0 63.912362,8.07113 81.488252,0.7006 0,0 -0.56974,-7.74657 1.60362,-10.91212 -17.57589,7.37053 -79.821755,-0.0115 -79.821755,-0.0115 3.474504,7.01583 -3.270117,10.22298 -3.270117,10.22298 z"
id="path842"
inkscape:connector-curvature="0" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer6"
inkscape:label="rat bottom"
style="display:inline;opacity:1"
transform="translate(-15.59043,-80.129979)">
<path
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccsccccccccccccccc"
inkscape:connector-curvature="0"
id="path1212"
d="m 122.70428,243.35492 c 6.05524,1.14081 7.22067,1.31431 10.02264,2.72758 0,0.38071 -0.19945,0.89381 -1.01365,1.66697 -0.8142,0.77314 -2.6542,0.92241 -3.94953,1.25266 -0.67325,0.3643 -1.36184,1.00187 -1.50199,1.72727 3.97782,-1.45575 2.82486,-1.28103 2.75389,0.45072 0.20024,0.42037 1.54248,-1.05607 1.70256,-1.07661 1.00124,-0.41482 0.93822,0.001 1.55056,0.0319 0.20389,0.64546 -0.30382,1.34832 -0.26341,1.72391 0.84425,0.0769 1.57036,-1.33585 1.5884,-2.00591 0.34832,-0.5087 0.57096,-0.30966 1.0296,0 0.83149,0.862 0.93498,0.50569 1.95428,1.01599 2.24374,0.45044 -0.93235,-2.10713 -1.49797,-2.41992 -0.0737,-0.0369 1.39328,-2.39745 1.58909,-2.64425 2.32503,-0.403 4.75988,-1.00269 6.10414,-1.57594 v -1.2e-4 c 5.97825,1.84348 14.60207,1.47181 21.66926,1.7325 8.87347,0.60502 6.80866,4.81981 -11.94665,7.57383 29.43774,3.60709 24.29174,-11.42807 13.49975,-11.41332 -4.45874,0.0577 -12.7835,-0.12064 -21.26078,-1.9791 -1.35135,-2.33359 -1.8837,-5.9598 -1.12611,-9.63435 -2.49031,-11.667 -8.91489,-30.75707 -16.82134,-42.62455 -2.9074,-3.93147 -6.12061,-11.52979 -7.33913,-14.68828 7.81948,-5.62697 0.38705,-8.64346 -3.43515,-4.04735 -4.2835,-4.24158 -9.25924,-6.58986 -17.436457,-7.91069 -4.46939,6.75139 7.201157,21.8355 7.201157,21.8355 0.27261,11.69368 -1.47411,14.8979 -4.3435,23.39568 0.0471,0.3928 -0.49786,0.52092 -0.68357,0.83384 -0.19254,0.21312 -0.924097,1.82103 -1.179137,2.01487 -0.12771,0.23832 -0.38006,0.38366 -0.60384,0.59827 -0.23775,0.19619 -0.40433,0.49501 -0.42142,0.8292 -0.13385,0.31584 -0.17018,0.488 -0.19925,0.87639 -0.15645,0.29381 0.11002,0.40231 0.35386,0.34986 0.27783,-0.0135 0.56968,0.0505 0.82065,-0.10012 0.38688,-0.0135 0.824117,-0.32301 0.901337,-0.70099 0.0571,-0.34113 0.16568,-0.80155 0.62396,-0.6509 0.27636,0.006 0.58137,-0.16307 0.77806,0.15023 0.27193,0.12771 0.77421,0.23993 0.87876,-0.14883 0.16039,-0.42589 0.57357,-0.67322 0.67434,-1.12667 0.14254,-0.12321 0.37352,-0.19611 0.30974,-0.28545 0.26187,-0.26516 0.52474,-0.58479 0.89076,-0.74525 3.05534,-1.07719 3.51973,-4.67744 3.86462,-4.59812 0.67734,0.15577 -0.84342,6.82001 3.73079,20.85428 -1.4046,15.75023 6.7093,18.67126 6.7093,18.67126 0.17258,1.22487 -3.10226,1.32242 -3.80222,1.80721 -0.96512,0.31347 -2.42142,0.5571 -3.36241,0.16943 -0.41052,-0.20344 -1.14128,-0.10911 -0.6235,0.34889 -0.6851,0.62634 -1.75451,0.42589 -2.61368,0.63307 -0.84134,0.12395 -1.06409,1.07707 -0.0627,0.80147 -0.42125,1.18238 1.04775,0.72998 1.68923,0.70002 0.53648,-0.0399 0.30954,0.7577 0.96774,0.39958 0.92805,-0.19058 1.83353,-0.32154 2.75115,-0.51031 0.98245,-0.0454 1.60905,0.10657 2.586,0.18597 0.728,0.16342 2.43322,-0.53193 2.89833,-1.06277 0.62324,-0.55427 1.57699,-1.41676 2.07353,-2.11063 0.49656,-0.69386 0.66544,-0.53528 1.31986,-1.29795 z"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.39657527px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0"
id="path850"
d="m 109.46587,169.42014 c -0.90244,-0.17526 -1.96937,-1.68007 -1.54842,-2.12186 0.86743,-0.27642 1.71468,0.92977 1.54842,2.12186 z"
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">
<animate
values="red;blue;red"
dur="5s"
repeatCount="indefinite"
attributeName="fill" />
</path>
</g>
<!-- comment out style section to remove animated eyes-->
<style>
.ratbag-eyes{animation: color-cycle 5s linear infinite}
@keyframes color-cycle{
20%{fill: #27A269}
40%{fill: #E5A50B}
60%{fill: #EE323A}
80%{fill: #C061CA}}
</style>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -152,6 +152,3 @@ texinfo_documents = [
author, '@PACKAGE_NAME@', 'One line description of project.',
'Miscellaneous'),
]

View File

@@ -1,6 +1,6 @@
if get_option('documentation')
cmd_sphinx = find_program('sphinx-build-3', 'sphinx-build3')
cmd_sphinx = find_program('sphinx-build-3', 'sphinx-build3', 'sphinx-build')
doc_config = configuration_data()
doc_config.set('PACKAGE_NAME', meson.project_name())

View File

@@ -1,5 +1,5 @@
project('libratbag', 'c', 'cpp',
version : '0.9.905',
project('libratbag', 'c',
version : '0.9.906',
license : 'MIT/Expat',
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
meson_version : '>= 0.40.0')
@@ -28,11 +28,11 @@ liblur_so_version = '@0@.@1@.@2@'.format((liblur_so_c-liblur_so_a),
# Compiler setup
cc = meson.get_compiler('c')
cpp = meson.get_compiler('cpp')
cppflags = ['-Wno-unused-parameter', '-fvisibility=hidden']
cflags = cppflags + ['-Wmissing-prototypes', '-Wstrict-prototypes']
cflags = ['-Wno-unused-parameter',
'-fvisibility=hidden',
'-Wmissing-prototypes',
'-Wstrict-prototypes']
add_project_arguments(cflags, language: 'c')
add_project_arguments(cppflags, language: 'cpp')
# Initialize config.h, to be added to in the various options below, config.h
# is generated at the end of this file
@@ -43,7 +43,7 @@ config_h.set_quoted('FALLBACK_SVG_NAME', 'fallback.svg')
libratbag_data_dir = join_paths(get_option('prefix'),
get_option('datadir'),
'libratbag')
libratbag_data_dir_devel = join_paths(meson.source_root(), 'data')
libratbag_data_dir_devel = join_paths(meson.source_root(), 'data', 'devices')
config_h.set_quoted('LIBRATBAG_DATA_DIR', libratbag_data_dir)
# Coverity breaks because it doesn't define _Float128 correctly, you'll end
@@ -71,11 +71,12 @@ dep_udev = dependency('libudev')
dep_libevdev = dependency('libevdev')
dep_glib = dependency('glib-2.0')
dep_lm = cc.find_library('m')
dep_unistring = cc.find_library('unistring')
if get_option('logind-provider') == 'elogind'
logind_dep = dependency('libelogind', version : '>=227')
dep_logind = dependency('libelogind', version : '>=227')
else
logind_dep = dependency('libsystemd', version : '>=227')
dep_logind = dependency('libsystemd', version : '>=227')
endif
enable_systemd = get_option('systemd')
@@ -269,8 +270,10 @@ data_files = files(
'data/devices/logitech-M325.device',
'data/devices/logitech-M570.device',
'data/devices/logitech-M705.device',
'data/devices/logitech-MX-Ergo.device',
'data/devices/logitech-MX-Master.device',
'data/devices/logitech-MX-Master-2S.device',
'data/devices/logitech-MX518.device',
'data/devices/logitech-T650.device',
'data/devices/logitech-Wireless-Touchpad.device',
'data/devices/logitech-g-pro-wireless.device',
@@ -280,14 +283,16 @@ data_files = files(
'data/devices/logitech-g302.device',
'data/devices/logitech-g303.device',
'data/devices/logitech-g402.device',
'data/devices/logitech-g403-hero.device',
'data/devices/logitech-g403-wireless.device',
'data/devices/logitech-g403.device',
'data/devices/logitech-g5-2007.device',
'data/devices/logitech-g5.device',
'data/devices/logitech-g500.device',
'data/devices/logitech-g500s.device',
'data/devices/logitech-g502-HERO-over-USB.device',
'data/devices/logitech-g502-Proteus-Core-over-USB.device',
'data/devices/logitech-g502-Proteus-Spectrum-over-USB.device',
'data/devices/logitech-g502-hero.device',
'data/devices/logitech-g502-proteus-core.device',
'data/devices/logitech-g502-proteus-spectrum.device',
'data/devices/logitech-g600.device',
'data/devices/logitech-g602.device',
'data/devices/logitech-g603.device',
@@ -296,14 +301,15 @@ data_files = files(
'data/devices/logitech-g700.device',
'data/devices/logitech-g700s-wireless.device',
'data/devices/logitech-g700s.device',
'data/devices/logitech-g703-hero.device',
'data/devices/logitech-g703.device',
'data/devices/logitech-g9.device',
'data/devices/logitech-g900-wireless.device',
'data/devices/logitech-g900.device',
'data/devices/logitech-g903-hero.device',
'data/devices/logitech-g903.device',
'data/devices/logitech-g9x-[Call-of-Duty-MW3-Edition].device',
'data/devices/logitech-g9x-[Original].device',
'data/devices/logitech-gpowerplay-wireless.device',
'data/devices/logitech-Marathon-M705.device',
'data/devices/logitech-MX-Anywhere2.device',
'data/devices/logitech-MX-Anywhere2S.device',
'data/devices/roccat-kone-xtd.device',
@@ -316,7 +322,7 @@ data_files = files(
)
install_data(data_files,
install_dir : join_paths(get_option('datadir'), 'libratbag', 'devices'))
install_dir : join_paths(get_option('datadir'), 'libratbag'))
data_parse_test = find_program(join_paths(meson.source_root(), 'data/devices/data-parse-test.py'))
test('data-parse-test', data_parse_test, args: data_files)
@@ -365,30 +371,6 @@ if enable_tests
'--error-exitcode=3',
'--suppressions=' + valgrind_suppressions_file ],
timeout_multiplier: 5)
executable('test-build-cxx',
['test/build-cxx.cc'],
dependencies : [ dep_libratbag ],
include_directories : include_directories('src'),
cpp_args : ['-Wall', '-Wextra', '-Wno-unused-parameter'],
install : false)
executable('test-build-linker',
['test/build-pedantic.c'],
dependencies : [ dep_libratbag ],
include_directories : include_directories('src'),
install : false)
executable('test-build-gnuc90',
['test/build-pedantic.c'],
dependencies : [ dep_libratbag ],
include_directories : include_directories('src'),
c_args : ['-std=gnu90', '-Werror'],
install : false)
executable('test-build-pedantic',
['test/build-pedantic.c'],
dependencies : [ dep_libratbag ],
include_directories : include_directories('src'),
c_args : ['-std=c99', '-pedantic', '-Werror'],
install : false)
endif
#### ratbagd ####
@@ -410,8 +392,9 @@ src_ratbagd = [
deps_ratbagd = [
dep_udev,
logind_dep,
dep_logind,
dep_libratbag,
dep_unistring,
]
executable('ratbagd',
@@ -566,8 +549,14 @@ swig_gen = generator(
'@INPUT@'],
)
# From python 3.8 we neeed python3-embed
dep_python3 = dependency('python3-embed', required: false)
if not dep_python3.found()
dep_python3 = dependency('python3')
endif
wrapper_deps = [
dependency('python3'),
dep_python3,
dep_libratbag,
dep_libshared,
]

View File

@@ -87,17 +87,10 @@ static int ratbagd_button_set_button(sd_bus *bus,
r = ratbag_button_set_button(button->lib_button, map);
if (r == 0) {
sd_bus *bus = sd_bus_message_get_bus(m);
sd_bus_emit_properties_changed(bus,
button->path,
RATBAGD_NAME_ROOT ".Button",
"ButtonMapping",
NULL);
sd_bus_emit_properties_changed(bus,
button->path,
RATBAGD_NAME_ROOT ".Button",
"ActionType",
"Mapping",
NULL);
}
@@ -146,17 +139,10 @@ static int ratbagd_button_set_special(sd_bus *bus,
r = ratbag_button_set_special(button->lib_button, special);
if (r == 0) {
sd_bus *bus = sd_bus_message_get_bus(m);
sd_bus_emit_properties_changed(bus,
button->path,
RATBAGD_NAME_ROOT ".Button",
"SpecialMapping",
NULL);
sd_bus_emit_properties_changed(bus,
button->path,
RATBAGD_NAME_ROOT ".Button",
"ActionType",
"Mapping",
NULL);
}
@@ -261,17 +247,10 @@ static int ratbagd_button_set_macro(sd_bus *bus,
}
if (r == 0) {
sd_bus *bus = sd_bus_message_get_bus(m);
sd_bus_emit_properties_changed(bus,
button->path,
RATBAGD_NAME_ROOT ".Button",
"Macro",
NULL);
sd_bus_emit_properties_changed(bus,
button->path,
RATBAGD_NAME_ROOT ".Button",
"ActionType",
"Mapping",
NULL);
}

View File

@@ -31,6 +31,8 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistr.h>
#include <uniconv.h>
#include <systemd/sd-bus.h>
#include <systemd/sd-event.h>
#include "ratbagd.h"
@@ -382,18 +384,23 @@ ratbagd_profile_get_name(sd_bus *bus,
{
struct ratbagd_profile *profile = userdata;
const char *name = ratbag_profile_get_name(profile->lib_profile);
_cleanup_free_ char *asciiname;
_cleanup_free_ char *utf8 = NULL;
if (!name)
asciiname = strdup("");
else
/* This should really be a UTF8 check and it should really be in
* libratbag, but for now this will do to at least not kick us off
* the bus. https://github.com/libratbag/libratbag/issues/617
*/
asciiname = strdup_ascii_only(name);
if (name) {
if (u8_check((const uint8_t*)name, strlen(name)) == NULL)
utf8 = strdup(name);
else
utf8 = (char*)u8_strconv_from_encoding(name,
"ISO-8859-1",
iconveh_question_mark);
if (!utf8)
utf8 = (char*)strdup_ascii_only(name);
} else {
utf8 = strdup("");
}
CHECK_CALL(sd_bus_message_append(reply, "s", asciiname));
CHECK_CALL(sd_bus_message_append(reply, "s", utf8));
return 0;
}

View File

@@ -56,6 +56,9 @@
#define HIDPP_CAP_ONBOARD_PROFILES_8100 (1 << 6)
#define HIDPP_CAP_LED_SW_CONTROL_1300 (1 << 7)
#define HIDPP_CAP_ADJUSTIBLE_REPORT_RATE_8060 (1 << 8)
#define HIDPP_CAP_BATTERY_VOLTAGE_1001 (1 << 9)
#define HIDPP_HIDDEN_FEATURE (1 << 6)
struct hidpp20drv_data {
struct hidpp20_device *dev;
@@ -897,6 +900,34 @@ out:
return rc;
}
static int
hidpp20drv_update_report_rate_8100(struct ratbag_profile *profile, int hz)
{
struct ratbag_device *device = profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
struct hidpp20_profile *h_profile;
h_profile = &drv_data->profiles->profiles[profile->index];
h_profile->report_rate = hz;
return RATBAG_SUCCESS;
}
static int
hidpp20drv_update_report_rate(struct ratbag_profile *profile, int hz)
{
struct ratbag_device *device = profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
return hidpp20drv_update_report_rate_8100(profile, hz);
if (drv_data->capabilities & HIDPP_CAP_ADJUSTIBLE_REPORT_RATE_8060)
return -ENOTSUP;
return -ENOTSUP;
}
static int
hidpp20drv_read_special_key_mouse(struct ratbag_device *device)
{
@@ -1078,6 +1109,10 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
if (rc < 0)
return rc;
/* check if it is a hidden feature */
if (feature_type & HIDPP_HIDDEN_FEATURE)
return 0;
switch (feature) {
case HIDPP_PAGE_ROOT:
case HIDPP_PAGE_FEATURE_SET:
@@ -1121,6 +1156,22 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
drv_data->capabilities |= HIDPP_CAP_BATTERY_LEVEL_1000;
break;
}
case HIDPP_PAGE_BATTERY_VOLTAGE: {
uint16_t voltage;
enum hidpp20_battery_voltage_status status;
rc = hidpp20_batteryvoltage_get_battery_voltage(drv_data->dev, &voltage);
if (rc < 0)
return rc;
status = rc;
log_debug(ratbag, "device battery voltage is %dmv, status %02x \n",
voltage, status);
drv_data->capabilities |= HIDPP_CAP_BATTERY_VOLTAGE_1001;
break;
}
case HIDPP_PAGE_KBD_REPROGRAMMABLE_KEYS: {
log_debug(ratbag, "device has programmable keys/buttons\n");
drv_data->capabilities |= HIDPP_CAP_KBD_REPROGRAMMABLE_KEYS_1b00;
@@ -1213,9 +1264,15 @@ hidpp20drv_commit(struct ratbag_device *device)
if (!profile->dirty)
continue;
rc = hidpp20drv_update_report_rate(profile, profile->hz);
if (rc)
return RATBAG_ERROR_DEVICE;
ratbag_profile_for_each_resolution(profile, resolution) {
if (resolution->is_active)
if (resolution->is_active) {
log_raw(device->ratbag, "dpi index: %d, profile %d\n", resolution->index, profile->index);
dpi_index = resolution->index;
}
rc = hidpp20drv_update_resolution_dpi(resolution,
resolution->dpi_x,
@@ -1254,9 +1311,14 @@ hidpp20drv_commit(struct ratbag_device *device)
return RATBAG_ERROR_DEVICE;
list_for_each(profile, &device->profiles, link) {
if (profile->is_active)
if (profile->is_active) {
ratbag_profile_for_each_resolution(profile, resolution) {
if (resolution->is_active)
dpi_index = resolution->index;
}
hidpp20_onboard_profiles_set_current_dpi_index(drv_data->dev,
dpi_index);
}
}
}

View File

@@ -271,8 +271,8 @@ steelseries_probe(struct ratbag_device *device)
struct ratbag_button *button;
struct ratbag_led *led;
int rc, button_count, led_count, device_version, mono_led, short_button;
_cleanup_(dpi_list_freep) struct dpi_list *dpilist = NULL;
_cleanup_(freep) struct dpi_range *dpirange = NULL;
struct dpi_list *dpilist = NULL;
struct dpi_range *dpirange = NULL;
unsigned int report_rates[] = { 125, 250, 500, 1000 };
@@ -366,10 +366,11 @@ steelseries_probe(struct ratbag_device *device)
drv_data = zalloc(sizeof(*drv_data));
ratbag_set_drv_data(device, drv_data);
steelseries_get_firmware_version(device);
log_debug(device->ratbag, "SteelSeries firmware version %d.%d\n",
drv_data->firmware_major,
drv_data->firmware_minor);
rc = steelseries_get_firmware_version(device);
if(rc == 0)
log_debug(device->ratbag, "SteelSeries firmware version %d.%d\n",
drv_data->firmware_major,
drv_data->firmware_minor);
steelseries_read_settings(device);
@@ -572,7 +573,7 @@ steelseries_write_buttons(struct ratbag_profile *profile)
msleep(10);
if (device_version == 3)
ret = ratbag_hidraw_raw_request(device, STEELSERIES_ID_BUTTONS,
ret = ratbag_hidraw_raw_request(device, STEELSERIES_ID_BUTTONS,
buf,sizeof(buf),HID_FEATURE_REPORT,HID_REQ_SET_REPORT);
else
ret = ratbag_hidraw_output_report(device, buf, sizeof(buf));
@@ -699,7 +700,7 @@ construct_cycle_buffer(struct steelseries_led_cycle *cycle,
/* this seems to be the minimum allowed */
duration = max(buf[spec->point_count_idx] * 330, cycle->duration);
hidpp_set_unaligned_le_u16(&buf[spec->duration_idx], duration);
}
@@ -709,6 +710,7 @@ steelseries_write_led_cycle(struct ratbag_led *led,
{
struct ratbag_device *device = led->profile->device;
uint8_t buf[STEELSERIES_REPORT_SIZE] = {0};
int device_version = ratbag_device_data_steelseries_get_device_version(device->data);
int ret;
struct steelseries_led_cycle cycle;
@@ -739,7 +741,7 @@ steelseries_write_led_cycle(struct ratbag_led *led,
list_append(&cycle.points, &point[0].link);
break;
case RATBAG_LED_CYCLE:
case RATBAG_LED_CYCLE:
point[0].color = red;
point[0].pos = 0x00;
@@ -768,7 +770,7 @@ steelseries_write_led_cycle(struct ratbag_led *led,
point[2].color = black;
point[2].pos = 0x7F;
list_append(&cycle.points, &point[0].link);
list_append(&cycle.points, &point[1].link);
list_append(&cycle.points, &point[2].link);
@@ -782,8 +784,12 @@ steelseries_write_led_cycle(struct ratbag_led *led,
construct_cycle_buffer(&cycle, cycle_spec, buf, sizeof(buf));
msleep(10);
ret = ratbag_hidraw_raw_request(device, cycle_spec->cmd_val, buf,
sizeof(buf), cycle_spec->hid_report_type, HID_REQ_SET_REPORT);
if (device_version == 3)
ret = ratbag_hidraw_raw_request(device, cycle_spec->cmd_val, buf,
sizeof(buf), cycle_spec->hid_report_type, HID_REQ_SET_REPORT);
else
ret = ratbag_hidraw_output_report(device, buf, sizeof(buf));
if (ret < 0)
return ret;

View File

@@ -1161,7 +1161,7 @@ hidpp10_onboard_profiles_parse_macro(struct hidpp10_device *device,
hidpp_log_raw(&device->base, "*** macro starts at (0x%02x, 0x%04x) ***\n", page, offset);
rc = hidpp10_onboard_profiles_read_macro(device, page, offset, &macro);
if (rc < 0)
if (rc)
return rc;
count = rc;

View File

@@ -58,6 +58,7 @@ hidpp20_feature_get_name(uint16_t feature)
CASE_RETURN_STRING(HIDPP_PAGE_DEVICE_NAME);
CASE_RETURN_STRING(HIDPP_PAGE_RESET);
CASE_RETURN_STRING(HIDPP_PAGE_BATTERY_LEVEL_STATUS);
CASE_RETURN_STRING(HIDPP_PAGE_BATTERY_VOLTAGE);
CASE_RETURN_STRING(HIDPP_PAGE_KBD_REPROGRAMMABLE_KEYS);
CASE_RETURN_STRING(HIDPP_PAGE_SPECIAL_KEYS_BUTTONS);
CASE_RETURN_STRING(HIDPP_PAGE_WIRELESS_DEVICE_STATUS);
@@ -430,6 +431,40 @@ hidpp20_batterylevel_get_battery_level(struct hidpp20_device *device,
return msg.msg.parameters[2];
}
/* -------------------------------------------------------------------------- */
/* 0x1000: Battery level status */
/* -------------------------------------------------------------------------- */
#define CMD_BATTERY_VOLTAGE_GET_BATTERY_VOLTAGE 0x00
int
hidpp20_batteryvoltage_get_battery_voltage(struct hidpp20_device *device,
uint16_t *voltage)
{
uint8_t feature_index;
union hidpp20_message msg = {
.msg.report_id = REPORT_ID_SHORT,
.msg.device_idx = device->index,
.msg.address = CMD_BATTERY_VOLTAGE_GET_BATTERY_VOLTAGE,
};
int rc;
feature_index = hidpp_root_get_feature_idx(device,
HIDPP_PAGE_BATTERY_VOLTAGE);
if (feature_index == 0)
return -ENOTSUP;
msg.msg.sub_id = feature_index;
rc = hidpp20_request_command(device, &msg);
if (rc)
return rc;
*voltage = (msg.msg.parameters[0] << 8) + msg.msg.parameters[1];
return msg.msg.parameters[2];
}
/* -------------------------------------------------------------------------- */
/* 0x1300: Non-RGB led support */
/* -------------------------------------------------------------------------- */
@@ -1429,6 +1464,12 @@ int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *d
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900 0x03
#define HIDPP20_ONBOARD_PROFILES_MACRO_TYPE_G402 0x01
#define HIDPP20_USER_PROFILES_G402 0x0000
#define HIDPP20_ROM_PROFILES_G402 0x0100
#define HIDPP20_PROFILE_DIR_END 0xFFFF
#define HIDPP20_PROFILE_DIR_ENABLED 2
union hidpp20_internal_profile {
uint8_t data[HIDPP20_PROFILE_SIZE];
struct {
@@ -1499,6 +1540,8 @@ hidpp20_onboard_profiles_read_sector(struct hidpp20_device *device,
.msg.address = CMD_ONBOARD_PROFILES_MEMORY_READ,
};
hidpp_log_debug(device, "Reading sector 0x%04x\n", sector);
feature_index = hidpp_root_get_feature_idx(device,
HIDPP_PAGE_ONBOARD_PROFILES);
if (feature_index == 0)
@@ -1523,7 +1566,7 @@ hidpp20_onboard_profiles_read_sector(struct hidpp20_device *device,
return rc;
/* msg.msg.parameters is guaranteed to have a size >= 16 */
memcpy(data + offset, buf.msg.parameters, min(count, 16));
memcpy(data + offset, buf.msg.parameters, 16);
/*
* no need to check for count >= 0:
@@ -1546,6 +1589,9 @@ hidpp20_onboard_profiles_is_sector_valid(struct hidpp20_device *device,
crc = hidpp_crc_ccitt(data, sector_size - 2);
read_crc = hidpp_get_unaligned_be_u16(&data[sector_size - 2]);
if (crc != read_crc)
hidpp_log_debug(device, "Invalid CRC (%04x != %04x)\n", read_crc, crc);
return crc == read_crc;
}
@@ -2349,16 +2395,18 @@ hidpp20_onboard_profiles_parse_profile(struct hidpp20_device *device,
return 0;
}
static int
hidpp20_onboard_profiles_parse(struct hidpp20_device *device,
struct hidpp20_profiles *profiles,
uint16_t dict_address,
bool check_crc)
int
hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
struct hidpp20_profiles *profiles)
{
_cleanup_free_ uint8_t *data = NULL;
int rc;
unsigned i;
uint16_t addr;
bool crc_valid;
bool read_userdata = true;
assert(profiles);
for (i = 0; i < profiles->num_profiles; i++) {
profiles->profiles[i].address = 0;
@@ -2368,7 +2416,7 @@ hidpp20_onboard_profiles_parse(struct hidpp20_device *device,
data = hidpp20_onboard_profiles_allocate_sector(profiles);
rc = hidpp20_onboard_profiles_read_sector(device,
dict_address,
HIDPP20_USER_PROFILES_G402,
profiles->sector_size,
data);
if (rc < 0)
@@ -2377,92 +2425,64 @@ hidpp20_onboard_profiles_parse(struct hidpp20_device *device,
crc_valid = hidpp20_onboard_profiles_is_sector_valid(device,
profiles->sector_size,
data);
if (crc_valid || !check_crc) {
if (crc_valid) {
for (i = 0; i < profiles->num_profiles; i++) {
uint8_t *d = data + 4 * i;
if (d[0] == 0xFF && d[1] == 0xFF)
addr = hidpp_get_unaligned_be_u16(d);
if(addr == HIDPP20_PROFILE_DIR_END)
break;
profiles->profiles[i].address = hidpp_get_unaligned_be_u16(d);
if (profiles->profiles[i].address != (dict_address | (i + 1)))
profiles->profiles[i].address = addr;
/* profile address sanity check */
if (profiles->profiles[i].address != (HIDPP20_USER_PROFILES_G402 | (i + 1)))
hidpp_log_info(&device->base,
"profile %d: error in the address: 0x%04x instead of 0x%04x\n",
i + 1,
profiles->profiles[i].address,
dict_address | (i + 1));
profiles->profiles[i].enabled = !!d[2];
"profile %d: error in the address: 0x%04x instead of 0x%04x\n",
i + 1,
profiles->profiles[i].address,
HIDPP20_USER_PROFILES_G402 | (i + 1));
profiles->profiles[i].enabled = !!d[HIDPP20_PROFILE_DIR_ENABLED];
}
} else {
hidpp_log_debug(device, "Profile directory has an invalid CRC... Reading ROM profiles.\n");
read_userdata = false;
}
/*
* Even if the crc is wrong, we still fetch all the profiles, so as
* to have the current stored values if some profiles are legitimate.
*/
for (i = 0; i < profiles->num_profiles; i++) {
if (profiles->profiles[i].address == 0x0000) {
switch (dict_address) {
case 0x0000:
profiles->profiles[i].address = i + 1;
break;
case 0x0100:
if (i >= profiles->num_rom_profiles) {
profiles->profiles[i].address = dict_address | profiles->num_rom_profiles;
} else {
profiles->profiles[i].address = dict_address | (i + 1);
}
break;
default:
hidpp_log_error(&device->base,
"this should never happen: dict address is 0x%04x\n",
dict_address);
return -EINVAL;
}
for (i = 0; i < profiles->num_profiles; i++) {
if (read_userdata) {
hidpp_log_debug(device, "Parsing profile %u\n", i);
rc = hidpp20_onboard_profiles_parse_profile(device,
profiles,
i,
true);
/* on fail to read the user profile fallback to the default profile */
if (rc)
hidpp_log_debug("Profile %u is bad. Falling back to the ROM settings.\n", i);
else
continue;
}
/* the number of rom profiles can be different than the number of user profiles
so we if there are not enough rom profiles to populate all the user profiles
we just use the first rom profile */
if (i + 1 > profiles->num_rom_profiles)
profiles->profiles[i].address = HIDPP20_ROM_PROFILES_G402 + 1;
else
profiles->profiles[i].address = HIDPP20_ROM_PROFILES_G402 + i + 1;
rc = hidpp20_onboard_profiles_parse_profile(device,
profiles,
i,
check_crc);
if (rc == -EAGAIN)
crc_valid = false;
profiles,
i,
false);
if (rc < 0)
return rc;
}
if (check_crc && !crc_valid)
return -EAGAIN;
return 0;
}
int
hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
struct hidpp20_profiles *profiles)
{
int rc;
assert(profiles);
rc = hidpp20_onboard_profiles_parse(device, profiles, 0x0000, true);
if (rc == 0)
return profiles->num_profiles;
if (rc != -EAGAIN) {
/* something went wrong */
return rc;
}
/*
* One of the used sector has a bad crc, the device is using the ROM
* profiles.
*/
hidpp_log_debug(&device->base, "device is using ROM settings\n");
rc = hidpp20_onboard_profiles_parse(device, profiles, 0x0100, false);
if (rc < 0)
return rc;
hidpp_log_debug(&device->base, "ROM settings loaded\n");
return profiles->num_profiles;
}

View File

@@ -138,6 +138,25 @@ int hidpp20_batterylevel_get_battery_level(struct hidpp20_device *device,
uint16_t *level,
uint16_t *next_level);
/* -------------------------------------------------------------------------- */
/* 0x1001: Battery Voltage */
/* -------------------------------------------------------------------------- */
#define HIDPP_PAGE_BATTERY_VOLTAGE 0x1001
enum hidpp20_battery_voltage_status {
BATTERY_VOLTAGE_STATUS_DISCHARGING = 0,
BATTERY_VOLTAGE_STATUS_WIRELESS_CHARGING = 0x10,
BATTERY_VOLTAGE_STATUS_CHARGING = 0x80,
};
/**
* Retrieves the battery voltage
*
* @return the battery status or a negative errno on error
*/
int hidpp20_batteryvoltage_get_battery_voltage(struct hidpp20_device *device,
uint16_t *voltage);
/* -------------------------------------------------------------------------- */
/* 0x1300: LED software control */
/* -------------------------------------------------------------------------- */

View File

@@ -465,18 +465,16 @@ ratbag_device_data_new_for_id(struct ratbag *ratbag, const struct input_id *id)
struct dirent **files;
int n, nfiles;
const char *datadir;
char devicedir[PATH_MAX] = {0};
datadir = getenv("LIBRATBAG_DATA_DIR");
if (!datadir)
datadir = LIBRATBAG_DATA_DIR;
log_debug(ratbag, "Using data directory '%s'\n", datadir);
snprintf(devicedir, sizeof(devicedir), "%s/devices", datadir);
n = scandir(devicedir, &files, filter_device_files, alphasort);
n = scandir(datadir, &files, filter_device_files, alphasort);
if (n <= 0) {
log_error(ratbag, "Unable to locate device files in %s: %s\n",
devicedir, n == 0 ? "No files found" : strerror(errno));
datadir, n == 0 ? "No files found" : strerror(errno));
return NULL;
}
@@ -485,13 +483,16 @@ ratbag_device_data_new_for_id(struct ratbag *ratbag, const struct input_id *id)
_cleanup_(freep) char *file = NULL;
int rc;
rc = xasprintf(&file, "%s/%s", devicedir, files[n]->d_name);
rc = xasprintf(&file, "%s/%s", datadir, files[n]->d_name);
if (rc == -1)
goto out;
if (file_data_matches(ratbag, file, id, &data))
goto out;
}
if (!data)
log_debug(ratbag, "No data file found for %04x:%04x\n", id->vendor, id->product);
out:
while(nfiles--)
free(files[nfiles]);

View File

@@ -1260,7 +1260,7 @@ ratbag_hidraw_parse_report_descriptor(struct ratbag_device *device)
switch (hid) {
case HID_REPORT_ID:
if (hidraw->reports) {
log_debug(device->ratbag, "report ID %02x\n", content);
log_debug(device->ratbag, "HID report ID %02x\n", content);
hidraw->reports[hidraw->num_reports].report_id = content;
hidraw->reports[hidraw->num_reports].usage_page = usage_page;
hidraw->reports[hidraw->num_reports].usage = usage;
@@ -1328,6 +1328,10 @@ ratbag_open_hidraw_node(struct ratbag_device *device, struct udev_device *hidraw
goto err;
}
log_debug(device->ratbag,
"hidraw info: bus %#04x vendor %#04x product %#04x\n",
info.bustype, info.vendor, info.product);
/* check basic matching between the hidraw node and the ratbag device */
if (info.bustype != device->ids.bustype ||
(info.vendor & 0xFFFF )!= device->ids.vendor ||

View File

@@ -32,6 +32,10 @@
#include "libratbag-util.h"
#include "libratbag-hidraw.h"
#ifdef NDEBUG
#error "libratbag relies on assert(). Do not define NDEBUG"
#endif
#define RATBAG_LED_TYPE_UNKNOWN 0
void

View File

@@ -395,10 +395,12 @@ ratbag_assign_driver(struct ratbag_device *device,
if (!test_device) {
driver_name = ratbag_device_data_get_driver(device->data);
} else {
log_debug(device->ratbag, "This is a test device\n");
driver_name = "test_driver";
}
if (driver_name) {
log_debug(device->ratbag, "device assigned driver %s\n", driver_name);
rc = ratbag_test_driver(device, dev_id, driver_name, test_device);
} else {
rc = ratbag_driver_fallback_logitech(device, dev_id);
@@ -456,6 +458,8 @@ ratbag_device_new_from_udev_device(struct ratbag *ratbag,
if ((name = get_device_name(udev_device)) == 0)
goto out_err;
log_debug(ratbag, "New device: %s\n", name);
device = ratbag_device_new(ratbag, udev_device, name, &id);
if (!device || !device->data)
goto out_err;

View File

@@ -1,11 +0,0 @@
#include <libratbag.h>
/* This is a build-test only */
using namespace std;
int
main(int argc, char **argv)
{
return 0;
}

View File

@@ -1,9 +0,0 @@
#include <libratbag.h>
/* This is a build-test only */
int
main(void)
{
return 0;
}

View File

@@ -31,8 +31,8 @@ import sys
def print_ratbagctl(ratbagctl_path, ratbagd_path, version_string):
with open(ratbagctl_path, 'r', encoding='utf-8') as ratbagctl, open(ratbagd_path, 'r', encoding='utf-8') as ratbagd:
for l in ratbagctl.readlines():
if l.startswith("from ratbagd import "):
for line in ratbagctl.readlines():
if line.startswith("from ratbagd import "):
headers = True
for r in ratbagd.readlines():
if not r.startswith('#') and r.strip():
@@ -40,9 +40,9 @@ def print_ratbagctl(ratbagctl_path, ratbagd_path, version_string):
if not headers:
print(r.rstrip('\n'))
else:
if '@version@' in l:
l = l.replace('@version@', version_string)
print(l.rstrip('\n'))
if '@version@' in line:
line = line.replace('@version@', version_string)
print(line.rstrip('\n'))
def main(argv):

View File

@@ -24,6 +24,7 @@
import libratbag
import os
import sys
from enum import IntEnum
from evdev import ecodes
@@ -497,9 +498,39 @@ class RatbagdButton(metaclass=MetaRatbag):
_PREFIX = "RATBAG_BUTTON_"
MACRO_KEY_PRESS = libratbag.RATBAG_MACRO_EVENT_KEY_PRESSED
MACRO_KEY_RELEASE = libratbag.RATBAG_MACRO_EVENT_KEY_RELEASED
MACRO_WAIT = libratbag.RATBAG_MACRO_EVENT_WAIT
class ActionType(IntEnum):
NONE = libratbag.RATBAG_BUTTON_ACTION_TYPE_NONE
BUTTON = libratbag.RATBAG_BUTTON_ACTION_TYPE_BUTTON
SPECIAL = libratbag.RATBAG_BUTTON_ACTION_TYPE_SPECIAL
MACRO = libratbag.RATBAG_BUTTON_ACTION_TYPE_MACRO
class ActionSpecial(IntEnum):
INVALID = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_INVALID
UNKNOWN = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_UNKNOWN
DOUBLECLICK = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_DOUBLECLICK
WHEEL_LEFT = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_LEFT
WHEEL_RIGHT = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_RIGHT
WHEEL_UP = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_UP
WHEEL_DOWN = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_DOWN
RATCHET_MODE_SWITCH = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_RATCHET_MODE_SWITCH
RESOLUTION_CYCLE_UP = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_CYCLE_UP
RESOLUTION_CYCLE_DOWN = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_CYCLE_DOWN
RESOLUTION_UP = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_UP
RESOLUTION_DOWN = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_DOWN
RESOLUTION_ALTERNATE = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_ALTERNATE
RESOLUTION_DEFAULT = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_DEFAULT
PROFILE_CYCLE_UP = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_UP
PROFILE_CYCLE_DOWN = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_DOWN
PROFILE_UP = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_UP
PROFILE_DOWN = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_DOWN
SECOND_MODE = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_SECOND_MODE
BATTERY_LEVEL = libratbag.RATBAG_BUTTON_ACTION_SPECIAL_BATTERY_LEVEL
class Macro(IntEnum):
NONE = libratbag.RATBAG_MACRO_EVENT_NONE
KEY_PRESS = libratbag.RATBAG_MACRO_EVENT_KEY_PRESSED
KEY_RELEASE = libratbag.RATBAG_MACRO_EVENT_KEY_RELEASED
WAIT = libratbag.RATBAG_MACRO_EVENT_WAIT
"""A table mapping a button's index to its usual function as defined by X
and the common desktop environments."""
@@ -517,25 +548,25 @@ class RatbagdButton(metaclass=MetaRatbag):
@classmethod
def __late_init__(cls):
cls.SPECIAL_DESCRIPTION = {
cls.ACTION_SPECIAL_UNKNOWN: N_("Unknown"),
cls.ACTION_SPECIAL_DOUBLECLICK: N_("Doubleclick"),
cls.ACTION_SPECIAL_WHEEL_LEFT: N_("Wheel Left"),
cls.ACTION_SPECIAL_WHEEL_RIGHT: N_("Wheel Right"),
cls.ACTION_SPECIAL_WHEEL_UP: N_("Wheel Up"),
cls.ACTION_SPECIAL_WHEEL_DOWN: N_("Wheel Down"),
cls.ACTION_SPECIAL_RATCHET_MODE_SWITCH: N_("Ratchet Mode"),
cls.ACTION_SPECIAL_RESOLUTION_CYCLE_UP: N_("Cycle Resolution Up"),
cls.ACTION_SPECIAL_RESOLUTION_CYCLE_DOWN: N_("Cycle Resolution Down"),
cls.ACTION_SPECIAL_RESOLUTION_UP: N_("Resolution Up"),
cls.ACTION_SPECIAL_RESOLUTION_DOWN: N_("Resolution Down"),
cls.ACTION_SPECIAL_RESOLUTION_ALTERNATE: N_("Resolution Switch"),
cls.ACTION_SPECIAL_RESOLUTION_DEFAULT: N_("Default Resolution"),
cls.ACTION_SPECIAL_PROFILE_CYCLE_UP: N_("Cycle Profile Up"),
cls.ACTION_SPECIAL_PROFILE_CYCLE_DOWN: N_("Cycle Profile Down"),
cls.ACTION_SPECIAL_PROFILE_UP: N_("Profile Up"),
cls.ACTION_SPECIAL_PROFILE_DOWN: N_("Profile Down"),
cls.ACTION_SPECIAL_SECOND_MODE: N_("Second Mode"),
cls.ACTION_SPECIAL_BATTERY_LEVEL: N_("Battery Level"),
cls.ActionSpecial.UNKNOWN: N_("Unknown"),
cls.ActionSpecial.DOUBLECLICK: N_("Doubleclick"),
cls.ActionSpecial.WHEEL_LEFT: N_("Wheel Left"),
cls.ActionSpecial.WHEEL_RIGHT: N_("Wheel Right"),
cls.ActionSpecial.WHEEL_UP: N_("Wheel Up"),
cls.ActionSpecial.WHEEL_DOWN: N_("Wheel Down"),
cls.ActionSpecial.RATCHET_MODE_SWITCH: N_("Ratchet Mode"),
cls.ActionSpecial.RESOLUTION_CYCLE_UP: N_("Cycle Resolution Up"),
cls.ActionSpecial.RESOLUTION_CYCLE_DOWN: N_("Cycle Resolution Down"),
cls.ActionSpecial.RESOLUTION_UP: N_("Resolution Up"),
cls.ActionSpecial.RESOLUTION_DOWN: N_("Resolution Down"),
cls.ActionSpecial.RESOLUTION_ALTERNATE: N_("Resolution Switch"),
cls.ActionSpecial.RESOLUTION_DEFAULT: N_("Default Resolution"),
cls.ActionSpecial.PROFILE_CYCLE_UP: N_("Cycle Profile Up"),
cls.ActionSpecial.PROFILE_CYCLE_DOWN: N_("Cycle Profile Down"),
cls.ActionSpecial.PROFILE_UP: N_("Profile Up"),
cls.ActionSpecial.PROFILE_DOWN: N_("Profile Down"),
cls.ActionSpecial.SECOND_MODE: N_("Second Mode"),
cls.ActionSpecial.BATTERY_LEVEL: N_("Battery Level"),
}
def __init__(self, profile, id):
@@ -594,15 +625,15 @@ class RatbagdButton(metaclass=MetaRatbag):
def special(self, special):
"""Set the button mapping to the given special entry.
@param special The special entry, as one of RatbagdButton.ACTION_SPECIAL_*
@param special The special entry, as one of RatbagdButton.ActionSpecial
"""
libratbag.ratbag_button_set_special(self._button, special)
@property
def action_type(self):
"""An enum describing the action type of the button. One of
ACTION_TYPE_NONE, ACTION_TYPE_BUTTON, ACTION_TYPE_SPECIAL,
ACTION_TYPE_MACRO. This decides which
ActionType.NONE, ActionType.BUTTON, ActionType.SPECIAL,
ActionType.MACRO. This decides which
*Mapping property has a value.
"""
return libratbag.ratbag_button_get_action_type(self._button)
@@ -610,7 +641,7 @@ class RatbagdButton(metaclass=MetaRatbag):
@property
def action_types(self):
"""An array of possible values for ActionType."""
return [t for t in (RatbagdButton.ACTION_TYPE_BUTTON, RatbagdButton.ACTION_TYPE_SPECIAL, RatbagdButton.ACTION_TYPE_MACRO)
return [t for t in (RatbagdButton.ActionType.BUTTON, RatbagdButton.ActionType.SPECIAL, RatbagdButton.ActionType.MACRO)
if libratbag.ratbag_button_has_action_type(self._button, t)]
def disable(self):
@@ -630,11 +661,13 @@ class RatbagdMacro(metaclass=MetaRatbag):
_MACRO_KEY = 1000
_MACRO_DESCRIPTION = {
RatbagdButton.MACRO_KEY_PRESS: lambda key:
RatbagdButton.Macro.NONE: lambda key:
".",
RatbagdButton.Macro.KEY_PRESS: lambda key:
"↓{}".format(ecodes.KEY[key][RatbagdMacro._PREFIX_LEN:]),
RatbagdButton.MACRO_KEY_RELEASE: lambda key:
RatbagdButton.Macro.KEY_RELEASE: lambda key:
"↑{}".format(ecodes.KEY[key][RatbagdMacro._PREFIX_LEN:]),
RatbagdButton.MACRO_WAIT: lambda val:
RatbagdButton.Macro.WAIT: lambda val:
"{}ms".format(val),
_MACRO_KEY: lambda key:
"↕{}".format(ecodes.KEY[key][RatbagdMacro._PREFIX_LEN:]),
@@ -652,10 +685,10 @@ class RatbagdMacro(metaclass=MetaRatbag):
while idx < len(self._macro):
t, v = self._macro[idx]
try:
if t == RatbagdButton.MACRO_KEY_PRESS:
if t == RatbagdButton.Macro.KEY_PRESS:
# Check for a paired press/release event
t2, v2 = self._macro[idx + 1]
if t2 == RatbagdButton.MACRO_KEY_RELEASE and v == v2:
if t2 == RatbagdButton.Macro.KEY_RELEASE and v == v2:
t = self._MACRO_KEY
idx += 1
except IndexError:
@@ -683,7 +716,7 @@ class RatbagdMacro(metaclass=MetaRatbag):
for i in range(libratbag.ratbag_button_macro_get_num_events(macro_object)):
type = libratbag.ratbag_button_macro_get_event_type(macro_object, i)
value = None
if type == RatbagdButton.MACRO_WAIT:
if type == RatbagdButton.Macro.WAIT:
value = libratbag.ratbag_button_macro_get_event_timeout(macro_object, i)
else:
value = libratbag.ratbag_button_macro_get_event_key(macro_object, i)
@@ -714,21 +747,27 @@ class RatbagdLed(metaclass=MetaRatbag):
_PREFIX = "RATBAG_LED_"
MODE_OFF = libratbag.RATBAG_LED_OFF
MODE_ON = libratbag.RATBAG_LED_ON
MODE_CYCLE = libratbag.RATBAG_LED_CYCLE
MODE_BREATHING = libratbag.RATBAG_LED_BREATHING
class Mode(IntEnum):
OFF = libratbag.RATBAG_LED_OFF
ON = libratbag.RATBAG_LED_ON
CYCLE = libratbag.RATBAG_LED_CYCLE
BREATHING = libratbag.RATBAG_LED_BREATHING
class ColorDepth(IntEnum):
MONOCHROME = libratbag.RATBAG_LED_COLORDEPTH_MONOCHROME
RGB_888 = libratbag.RATBAG_LED_COLORDEPTH_RGB_888
RGB_111 = libratbag.RATBAG_LED_COLORDEPTH_RGB_111
LED_DESCRIPTION = {
# Translators: the LED is off.
MODE_OFF: N_("Off"),
Mode.OFF: N_("Off"),
# Translators: the LED has a single, solid color.
MODE_ON: N_("Solid"),
Mode.ON: N_("Solid"),
# Translators: the LED is cycling between red, green and blue.
MODE_CYCLE: N_("Cycle"),
Mode.CYCLE: N_("Cycle"),
# Translators: the LED's is pulsating a single color on different
# brightnesses.
MODE_BREATHING: N_("Breathing"),
Mode.BREATHING: N_("Breathing"),
}
def __init__(self, profile, id):
@@ -746,16 +785,16 @@ class RatbagdLed(metaclass=MetaRatbag):
@property
def mode(self):
"""This led's mode, one of MODE_OFF, MODE_ON, MODE_CYCLE and
MODE_BREATHING."""
"""This led's mode, one of Mode.OFF, Mode.ON, Mode.CYCLE and
Mode.BREATHING."""
return libratbag.ratbag_led_get_mode(self._led)
@mode.setter
def mode(self, mode):
"""Set the led's mode to the given mode.
@param mode The new mode, as one of MODE_OFF, MODE_ON, MODE_CYCLE and
MODE_BREATHING.
@param mode The new mode, as one of Mode.OFF, Mode.ON, Mode.CYCLE and
Mode.BREATHING.
"""
libratbag.ratbag_led_set_mode(self._led, mode)
@@ -776,7 +815,7 @@ class RatbagdLed(metaclass=MetaRatbag):
@property
def colordepth(self):
"""An enum describing this led's colordepth, one of
RatbagdLed.COLORDEPTH_MONOCHROME, RatbagdLed.COLORDEPTH_RGB"""
RatbagdLed.ColorDepth.MONOCHROME, RatbagdLed.ColorDepth.RGB"""
return libratbag.ratbag_led_get_colordepth(self._led)
@property

View File

@@ -32,28 +32,9 @@ from ratbagd import Ratbagd, RatbagdDevice, RatbagdProfile, RatbagdMacro, Ratbag
button_specials_strmap = {
RatbagdButton.ACTION_SPECIAL_UNKNOWN: "unknown",
RatbagdButton.ACTION_SPECIAL_DOUBLECLICK: "doubleclick",
RatbagdButton.ACTION_SPECIAL_WHEEL_LEFT: "wheel-left",
RatbagdButton.ACTION_SPECIAL_WHEEL_RIGHT: "wheel-right",
RatbagdButton.ACTION_SPECIAL_WHEEL_UP: "wheel-up",
RatbagdButton.ACTION_SPECIAL_WHEEL_DOWN: "wheel-down",
RatbagdButton.ACTION_SPECIAL_RATCHET_MODE_SWITCH: "ratchet-mode-switch",
RatbagdButton.ACTION_SPECIAL_RESOLUTION_CYCLE_UP: "resolution-cycle-up",
RatbagdButton.ACTION_SPECIAL_RESOLUTION_CYCLE_DOWN: "resolution-cycle-down",
RatbagdButton.ACTION_SPECIAL_RESOLUTION_UP: "resolution-up",
RatbagdButton.ACTION_SPECIAL_RESOLUTION_DOWN: "resolution-down",
RatbagdButton.ACTION_SPECIAL_RESOLUTION_ALTERNATE: "resolution-alternate",
RatbagdButton.ACTION_SPECIAL_RESOLUTION_DEFAULT: "resolution-default",
RatbagdButton.ACTION_SPECIAL_PROFILE_CYCLE_UP: "profile-cycle-up",
RatbagdButton.ACTION_SPECIAL_PROFILE_CYCLE_DOWN: "profile-cycle-down",
RatbagdButton.ACTION_SPECIAL_PROFILE_UP: "profile-up",
RatbagdButton.ACTION_SPECIAL_PROFILE_DOWN: "profile-down",
RatbagdButton.ACTION_SPECIAL_SECOND_MODE: "second-mode",
RatbagdButton.ACTION_SPECIAL_BATTERY_LEVEL: "battery-level",
**{e: e.name.lower().replace("_", "-") for e in RatbagdButton.ActionSpecial},
**{e.name.lower().replace("_", "-"): e for e in RatbagdButton.ActionSpecial}
}
for k, v in [(v, k) for k, v in button_specials_strmap.items()]:
button_specials_strmap[k] = v
def list_devices(r, args):
@@ -121,34 +102,34 @@ def find_led(r, args):
def print_led(d, p, l, level):
leds = {
RatbagdLed.MODE_BREATHING: "breathing",
RatbagdLed.MODE_CYCLE: "cycle",
RatbagdLed.MODE_OFF: "off",
RatbagdLed.MODE_ON: "on",
RatbagdLed.Mode.BREATHING: "breathing",
RatbagdLed.Mode.CYCLE: "cycle",
RatbagdLed.Mode.OFF: "off",
RatbagdLed.Mode.ON: "on",
}
depths = {
RatbagdLed.COLORDEPTH_MONOCHROME: "monochrome",
RatbagdLed.COLORDEPTH_RGB_888: "rgb",
RatbagdLed.COLORDEPTH_RGB_111: "rgb111",
RatbagdLed.ColorDepth.MONOCHROME: "monochrome",
RatbagdLed.ColorDepth.RGB_888: "rgb",
RatbagdLed.ColorDepth.RGB_111: "rgb111",
}
if l.mode == RatbagdLed.MODE_OFF:
if l.mode == RatbagdLed.Mode.OFF:
print(" " * level + "LED: {}, depth: {}, mode: {}".format(l.index,
depths[l.colordepth],
leds[l.mode]))
elif l.mode == RatbagdLed.MODE_ON:
elif l.mode == RatbagdLed.Mode.ON:
print(" " * level + "LED: {}, depth: {}, mode: {}, color: {:02x}{:02x}{:02x}".format(l.index,
depths[l.colordepth],
leds[l.mode],
l.color[0],
l.color[1],
l.color[2]))
elif l.mode == RatbagdLed.MODE_CYCLE:
elif l.mode == RatbagdLed.Mode.CYCLE:
print(" " * level + "LED: {}, depth: {}, mode: {}, duration: {}, brightness: {}".format(l.index,
depths[l.colordepth],
leds[l.mode],
l.effect_duration,
l.brightness))
elif l.mode == RatbagdLed.MODE_BREATHING:
elif l.mode == RatbagdLed.Mode.BREATHING:
print(" " * level + "LED: {}, depth: {}, mode: {}, color: {:02x}{:02x}{:02x}, duration: {}, brightness: {}".format(l.index,
depths[l.colordepth],
leds[l.mode],
@@ -161,10 +142,10 @@ def print_led(d, p, l, level):
def print_led_caps(d, p, l, level):
leds = {
RatbagdLed.MODE_BREATHING: "breathing",
RatbagdLed.MODE_CYCLE: "cycle",
RatbagdLed.MODE_OFF: "off",
RatbagdLed.MODE_ON: "on",
RatbagdLed.Mode.BREATHING: "breathing",
RatbagdLed.Mode.CYCLE: "cycle",
RatbagdLed.Mode.OFF: "off",
RatbagdLed.Mode.ON: "on",
}
supported = sorted([v for k, v in leds.items() if k in l.modes])
print(" " * level + "Modes: {}".format(", ".join(supported)))
@@ -173,13 +154,13 @@ def print_led_caps(d, p, l, level):
def print_button(d, p, b, level):
header = " " * level + "Button: {} is mapped to ".format(b.index)
if b.action_type == RatbagdButton.ACTION_TYPE_BUTTON:
if b.action_type == RatbagdButton.ActionType.BUTTON:
print("{}'button {}'".format(header, b.mapping))
elif b.action_type == RatbagdButton.ACTION_TYPE_SPECIAL:
elif b.action_type == RatbagdButton.ActionType.SPECIAL:
print("{}'{}'".format(header, button_specials_strmap[b.special]))
elif b.action_type == RatbagdButton.ACTION_TYPE_MACRO:
elif b.action_type == RatbagdButton.ActionType.MACRO:
print("{}macro '{}'".format(header, str(b.macro)))
elif b.action_type == RatbagdButton.ACTION_TYPE_NONE:
elif b.action_type == RatbagdButton.ActionType.NONE:
print("{}none".format(header))
else:
print("{}UNKNOWN".format(header))
@@ -279,10 +260,10 @@ def func_led_set(r, args):
pass
else:
leds = {
"breathing": RatbagdLed.MODE_BREATHING,
"cycle": RatbagdLed.MODE_CYCLE,
"off": RatbagdLed.MODE_OFF,
"on": RatbagdLed.MODE_ON,
"breathing": RatbagdLed.Mode.BREATHING,
"cycle": RatbagdLed.Mode.CYCLE,
"off": RatbagdLed.Mode.OFF,
"on": RatbagdLed.Mode.ON,
}
l.mode = leds[mode]
try:
@@ -336,7 +317,7 @@ def func_button_action_set_special(r, args):
def func_button_action_set_macro(r, args):
b, p, d = find_button(r, args)
if not b.ACTION_TYPE_MACRO in b.action_types:
if not b.ActionType.MACRO in b.action_types:
raise RatbagErrorCapability("assigning a macro is not supported on this device")
macro_keys = args.target_macro
@@ -360,7 +341,7 @@ def func_button_action_set_macro(r, args):
if is_timeout:
t = int(s[1:])
macro.append(RatbagdButton.MACRO_WAIT, t)
macro.append(RatbagdButton.Macro.WAIT, t)
else:
if not s.startswith("KEY_") and not s.startswith("BTN_"):
msg = "Don't know how to convert {}".format(s)
@@ -368,9 +349,9 @@ def func_button_action_set_macro(r, args):
code = evdev.ecodes.ecodes[s]
if is_press:
macro.append(RatbagdButton.MACRO_KEY_PRESS, code)
macro.append(RatbagdButton.Macro.KEY_PRESS, code)
if is_release:
macro.append(RatbagdButton.MACRO_KEY_RELEASE, code)
macro.append(RatbagdButton.Macro.KEY_RELEASE, code)
b.macro = macro
commit(d, args)
@@ -418,6 +399,7 @@ def func_report_rate_get_all(r, args):
def func_report_rate_set(r, args):
p, d = find_profile(r, args)
p.report_rate = args.rate_n
commit(d, args)
def func_resolution_get(r, args):

View File

@@ -595,35 +595,39 @@ class RatbagdResolution(_RatbagdDBus):
class RatbagdButton(_RatbagdDBus):
"""Represents a ratbagd button."""
ACTION_TYPE_NONE = 0
ACTION_TYPE_BUTTON = 1
ACTION_TYPE_SPECIAL = 2
ACTION_TYPE_MACRO = 4
class ActionType(IntEnum):
NONE = 0
BUTTON = 1
SPECIAL = 2
MACRO = 4
ACTION_SPECIAL_INVALID = -1
ACTION_SPECIAL_UNKNOWN = (1 << 30)
ACTION_SPECIAL_DOUBLECLICK = (1 << 30) + 1
ACTION_SPECIAL_WHEEL_LEFT = (1 << 30) + 2
ACTION_SPECIAL_WHEEL_RIGHT = (1 << 30) + 3
ACTION_SPECIAL_WHEEL_UP = (1 << 30) + 4
ACTION_SPECIAL_WHEEL_DOWN = (1 << 30) + 5
ACTION_SPECIAL_RATCHET_MODE_SWITCH = (1 << 30) + 6
ACTION_SPECIAL_RESOLUTION_CYCLE_UP = (1 << 30) + 7
ACTION_SPECIAL_RESOLUTION_CYCLE_DOWN = (1 << 30) + 8
ACTION_SPECIAL_RESOLUTION_UP = (1 << 30) + 9
ACTION_SPECIAL_RESOLUTION_DOWN = (1 << 30) + 10
ACTION_SPECIAL_RESOLUTION_ALTERNATE = (1 << 30) + 11
ACTION_SPECIAL_RESOLUTION_DEFAULT = (1 << 30) + 12
ACTION_SPECIAL_PROFILE_CYCLE_UP = (1 << 30) + 13
ACTION_SPECIAL_PROFILE_CYCLE_DOWN = (1 << 30) + 14
ACTION_SPECIAL_PROFILE_UP = (1 << 30) + 15
ACTION_SPECIAL_PROFILE_DOWN = (1 << 30) + 16
ACTION_SPECIAL_SECOND_MODE = (1 << 30) + 17
ACTION_SPECIAL_BATTERY_LEVEL = (1 << 30) + 18
class ActionSpecial(IntEnum):
INVALID = -1
UNKNOWN = (1 << 30)
DOUBLECLICK = (1 << 30) + 1
WHEEL_LEFT = (1 << 30) + 2
WHEEL_RIGHT = (1 << 30) + 3
WHEEL_UP = (1 << 30) + 4
WHEEL_DOWN = (1 << 30) + 5
RATCHET_MODE_SWITCH = (1 << 30) + 6
RESOLUTION_CYCLE_UP = (1 << 30) + 7
RESOLUTION_CYCLE_DOWN = (1 << 30) + 8
RESOLUTION_UP = (1 << 30) + 9
RESOLUTION_DOWN = (1 << 30) + 10
RESOLUTION_ALTERNATE = (1 << 30) + 11
RESOLUTION_DEFAULT = (1 << 30) + 12
PROFILE_CYCLE_UP = (1 << 30) + 13
PROFILE_CYCLE_DOWN = (1 << 30) + 14
PROFILE_UP = (1 << 30) + 15
PROFILE_DOWN = (1 << 30) + 16
SECOND_MODE = (1 << 30) + 17
BATTERY_LEVEL = (1 << 30) + 18
MACRO_KEY_PRESS = 1
MACRO_KEY_RELEASE = 2
MACRO_WAIT = 3
class Macro(IntEnum):
NONE = 0
KEY_PRESS = 1
KEY_RELEASE = 2
WAIT = 3
"""A table mapping a button's index to its usual function as defined by X
and the common desktop environments."""
@@ -637,33 +641,33 @@ class RatbagdButton(_RatbagdDBus):
"""A table mapping a special function to its human-readable description."""
SPECIAL_DESCRIPTION = {
ACTION_SPECIAL_INVALID: N_("Invalid"),
ACTION_SPECIAL_UNKNOWN: N_("Unknown"),
ACTION_SPECIAL_DOUBLECLICK: N_("Doubleclick"),
ACTION_SPECIAL_WHEEL_LEFT: N_("Wheel Left"),
ACTION_SPECIAL_WHEEL_RIGHT: N_("Wheel Right"),
ACTION_SPECIAL_WHEEL_UP: N_("Wheel Up"),
ACTION_SPECIAL_WHEEL_DOWN: N_("Wheel Down"),
ACTION_SPECIAL_RATCHET_MODE_SWITCH: N_("Ratchet Mode"),
ACTION_SPECIAL_RESOLUTION_CYCLE_UP: N_("Cycle Resolution Up"),
ACTION_SPECIAL_RESOLUTION_CYCLE_DOWN: N_("Cycle Resolution Down"),
ACTION_SPECIAL_RESOLUTION_UP: N_("Resolution Up"),
ACTION_SPECIAL_RESOLUTION_DOWN: N_("Resolution Down"),
ACTION_SPECIAL_RESOLUTION_ALTERNATE: N_("Resolution Switch"),
ACTION_SPECIAL_RESOLUTION_DEFAULT: N_("Default Resolution"),
ACTION_SPECIAL_PROFILE_CYCLE_UP: N_("Cycle Profile Up"),
ACTION_SPECIAL_PROFILE_CYCLE_DOWN: N_("Cycle Profile Down"),
ACTION_SPECIAL_PROFILE_UP: N_("Profile Up"),
ACTION_SPECIAL_PROFILE_DOWN: N_("Profile Down"),
ACTION_SPECIAL_SECOND_MODE: N_("Second Mode"),
ACTION_SPECIAL_BATTERY_LEVEL: N_("Battery Level"),
ActionSpecial.INVALID: N_("Invalid"),
ActionSpecial.UNKNOWN: N_("Unknown"),
ActionSpecial.DOUBLECLICK: N_("Doubleclick"),
ActionSpecial.WHEEL_LEFT: N_("Wheel Left"),
ActionSpecial.WHEEL_RIGHT: N_("Wheel Right"),
ActionSpecial.WHEEL_UP: N_("Wheel Up"),
ActionSpecial.WHEEL_DOWN: N_("Wheel Down"),
ActionSpecial.RATCHET_MODE_SWITCH: N_("Ratchet Mode"),
ActionSpecial.RESOLUTION_CYCLE_UP: N_("Cycle Resolution Up"),
ActionSpecial.RESOLUTION_CYCLE_DOWN: N_("Cycle Resolution Down"),
ActionSpecial.RESOLUTION_UP: N_("Resolution Up"),
ActionSpecial.RESOLUTION_DOWN: N_("Resolution Down"),
ActionSpecial.RESOLUTION_ALTERNATE: N_("Resolution Switch"),
ActionSpecial.RESOLUTION_DEFAULT: N_("Default Resolution"),
ActionSpecial.PROFILE_CYCLE_UP: N_("Cycle Profile Up"),
ActionSpecial.PROFILE_CYCLE_DOWN: N_("Cycle Profile Down"),
ActionSpecial.PROFILE_UP: N_("Profile Up"),
ActionSpecial.PROFILE_DOWN: N_("Profile Down"),
ActionSpecial.SECOND_MODE: N_("Second Mode"),
ActionSpecial.BATTERY_LEVEL: N_("Battery Level"),
}
def __init__(self, object_path):
_RatbagdDBus.__init__(self, "Button", object_path)
def _on_properties_changed(self, proxy, changed_props, invalidated_props):
if "ActionType" in changed_props.keys():
if "Mapping" in changed_props.keys():
self.notify("action-type")
def _mapping(self):
@@ -679,7 +683,7 @@ class RatbagdButton(_RatbagdDBus):
"""An integer of the current button mapping, if mapping to a button
or None otherwise."""
type, button = self._mapping()
if type != RatbagdButton.ACTION_TYPE_BUTTON:
if type != RatbagdButton.ActionType.BUTTON:
return None
return button
@@ -691,14 +695,14 @@ class RatbagdButton(_RatbagdDBus):
"""
button = GLib.Variant("u", button)
self._set_dbus_property("Mapping", "(uv)",
(RatbagdButton.ACTION_TYPE_BUTTON, button))
(RatbagdButton.ActionType.BUTTON, button))
@GObject.Property
def macro(self):
"""A RatbagdMacro object representing the currently set macro or
None otherwise."""
type, macro = self._mapping()
if type != RatbagdButton.ACTION_TYPE_MACRO:
if type != RatbagdButton.ActionType.MACRO:
return None
return RatbagdMacro.from_ratbag(macro)
@@ -712,14 +716,14 @@ class RatbagdButton(_RatbagdDBus):
"""
macro = GLib.Variant("a(uu)", macro.keys)
self._set_dbus_property("Mapping", "(uv)",
(RatbagdButton.ACTION_TYPE_MACRO, macro))
(RatbagdButton.ActionType.MACRO, macro))
@GObject.Property
def special(self):
"""An enum describing the current special mapping, if mapped to
special or None otherwise."""
type, special = self._mapping()
if type != RatbagdButton.ACTION_TYPE_SPECIAL:
if type != RatbagdButton.ActionType.SPECIAL:
return None
return special
@@ -727,17 +731,17 @@ class RatbagdButton(_RatbagdDBus):
def special(self, special):
"""Set the button mapping to the given special entry.
@param special The special entry, as one of RatbagdButton.ACTION_SPECIAL_*
@param special The special entry, as one of RatbagdButton.ActionSpecial
"""
special = GLib.Variant("u", special)
self._set_dbus_property("Mapping", "(uv)",
(RatbagdButton.ACTION_TYPE_SPECIAL, special))
(RatbagdButton.ActionType.SPECIAL, special))
@GObject.Property
def action_type(self):
"""An enum describing the action type of the button. One of
ACTION_TYPE_NONE, ACTION_TYPE_BUTTON, ACTION_TYPE_SPECIAL,
ACTION_TYPE_MACRO. This decides which
ActionType.NONE, ActionType.BUTTON, ActionType.SPECIAL,
ActionType.MACRO. This decides which
*Mapping property has a value.
"""
type, mapping = self._mapping()
@@ -765,11 +769,11 @@ class RatbagdMacro(GObject.Object):
_MACRO_KEY = 1000
_MACRO_DESCRIPTION = {
RatbagdButton.MACRO_KEY_PRESS: lambda key:
RatbagdButton.Macro.KEY_PRESS: lambda key:
"↓{}".format(ecodes.KEY[key][RatbagdMacro._PREFIX_LEN:]),
RatbagdButton.MACRO_KEY_RELEASE: lambda key:
RatbagdButton.Macro.KEY_RELEASE: lambda key:
"↑{}".format(ecodes.KEY[key][RatbagdMacro._PREFIX_LEN:]),
RatbagdButton.MACRO_WAIT: lambda val:
RatbagdButton.Macro.WAIT: lambda val:
"{}ms".format(val),
_MACRO_KEY: lambda key:
"↕{}".format(ecodes.KEY[key][RatbagdMacro._PREFIX_LEN:]),
@@ -793,10 +797,10 @@ class RatbagdMacro(GObject.Object):
while idx < len(self._macro):
t, v = self._macro[idx]
try:
if t == RatbagdButton.MACRO_KEY_PRESS:
if t == RatbagdButton.Macro.KEY_PRESS:
# Check for a paired press/release event
t2, v2 = self._macro[idx + 1]
if t2 == RatbagdButton.MACRO_KEY_RELEASE and v == v2:
if t2 == RatbagdButton.Macro.KEY_RELEASE and v == v2:
t = self._MACRO_KEY
idx += 1
except IndexError:
@@ -855,25 +859,27 @@ class RatbagdLed(_RatbagdDBus):
TYPE_DPI = 4
TYPE_WHEEL = 5
MODE_OFF = 0
MODE_ON = 1
MODE_CYCLE = 2
MODE_BREATHING = 3
class Mode(IntEnum):
OFF = 0
ON = 1
CYCLE = 2
BREATHING = 3
COLORDEPTH_MONOCHROME = 0
COLORDEPTH_RGB_888 = 1
COLORDEPTH_RGB_111 = 2
class ColorDepth(IntEnum):
MONOCHROME = 0
RGB_888 = 1
RGB_111 = 2
LED_DESCRIPTION = {
# Translators: the LED is off.
MODE_OFF: N_("Off"),
Mode.OFF: N_("Off"),
# Translators: the LED has a single, solid color.
MODE_ON: N_("Solid"),
Mode.ON: N_("Solid"),
# Translators: the LED is cycling between red, green and blue.
MODE_CYCLE: N_("Cycle"),
Mode.CYCLE: N_("Cycle"),
# Translators: the LED's is pulsating a single color on different
# brightnesses.
MODE_BREATHING: N_("Breathing"),
Mode.BREATHING: N_("Breathing"),
}
def __init__(self, object_path):
@@ -886,16 +892,16 @@ class RatbagdLed(_RatbagdDBus):
@GObject.Property
def mode(self):
"""This led's mode, one of MODE_OFF, MODE_ON, MODE_CYCLE and
MODE_BREATHING."""
"""This led's mode, one of Mode.OFF, Mode.ON, Mode.CYCLE and
Mode.BREATHING."""
return self._get_dbus_property("Mode")
@mode.setter
def mode(self, mode):
"""Set the led's mode to the given mode.
@param mode The new mode, as one of MODE_OFF, MODE_ON, MODE_CYCLE and
MODE_BREATHING.
@param mode The new mode, as one of Mode.OFF, Mode.ON, Mode.CYCLE and
Mode.BREATHING.
"""
self._set_dbus_property("Mode", "u", mode)
@@ -920,7 +926,7 @@ class RatbagdLed(_RatbagdDBus):
@GObject.Property
def colordepth(self):
"""An enum describing this led's colordepth, one of
RatbagdLed.COLORDEPTH_MONOCHROME, RatbagdLed.COLORDEPTH_RGB"""
RatbagdLed.ColorDepth.MONOCHROME, RatbagdLed.ColorDepth.RGB"""
return self._get_dbus_property("ColorDepth")
@GObject.Property