38 Commits
v0.12 ... v0.13

Author SHA1 Message Date
Filipe Laíns
42787ee422 meson: libratbag 0.13
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-02-09 23:32:55 +00:00
Filipe Laíns
611dd9be0d hidpp20: keep unsupported effects
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-02-09 23:31:42 +00:00
Filipe Laíns
fd20f9e642 hidpp20: simplify hidpp20_onboard_profiles_write_led
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-02-09 23:31:42 +00:00
Filipe Laíns
9be5576967 hidpp20: add some missing led effects
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-02-09 23:31:42 +00:00
Filipe Laíns
9fe511fcc5 hidpp20: add profile field to special bindings in onboard profiles
New devices define a profile field in the button configuration. This
allows us to map a button to set the target profile as active. Even
though we don't support configuring this right now, some devices, such
as the G915/G815, come pre-configured with this action on th M-Keys.
This patch makes us able to read and write those settings, this way they
don't get lost when we write a profile to the device.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-02-09 23:31:42 +00:00
Filipe Laíns
f0b69aab19 hidpp20: only set active resolution if there are resolutions on 0x8100
This prevents us from trying to set a resolution on keyboards.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-02-09 23:31:42 +00:00
Filipe Laíns
7610b80ced hidpp20: log errors when failed to write sector
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-02-09 23:31:42 +00:00
Filipe Laíns
f0a05bb522 data: add the Logitech G Powerplay
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-02-10 08:24:10 +10:00
Torbjørn Fylling
2669cc28b2 data: add support for Logitech G815 keyboard 2020-01-31 10:13:37 +00:00
Peter Hutterer
302702d94a Declare a bunch of structs as extern
gcc 10 complains about multiple definitions of these when linking.

/usr/bin/ld: libhidpp.a(src_hidpp-generic.c.o):/builddir/build/BUILD/libratbag-0.12/x86_64-redhat-linux-gnu/../src/libratbag-private.h:588:
multiple definition of `etekcity_driver';
libutil.a(src_libratbag-util.c.o):/builddir/build/BUILD/libratbag-0.12/x86_64-redhat-linux-gnu/../src/libratbag-private.h:588:
first defined here

Special case here is the test_driver struct, without the extern gcc seems to
think it's a new struct with all zeros, causing a segfault when we then try to
strcmp the test driver name.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2020-01-29 02:12:28 +00:00
Filipe Laíns
e1136c4d30 hidpp20: add debug log when failed to read led (8070, getZoneEffects)
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-28 21:41:45 +01:00
Filipe Laíns
0012853a1d hidpp20: make sure getZoneEffect (8070) is supported
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-28 21:41:45 +01:00
Filipe Laíns
afb85f868c hidpp20: change unsupported effect log msg to debug verbosity
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-28 21:41:45 +01:00
Filipe Laíns
b76fcdadde hidpp20: enable 0x8070 (ColorLedEffects) standalone use
0x8071 is still missing but as of now we don't have any device that
needs it.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-28 21:41:45 +01:00
Stephan Lachnit
ba7c092ee2 driver-hidpp20: replace goto with return
Signed-off-by: Stephan Lachnit <stephanlachnit@protonmail.com>
2020-01-08 07:36:52 +10:00
Stephan Lachnit
3483bd8c14 driver-hidpp20: minor cleanup
Removes useless setting of the dpi index when updating resolutions.
Removes weird empty line.

Signed-off-by: Stephan Lachnit <stephanlachnit@protonmail.com>
2020-01-08 07:36:52 +10:00
Filipe Laíns
0fb0eb3d42 hidpp20: log errors in hidpp20drv_commit
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-06 19:22:57 +00:00
Filipe Laíns
5fb1f4429d ratbagd: log error if failed to commit
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-06 19:22:57 +00:00
Filipe Laíns
5f5e294598 hidpp20: add support for reading/writing the report rate via 0x8060
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-06 19:18:06 +00:00
Filipe Laíns
b4218737cd hidpp20: fix bug that was unsetting some capabilities
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-06 19:18:06 +00:00
Filipe Laíns
3875bb70fd hidpp20: implement dirty flag for report rate
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-06 19:13:01 +00:00
Filipe Laíns
e9d67b7235 ratbag: add dirty flag for report rate
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-06 19:13:01 +00:00
Filipe Laíns
8a476a8724 hidpp: fix supported_report_types data type
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-03 22:40:03 +00:00
Sadika Sumanapala
d67cbec5f8 Add M590 bluetooth ID 2020-01-03 08:17:43 +10:00
Stephan Lachnit
f82c6f72b6 Use EditorConfig instead of vim comments
Signed-off-by: Stephan Lachnit <stephanlachnit@protonmail.com>
2019-12-24 08:04:11 +10:00
Stephan Lachnit
af30fc28cd CircleCI: use variables for dependencies
Use separate variable lists for dependencies.
Uninstall check merged in upstream meson, so it can be simplified.
`libsolv` doesn't need to be updated any more with Fedora 31.

Signed-off-by: Stephan Lachnit <stephanlachnit@protonmail.com>
2019-12-24 07:34:18 +10:00
Filipe Laíns
3fb8a51456 docs: adjust description to say we support other devices than mice
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-12-23 06:26:55 +10:00
Matthias Bach
ceaa3c3ad5 Reorder the initialisation of the ratbagd client
When the API version mismatches we want to fail early before performing
any more complex initialisation. We do however have to check for
devices first so that we can distinguish cases where we cannot access
the daemon from those where it is too old to provide an API version.
2019-12-22 16:58:20 +00:00
Matthias Bach
551b918ba8 Give a more specific error message if user cannot reach ratbagd via D-BUS
If access failed, e.g. due to insufficient permissions, don't confuse
the user by reporting an API mismatch.

This is a minimal improvement to target issue #802. As, if access is
restricted to a group, that group is known in Meson, it would even be
possible to report that group in the error message. But, that would
require converting ratbagd.py to a template or finding some other way to
inject that information at build time.
2019-12-22 16:58:20 +00:00
Filipe Laíns
3105428ba1 tests: fix data parse for hidpp index
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-12-20 10:30:10 +01:00
Benjamin Tissoires
b3f2406180 data: add G910
Same situation than the G513, 0x8100 is not present.
But heh.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2019-12-20 09:15:24 +00:00
Benjamin Tissoires
902160f430 ratbag-command fixes
- File "./build/ratbag-command", line 2289, in open_ratbagd
    r = Ratbagd(1)
  TypeError: __init__() takes 1 positional argument but 2 were given
- AttributeError: module 'libratbag' has no attribute
  'ratbag_device_get_bus'
- File "./build/ratbag-command", line 267, in model
    return "{}:{04x}:{04x}:{d}".format(bus, vid, pid, version)
  KeyError: '04x'
- swig/python detected a memory leak of type 'uint32_t *', no destructor
  found.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2019-12-19 15:56:52 +01:00
Filipe Laíns
fd6d0b6198 data: add G513
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-12-19 13:58:02 +01:00
Filipe Laíns
5ed98fdb22 hidpp20: only enable 0x8070 or 0x8071 if 0x8100 is present
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-12-19 13:58:02 +01:00
Filipe Laíns
e0e73c2971 data: add G915
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-12-19 12:06:15 +00:00
Filipe Laíns
0d3b4f1b64 libratbag: add 'switches' led type
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-12-19 12:06:15 +00:00
Filipe Laíns
20b6e3deeb hidpp20: only populate resolutions if the device supports
This patch moves the 0x8100 initialization routine out of
hidpp20drv_init_feature because it needs the capabilities to be
processed first.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-12-19 12:05:54 +00:00
Filipe Laíns
ffcdee912d libratbag: allow no resolutions
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-12-19 12:05:54 +00:00
34 changed files with 555 additions and 140 deletions

View File

@@ -1,5 +1,10 @@
# vim: set expandtab shiftwidth=2 tabstop=8:
libratbag_references:
build_dependencies: &build_dependencies
FEDORA_DEP_BUILD: gcc gcc-c++ meson dbus-daemon glib2-devel json-glib-devel libevdev-devel libudev-devel libunistring-devel python3-devel python3-evdev swig
FEDORA_DEP_TEST: check-devel python3-gobject python3-lxml valgrind
FEDORA_DEP_DOC: python3-sphinx python3-sphinx_rtd_theme
UBUNTU_DEP_BUILD: gcc g++ meson pkg-config systemd libevdev-dev libglib2.0-dev libjson-glib-dev libsystemd-dev libudev-dev libunistring-dev python3-dev python3-evdev swig
UBUNTU_DEP_TEST: check python3-gi python3-lxml valgrind
default_settings: &default_settings
working_directory: ~/libratbag
environment:
@@ -52,10 +57,7 @@ libratbag_references:
name: Checking if any files are left after uninstall
command: |
PREFIX=/root/test_install
# workaround until https://github.com/mesonbuild/meson/pull/2033 is merged
# and a new release appears
git clone https://github.com/whot/meson -b wip/remove-directories-on-uninstall
./meson/meson.py build_install --prefix=$PREFIX
meson build_install --prefix=$PREFIX
ninja -C build_install install
ninja -C build_install uninstall
if [ -d $PREFIX ]
@@ -78,11 +80,13 @@ 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 libunistring-devel dbus-daemon json-glib-devel diffutils
command: dnf install -y --downloadonly git ${FEDORA_DEP_BUILD} ${FEDORA_DEP_TEST} ${FEDORA_DEP_DOC}
- persist_to_workspace:
root: /var/cache/
paths:
- dnf/*
environment:
*build_dependencies
fedora_fetch_cache: &fedora_fetch_cache
attach_workspace:
@@ -93,8 +97,7 @@ fedora_install: &fedora_install
name: Install prerequisites
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 libunistring-devel dbus-daemon json-glib-devel diffutils
dnf install -y git ${FEDORA_DEP_BUILD} ${FEDORA_DEP_TEST}
sed -i 's/systemd//' /etc/nsswitch.conf
fedora_settings: &fedora_settings
@@ -111,7 +114,8 @@ fedora_settings: &fedora_settings
- *build_buildtype_plain
- *build_buildtype_release
- *export_logs
environment:
*build_dependencies
ubuntu_settings: &ubuntu_settings
<<: *default_settings
@@ -124,7 +128,7 @@ ubuntu_settings: &ubuntu_settings
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 libunistring-dev libjson-glib-dev
apt-get install -y git ${UBUNTU_DEP_BUILD} ${UBUNTU_DEP_TEST}
- checkout
- *start_dbus
- *build_and_test
@@ -134,6 +138,8 @@ ubuntu_settings: &ubuntu_settings
- *build_buildtype_plain
- *build_buildtype_release
- *export_logs
environment:
*build_dependencies
doc_build: &doc_build
<<: *default_settings
@@ -142,7 +148,7 @@ doc_build: &doc_build
- *fedora_install
- run:
name: Install documentation build-deps
command: dnf install -y python3-sphinx python3-sphinx_rtd_theme
command: dnf install -y ${FEDORA_DEP_DOC}
- checkout
- *build_with_docs
- *export_logs
@@ -152,6 +158,8 @@ doc_build: &doc_build
root: build
paths:
- doc/html/*
environment:
*build_dependencies
docs_deploy: &docs_deploy
<<: *default_settings

20
.editorconfig Normal file
View File

@@ -0,0 +1,20 @@
root = true
[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
[*.{c,h}]
indent_style = tab
tab_width = 8
trim_trailing_whitespace = true
[{*.{py,py.in},tools/ratbagctl.*.in}]
indent_style = space
indent_size = 4
[*.{yml,xsl}]
indent_style = space
indent_size = 2

View File

@@ -3,9 +3,10 @@ libratbag
<img src="https://libratbag.github.io/_images/logo.svg" alt="" width="30%" align="right">
libratbag provides **ratbagd**, a DBus daemon to configure gaming mice.
The daemon provides a generic way to access the various features exposed by
these mice and abstracts away hardware-specific and kernel-specific quirks.
libratbag provides **ratbagd**, a DBus daemon to configure input devices,
mainly gaming mice. The daemon provides a generic way to access the various
features exposed by these mice and abstracts away hardware-specific and
kernel-specific quirks.
libratbag currently supports devices from Logitech, Etekcity, GSkill,
Roccat, Steelseries. See [the device

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3
# vim: set expandtab shiftwidth=4 tabstop=4:
#
# Copyright © 2017 Red Hat, Inc.
#
@@ -58,7 +57,7 @@ def check_match_str(string):
def check_ledtypes_str(string):
permitted_types = ['logo', 'side', 'battery', 'dpi']
permitted_types = ['logo', 'side', 'battery', 'dpi', 'switches']
types = string.split(';')
for t in types:
@@ -138,9 +137,8 @@ def check_section_hidpp10(section):
pass
try:
index = int(section['DeviceIndex'])
# 10 is arbitrarily chosen
assert(index > 0 and index < 10)
index = int(section['DeviceIndex'], 16)
assert(index > 0 and index <= 0xff)
except KeyError:
pass
@@ -175,9 +173,8 @@ def check_section_hidpp20(section):
assertIn(key, permitted)
try:
index = int(section['DeviceIndex'])
# 10 is arbitrarily chosen
assert(index > 0 and index < 10)
index = int(section['DeviceIndex'], 16)
assert(index > 0 and index <= 0xff)
except KeyError:
pass

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3
# vim: set expandtab shiftwidth=4 tabstop=4:
#
# Copyright © 2018 Red Hat, Inc.
#

View File

@@ -1,5 +1,5 @@
# Logitech M585/M590
[Device]
Name=Logitech M585/M590
DeviceMatch=usb:046d:406b
DeviceMatch=usb:046d:406b;bluetooth:046d:b01b
Driver=hidpp20

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,8 @@
[Device]
Name=Logitech G910
DeviceMatch=usb:046d:c335
LedTypes=logo;switches
Driver=hidpp20
[Driver/hidpp20]
DeviceIndex=ff

View File

@@ -0,0 +1,8 @@
[Device]
Name=Logitech G915
DeviceMatch=usb:046d:c33e
LedTypes=logo;switches
Driver=hidpp20
[Driver/hidpp20]
DeviceIndex=1

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3
# vim: set expandtab shiftwidth=4 tabstop=4:
#
# Copyright © 2018 Red Hat, Inc.
#

View File

@@ -1,5 +1,5 @@
project('libratbag', 'c',
version : '0.12',
version : '0.13',
license : 'MIT/Expat',
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
meson_version : '>= 0.40.0')
@@ -291,6 +291,7 @@ data_files = files(
'data/devices/logitech-MX518.device',
'data/devices/logitech-T650.device',
'data/devices/logitech-Wireless-Touchpad.device',
'data/devices/logitech-g-powerplay.device',
'data/devices/logitech-g-pro-wireless.device',
'data/devices/logitech-g-pro.device',
'data/devices/logitech-g102-g203.device',
@@ -310,6 +311,7 @@ data_files = files(
'data/devices/logitech-g502-hero.device',
'data/devices/logitech-g502-proteus-core.device',
'data/devices/logitech-g502-proteus-spectrum.device',
'data/devices/logitech-g513.device',
'data/devices/logitech-g600.device',
'data/devices/logitech-g602.device',
'data/devices/logitech-g603.device',
@@ -324,6 +326,9 @@ data_files = files(
'data/devices/logitech-g900.device',
'data/devices/logitech-g903-hero.device',
'data/devices/logitech-g903.device',
'data/devices/logitech-g815.device',
'data/devices/logitech-g910.device',
'data/devices/logitech-g915.device',
'data/devices/logitech-g9x-Call-of-Duty-MW3-Edition.device',
'data/devices/logitech-g9x-Original.device',
'data/devices/logitech-Marathon-M705.device',

View File

@@ -172,6 +172,8 @@ static void ratbagd_device_commit_pending(void *data)
int r;
r = ratbag_device_commit(device->lib_device);
if (r)
log_error("error committing device (%d)\n", r);
if (r < 0)
ratbagd_device_resync(device, device->ctx->bus);
ratbagd_device_unref(device);

View File

@@ -170,7 +170,7 @@ static void parse_led_member(JsonObject *obj, const gchar *name,
if (streq(name, "type")) {
gboolean v = json_object_get_int_member(obj, name);
if (v < 0 || v > RATBAG_LED_TYPE_WHEEL)
if (v < 0 || v > RATBAG_LED_TYPE_SWITCHES)
parser_error("type");
led->type = v;

View File

@@ -69,6 +69,7 @@ struct hidpp20drv_data {
unsigned num_controls;
struct hidpp20_control_id *controls;
struct hidpp20_profiles *profiles;
struct hidpp20_led *leds;
union hidpp20_generic_led_zone_info led_infos;
unsigned int report_rates[4];
@@ -334,14 +335,24 @@ static void
hidpp20drv_read_led_8070(struct ratbag_led *led, struct hidpp20drv_data* drv_data)
{
struct hidpp20_profile *profile;
struct hidpp20_led *h_led;
struct hidpp20_led h_led_val;
struct hidpp20_led *h_led = &h_led_val;
struct hidpp20_color_led_zone_info* led_info;
struct hidpp20_color_led_info info;
int rc;
led_info = &drv_data->led_infos.color_leds_8070[led->index];
profile = &drv_data->profiles->profiles[led->profile->index];
h_led = &profile->leds[led->index];
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
profile = &drv_data->profiles->profiles[led->profile->index];
h_led = &profile->leds[led->index];
} else {
rc = hidpp20_color_led_effects_get_zone_effect(drv_data->dev, led->index, h_led);
if (rc) {
log_debug(led->profile->device->ratbag,
"Failed to read led settings\n");
}
}
switch (h_led->mode) {
case HIDPP20_LED_ON:
@@ -397,10 +408,10 @@ hidpp20drv_read_led_8070(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING);
break;
default:
log_bug_libratbag(led->profile->device->ratbag,
"%s: Unknown effect id %d\n",
led->profile->device->name,
ei.effect_id);
log_debug(led->profile->device->ratbag,
"%s: Unsupported effect (%d)\n",
led->profile->device->name,
ei.effect_id);
break;
}
}
@@ -472,10 +483,10 @@ hidpp20drv_read_led_8071(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING);
break;
default:
log_bug_libratbag(led->profile->device->ratbag,
"%s: Unknown effect id %d\n",
led->profile->device->name,
ei.effect_id);
log_debug(led->profile->device->ratbag,
"%s: Unsupported effect (%d)\n",
led->profile->device->name,
ei.effect_id);
break;
}
}
@@ -691,11 +702,13 @@ hidpp20drv_update_led_8070_8071(struct ratbag_led *led, struct ratbag_profile* p
struct hidpp20drv_data *drv_data)
{
struct hidpp20_profile *h_profile;
struct hidpp20_led *h_led;
struct hidpp20_led h_led_val;
struct hidpp20_led *h_led = &h_led_val;
h_profile = &drv_data->profiles->profiles[profile->index];
h_led = &(h_profile->leds[led->index]);
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 (!h_led)
return -EINVAL;
@@ -720,6 +733,13 @@ hidpp20drv_update_led_8070_8071(struct ratbag_led *led, struct ratbag_profile* p
h_led->period = led->ms;
h_led->brightness = led->brightness * 100 / 255;
if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)) {
if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070)
hidpp20_color_led_effects_set_zone_effect(drv_data->dev,
led->index,
h_led_val);
}
return RATBAG_SUCCESS;
}
@@ -822,9 +842,12 @@ hidpp20drv_read_report_rate_8060(struct ratbag_device *device)
{
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
struct ratbag *ratbag = device->ratbag;
struct ratbag_profile *profile;
uint8_t bitflags_ms;
int nrates = 0;
int rc;
uint8_t rate_ms;
unsigned rate_hz;
rc = hidpp20_adjustable_report_rate_get_report_rate_list(drv_data->dev,
&bitflags_ms);
@@ -843,6 +866,37 @@ hidpp20drv_read_report_rate_8060(struct ratbag_device *device)
drv_data->num_report_rates = nrates;
if (!hidpp20_adjustable_report_rate_get_report_rate(drv_data->dev, &rate_ms)) {
switch (rate_ms)
{
case 1:
rate_hz = 1000;
break;
case 2:
case 3: /* 3ms = 333.(3)Hz, we round to 500Hz */
rate_hz = 500;
break;
case 4:
case 5: /* 5ms = 200Hz, we round to 250Hz */
rate_hz = 250;
break;
case 6: /* 6ms = 166.(6)Hz, we round to 125Hz */
case 7: /* 7ms = 142Hz, we round to 125Hz */
case 8:
rate_hz = 125;
break;
default:
rate_hz = 0;
break;
}
if (rate_hz) {
log_debug(ratbag, "report rate is %u\n", rate_hz);
ratbag_device_for_each_profile(device, profile)
profile->hz = rate_hz;
}
}
log_debug(ratbag, "device has %d report rates\n", nrates);
return 0;
@@ -943,7 +997,7 @@ hidpp20drv_update_resolution_dpi(struct ratbag_resolution *resolution,
struct ratbag_device *device = profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
struct hidpp20_sensor *sensor;
int rc, i;
int i;
int dpi = dpi_x; /* dpi_x == dpi_y if we don't have the individual resolution cap */
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
@@ -959,14 +1013,13 @@ hidpp20drv_update_resolution_dpi(struct ratbag_resolution *resolution,
sensor = &drv_data->sensors[0];
/* validate that the sensor accepts the given DPI */
rc = -EINVAL;
if (dpi < sensor->dpi_min || dpi > sensor->dpi_max)
goto out;
return -EINVAL;
if (sensor->dpi_steps) {
for (i = sensor->dpi_min; i < dpi; i += sensor->dpi_steps) {
}
if (i != dpi)
goto out;
return -EINVAL;
} else {
i = 0;
while (sensor->dpi_list[i]) {
@@ -974,13 +1027,24 @@ hidpp20drv_update_resolution_dpi(struct ratbag_resolution *resolution,
break;
}
if (sensor->dpi_list[i] != dpi)
goto out;
return -EINVAL;
}
rc = hidpp20_adjustable_dpi_set_sensor_dpi(drv_data->dev, sensor, dpi);
return hidpp20_adjustable_dpi_set_sensor_dpi(drv_data->dev, sensor, dpi);
}
out:
return rc;
static int
hidpp20drv_update_report_rate_8060(struct ratbag_profile *profile, int hz)
{
struct ratbag_device *device = profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
int rc;
rc = hidpp20_adjustable_report_rate_set_report_rate(drv_data->dev, 1000/hz);
if (rc)
return rc;
return RATBAG_SUCCESS;
}
static int
@@ -1001,12 +1065,20 @@ 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);
int rc;
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;
if (drv_data->capabilities & HIDPP_CAP_ADJUSTIBLE_REPORT_RATE_8060) {
rc = hidpp20drv_update_report_rate_8060(profile, hz);
/* re-populate the profile with the correct value if we fail */
if (rc)
hidpp20drv_read_report_rate_8060(profile->device);
return rc;
}
return -ENOTSUP;
}
@@ -1179,6 +1251,60 @@ hidpp20drv_read_profile_8100(struct ratbag_profile *profile)
ratbag_profile_set_report_rate(profile, p->report_rate);
}
static int
hidpp20drv_init_leds_8070_8071(struct ratbag_device *device)
{
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
struct ratbag *ratbag = device->ratbag;
/* we only support 0x8071 via 0x8100 */
if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) &&
drv_data->capabilities & HIDPP_CAP_RGB_EFFECTS_8071) {
log_debug(ratbag, "disabling 0x8071 (RGB Effects) feature because the device doesn't have 0x8100 (Onboard Memory Profiles)\n");
drv_data->capabilities &= ~HIDPP_CAP_RGB_EFFECTS_8071;
}
if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070 ||
drv_data->capabilities & HIDPP_CAP_RGB_EFFECTS_8071) {
/* we read the profile once to get the correct number of
* supported leds. */
if (hidpp20drv_read_color_leds(device))
return 0;
device->num_leds = drv_data->num_leds;
}
return 0;
}
static int
hidpp20drv_init_profile_8100(struct ratbag_device *device)
{
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
struct ratbag *ratbag = device->ratbag;
int rc;
log_debug(ratbag, "initializing onboard profiles\n");
rc = hidpp20_onboard_profiles_allocate(drv_data->dev, &drv_data->profiles);
if (rc < 0)
return rc;
rc = hidpp20_onboard_profiles_initialize(drv_data->dev, drv_data->profiles);
if (rc < 0)
return rc;
drv_data->num_profiles = drv_data->profiles->num_profiles;
drv_data->num_buttons = drv_data->profiles->num_buttons;
if (drv_data->capabilities & HIDPP_CAP_SWITCHABLE_RESOLUTION_2201)
drv_data->num_resolutions = drv_data->profiles->num_modes;
/* We ignore the profile's num_leds and require
* HIDPP_PAGE_COLOR_LED_EFFECTS to succeed instead
*/
return 0;
}
static void
hidpp20drv_read_profile(struct ratbag_profile *profile)
{
@@ -1313,25 +1439,11 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
log_debug(ratbag, "device has color effects\n");
drv_data->capabilities |= HIDPP_CAP_COLOR_LED_EFFECTS_8070;
/* we read the profile once to get the correct number of
* supported leds. */
if (hidpp20drv_read_color_leds(device))
return 0;
device->num_leds = drv_data->num_leds;
break;
}
case HIDPP_PAGE_RGB_EFFECTS: {
log_debug(ratbag, "device has color effects\n");
drv_data->capabilities |= HIDPP_CAP_RGB_EFFECTS_8071;
/* we read the profile once to get the correct number of
* supported leds. */
if (hidpp20drv_read_color_leds(device))
return 0;
device->num_leds = drv_data->num_leds;
break;
}
case HIDPP_PAGE_LED_SW_CONTROL: {
@@ -1349,22 +1461,6 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
case HIDPP_PAGE_ONBOARD_PROFILES: {
log_debug(ratbag, "device has onboard profiles\n");
drv_data->capabilities |= HIDPP_CAP_ONBOARD_PROFILES_8100;
rc = hidpp20_onboard_profiles_allocate(drv_data->dev, &drv_data->profiles);
if (rc < 0)
return rc;
rc = hidpp20_onboard_profiles_initialize(drv_data->dev, drv_data->profiles);
if (rc < 0)
return rc;
drv_data->num_profiles = drv_data->profiles->num_profiles;
drv_data->num_resolutions = drv_data->profiles->num_modes;
drv_data->num_buttons = drv_data->profiles->num_buttons;
/* We ignore the profile's num_leds and require
* HIDPP_PAGE_COLOR_LED_EFFECTS to succeed instead
*/
break;
}
case HIDPP_PAGE_MOUSE_BUTTON_SPY: {
@@ -1386,27 +1482,27 @@ hidpp20drv_commit(struct ratbag_device *device)
struct ratbag_led *led;
struct ratbag_resolution *resolution;
int rc;
unsigned int dpi_index = 0;
list_for_each(profile, &device->profiles, link) {
if (!profile->dirty)
continue;
rc = hidpp20drv_update_report_rate(profile, profile->hz);
if (rc)
return RATBAG_ERROR_DEVICE;
if (profile->rate_dirty) {
rc = hidpp20drv_update_report_rate(profile, profile->hz);
if (rc) {
log_error(device->ratbag, "hidpp20: failed to update report rate\n");
return RATBAG_ERROR_DEVICE;
}
}
ratbag_profile_for_each_resolution(profile, resolution) {
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,
resolution->dpi_y);
if (rc)
if (rc) {
log_error(device->ratbag, "hidpp20: failed to update resolution\n");
return RATBAG_ERROR_DEVICE;
}
}
list_for_each(button, &profile->buttons, link) {
@@ -1414,8 +1510,10 @@ hidpp20drv_commit(struct ratbag_device *device)
continue;
rc = hidpp20drv_update_button(button);
if (rc)
if (rc) {
log_error(device->ratbag, "hidpp20: failed to update button\n");
return RATBAG_ERROR_DEVICE;
}
}
list_for_each(led, &profile->leds, link) {
@@ -1423,10 +1521,11 @@ hidpp20drv_commit(struct ratbag_device *device)
continue;
rc = hidpp20drv_update_led(led);
if (rc)
if (rc) {
log_error(device->ratbag, "hidpp20: failed to update led\n");
return RATBAG_ERROR_DEVICE;
}
}
}
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
@@ -1435,17 +1534,18 @@ hidpp20drv_commit(struct ratbag_device *device)
rc = hidpp20_onboard_profiles_commit(drv_data->dev,
drv_data->profiles);
if (rc)
if (rc) {
log_error(device->ratbag, "hidpp20: failed to commit profile\n");
return RATBAG_ERROR_DEVICE;
}
list_for_each(profile, &device->profiles, link) {
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,
resolution->index);
}
hidpp20_onboard_profiles_set_current_dpi_index(drv_data->dev,
dpi_index);
}
}
}
@@ -1476,8 +1576,21 @@ hidpp20drv_20_probe(struct ratbag_device *device)
return rc;
}
return 0;
/* initializations that depend on other features */
if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070 ||
drv_data->capabilities & HIDPP_CAP_RGB_EFFECTS_8071) {
rc = hidpp20drv_init_leds_8070_8071(device);
if (rc < 0)
return rc;
}
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
rc = hidpp20drv_init_profile_8100(device);
if (rc < 0)
return rc;
}
return 0;
}
static int
@@ -1511,6 +1624,7 @@ hidpp20drv_remove(struct ratbag_device *device)
free(drv_data->led_infos.color_leds_8070);
free(drv_data->controls);
free(drv_data->sensors);
free(drv_data->leds);
if (drv_data->dev)
hidpp20_device_destroy(drv_data->dev);
free(drv_data);
@@ -1592,7 +1706,7 @@ hidpp20drv_probe(struct ratbag_device *device)
/* add some defaults that will be overwritten by the device */
drv_data->num_profiles = 1;
drv_data->num_resolutions = 1;
drv_data->num_resolutions = 0;
drv_data->num_buttons = 8;
drv_data->num_leds = 0;

View File

@@ -106,7 +106,7 @@ struct hidpp_device {
void *userdata;
hidpp_log_handler log_handler;
enum hidpp_log_priority log_priority;
uint8_t supported_report_types;
unsigned supported_report_types;
};
#define HIDPP_REPORT_SHORT (1 << 0)

View File

@@ -868,6 +868,8 @@ err:
#define CMD_COLOR_LED_EFFECTS_GET_INFO 0x00
#define CMD_COLOR_LED_EFFECTS_GET_ZONE_INFO 0x10
#define CMD_COLOR_LED_EFFECTS_GET_ZONE_EFFECT_INFO 0x20
#define CMD_COLOR_LED_EFFECTS_SET_ZONE_EFFECT 0x30
#define CMD_COLOR_LED_EFFECTS_GET_ZONE_EFFECT 0xe0
int
hidpp20_color_led_effects_get_info(struct hidpp20_device *device,
@@ -893,6 +895,7 @@ hidpp20_color_led_effects_get_info(struct hidpp20_device *device,
return rc;
*info = *(struct hidpp20_color_led_info *)msg.msg.parameters;
device->led_ext_caps = info->ext_caps;
return 0;
}
@@ -1012,6 +1015,80 @@ hidpp20_color_led_effect_get_zone_effect_info(struct hidpp20_device *device,
return 0;
}
int
hidpp20_color_led_effects_set_zone_effect(struct hidpp20_device *device,
uint8_t zone_index,
struct hidpp20_led led)
{
uint8_t feature_index;
union hidpp20_message msg = {
.msg.report_id = REPORT_ID_SHORT,
.msg.address = CMD_COLOR_LED_EFFECTS_SET_ZONE_EFFECT,
.msg.device_idx = device->index,
.msg.parameters[0] = zone_index,
.msg.parameters[12] = 1, /* write to RAM and flash */
};
int rc;
struct hidpp20_internal_led *internal_led = (struct hidpp20_internal_led*) &msg.msg.parameters[1];
hidpp20_onboard_profiles_write_led(internal_led, &led);
feature_index = hidpp_root_get_feature_idx(device,
HIDPP_PAGE_COLOR_LED_EFFECTS);
if (feature_index == 0)
return -ENOTSUP;
msg.msg.sub_id = feature_index;
rc = hidpp20_request_command(device, &msg);
if (rc)
return rc;
return 0;
}
int
hidpp20_color_led_effects_get_zone_effect(struct hidpp20_device *device,
uint8_t zone_index,
struct hidpp20_led *led)
{
uint8_t feature_index;
union hidpp20_message msg = {
.msg.report_id = REPORT_ID_SHORT,
.msg.address = CMD_COLOR_LED_EFFECTS_GET_ZONE_EFFECT,
.msg.device_idx = device->index,
.msg.parameters[0] = zone_index,
};
struct hidpp20_internal_led *internal_led;
int rc;
/* hidpp20_color_led_effects_get_info() must be called first to set the capabilities */
if (!(device->led_ext_caps & HIDPP20_COLOR_LED_INFO_EXT_CAP_HAS_ZONE_EFFECT))
return -ENOTSUP;
feature_index = hidpp_root_get_feature_idx(device,
HIDPP_PAGE_COLOR_LED_EFFECTS);
if (feature_index == 0)
return -ENOTSUP;
msg.msg.sub_id = feature_index;
rc = hidpp20_request_command(device, &msg);
if (rc)
return rc;
if (msg.msg.parameters[0] != zone_index)
return -EPROTO;
internal_led = (struct hidpp20_internal_led*) &msg.msg.parameters[1];
hidpp20_onboard_profiles_read_led(led, *internal_led);
hidpp_log_debug(&device->base, "zone %u has effect %u\n", zone_index, led->mode);
return 0;
}
/* -------------------------------------------------------------------------- */
/* 0x8071: RGB Effects */
/* -------------------------------------------------------------------------- */
@@ -1612,6 +1689,8 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device,
/* -------------------------------------------------------------------------- */
#define CMD_ADJUSTABLE_REPORT_RATE_GET_REPORT_RATE_LIST 0x00
#define CMD_ADJUSTABLE_REPORT_RATE_GET_REPORT_RATE 0x10
#define CMD_ADJUSTABLE_REPORT_RATE_SET_REPORT_RATE 0x20
int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *device,
uint8_t *bitflags_ms)
@@ -1641,6 +1720,60 @@ int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *d
return 0;
}
int hidpp20_adjustable_report_rate_get_report_rate(struct hidpp20_device *device,
uint8_t *rate_ms)
{
uint8_t feature_index;
int rc;
union hidpp20_message msg = {
.msg.report_id = REPORT_ID_SHORT,
.msg.device_idx = device->index,
.msg.address = CMD_ADJUSTABLE_REPORT_RATE_GET_REPORT_RATE,
.msg.parameters[0] = 0,
};
feature_index = hidpp_root_get_feature_idx(device,
HIDPP_PAGE_ADJUSTABLE_REPORT_RATE);
if (feature_index == 0)
return -ENOTSUP;
msg.msg.sub_id = feature_index;
rc = hidpp20_request_command(device, &msg);
if (rc)
return rc;
*rate_ms = msg.msg.parameters[0];
return 0;
}
int hidpp20_adjustable_report_rate_set_report_rate(struct hidpp20_device *device,
uint8_t rate_ms)
{
uint8_t feature_index;
int rc;
union hidpp20_message msg = {
.msg.report_id = REPORT_ID_SHORT,
.msg.device_idx = device->index,
.msg.address = CMD_ADJUSTABLE_REPORT_RATE_SET_REPORT_RATE,
.msg.parameters[0] = rate_ms,
};
feature_index = hidpp_root_get_feature_idx(device,
HIDPP_PAGE_ADJUSTABLE_REPORT_RATE);
if (feature_index == 0)
return -ENOTSUP;
msg.msg.sub_id = feature_index;
rc = hidpp20_request_command(device, &msg);
if (rc)
return rc;
return 0;
}
/* -------------------------------------------------------------------------- */
/* 0x8100 - Onboard Profiles */
/* -------------------------------------------------------------------------- */
@@ -2399,6 +2532,9 @@ hidpp20_onboard_profiles_write_dict(struct hidpp20_device *device,
sector_size,
data,
true);
if (rc)
hidpp_log_error(&device->base, "failed to write profile dictionary\n");
return rc;
}
@@ -2436,6 +2572,7 @@ hidpp20_buttons_to_cpu(struct hidpp20_device *device,
break;
case HIDPP20_BUTTON_SPECIAL:
button->special.special = b->special.special;
button->special.profile = b->special.profile;
break;
case HIDPP20_BUTTON_MACRO:
if (profile->macros[i]) {
@@ -2495,6 +2632,7 @@ hidpp20_buttons_from_cpu(struct hidpp20_profile *profile,
break;
case HIDPP20_BUTTON_SPECIAL:
button->special.special = b->special.special;
button->special.profile = b->special.profile;
break;
case HIDPP20_BUTTON_DISABLED:
break;
@@ -2510,7 +2648,7 @@ hidpp20_buttons_from_cpu(struct hidpp20_profile *profile,
}
}
static void
void
hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
struct hidpp20_internal_led internal_led)
{
@@ -2526,6 +2664,10 @@ hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
if (brightness == 0)
brightness = 100;
break;
case HIDPP20_LED_STARLIGHT:
led->color = internal_led.effect.starlight.color_sky;
led->extra_color = internal_led.effect.starlight.color_star;
break;
case HIDPP20_LED_BREATHING:
period = hidpp_be_u16_to_cpu(internal_led.effect.breath.period_or_speed);
brightness = internal_led.effect.breath.intensity;
@@ -2533,11 +2675,18 @@ hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
brightness = 100;
led->color = internal_led.effect.breath.color;
break;
case HIDPP20_LED_RIPPLE:
period = hidpp_be_u16_to_cpu(internal_led.effect.breath.period_or_speed);
led->color = internal_led.effect.ripple.color;
break;
case HIDPP20_LED_ON:
led->color = internal_led.effect.fixed.color;
break;
case HIDPP20_LED_OFF:
break;
default:
memcpy(led->original, &internal_led, sizeof(internal_led));
break;
}
led->period = period;
@@ -2713,7 +2862,7 @@ read_profiles:
return profiles->num_profiles;
}
static void
void
hidpp20_onboard_profiles_write_led(struct hidpp20_internal_led *internal_led,
struct hidpp20_led *led)
{
@@ -2732,24 +2881,31 @@ hidpp20_onboard_profiles_write_led(struct hidpp20_internal_led *internal_led,
else
internal_led->effect.cycle.intensity = 0;
break;
case HIDPP20_LED_STARLIGHT:
internal_led->effect.starlight.color_sky = led->color;
internal_led->effect.starlight.color_star = led->extra_color;
break;
case HIDPP20_LED_BREATHING:
internal_led->effect.breath.color.red = led->color.red;
internal_led->effect.breath.color.blue = led->color.blue;
internal_led->effect.breath.color.green = led->color.green;
internal_led->effect.breath.color = led->color;
internal_led->effect.breath.period_or_speed = hidpp_cpu_to_be_u16(period);
if (brightness < 100)
internal_led->effect.breath.intensity = brightness;
else
internal_led->effect.breath.intensity = 0;
break;
case HIDPP20_LED_RIPPLE:
internal_led->effect.ripple.color = led->color;
internal_led->effect.ripple.period = hidpp_cpu_to_be_u16(period);
break;
case HIDPP20_LED_ON:
internal_led->effect.fixed.color.red = led->color.red;
internal_led->effect.fixed.color.blue = led->color.blue;
internal_led->effect.fixed.color.green = led->color.green;
internal_led->effect.fixed.color = led->color;
internal_led->effect.fixed.effect = 0;
break;
case HIDPP20_LED_OFF:
break;
default:
memcpy(internal_led, led->original, sizeof(*internal_led));
break;
}
}
@@ -2797,8 +2953,10 @@ hidpp20_onboard_profiles_write_profile(struct hidpp20_device *device,
memcpy(pdata->profile.name.txt, profile->name, sizeof(profile->name));
rc = hidpp20_onboard_profiles_write_sector(device, sector, sector_size, data, true);
if (rc < 0)
if (rc < 0) {
hidpp_log_error(&device->base, "failed to write profile\n");
return rc;
}
return 0;
}
@@ -2894,6 +3052,8 @@ hidpp20_device_new(const struct hidpp_device *base, unsigned int idx, struct hid
dev->proto_major = 1;
dev->proto_minor = 0;
dev->led_ext_caps = 0;
hidpp_get_supported_report_types(&(dev->base), reports, num_reports);
if (!(dev->base.supported_report_types & HIDPP_REPORT_SHORT) &&

View File

@@ -65,6 +65,7 @@ struct hidpp20_device {
unsigned feature_count;
struct hidpp20_feature *feature_list;
enum hidpp20_quirk quirk;
unsigned int led_ext_caps;
};
int hidpp20_request_command(struct hidpp20_device *dev, union hidpp20_message *msg);
@@ -432,6 +433,12 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device,
int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *device,
uint8_t *bitflags_ms);
int hidpp20_adjustable_report_rate_get_report_rate(struct hidpp20_device *device,
uint8_t *rate_ms);
int hidpp20_adjustable_report_rate_set_report_rate(struct hidpp20_device *device,
uint8_t rate_ms);
/* -------------------------------------------------------------------------- */
/* 0x8070v4 - Color LED effects */
/* -------------------------------------------------------------------------- */
@@ -495,6 +502,18 @@ hidpp20_rgb_effects_get_effect_info(struct hidpp20_device *device,
uint8_t effect_index,
struct hidpp20_rgb_effect_info *info);
struct hidpp20_led;
int
hidpp20_color_led_effects_set_zone_effect(struct hidpp20_device *device,
uint8_t zone_index,
struct hidpp20_led led);
int
hidpp20_color_led_effects_get_zone_effect(struct hidpp20_device *device,
uint8_t zone_index,
struct hidpp20_led *led);
enum hidpp20_color_led_location {
HIDPP20_COLOR_LED_LOCATION_UNDEFINED = 0,
HIDPP20_COLOR_LED_LOCATION_PRIMARY,
@@ -599,6 +618,8 @@ union hidpp20_button_binding {
struct {
uint8_t type; /* HIDPP20_BUTTON_SPECIAL */
uint8_t special;
uint8_t reserved;
uint8_t profile;
} __attribute__((packed)) special;
struct {
uint8_t type; /* HIDPP20_BUTTON_MACRO */
@@ -698,7 +719,11 @@ enum hidpp20_led_mode {
HIDPP20_LED_OFF = 0x00,
HIDPP20_LED_ON = 0x01,
HIDPP20_LED_CYCLE = 0x03,
HIDPP20_LED_COLOR_WAVE = 0x04,
HIDPP20_LED_STARLIGHT = 0x05,
HIDPP20_LED_BREATHING = 0x0a,
HIDPP20_LED_RIPPLE = 0x0b,
HIDPP20_LED_CUSTOM = 0x0c,
};
enum hidpp20_led_waveform {
@@ -723,27 +748,48 @@ struct hidpp20_internal_led {
uint16_t period_or_speed; /* period in ms, speed is device dependent */
uint8_t intensity; /* 1 - 100 percent, 0 means 100 */
} __attribute__((packed)) cycle;
struct hidpp20_led_starlight {
struct hidpp20_color color_sky;
struct hidpp20_color color_star;
} __attribute__((packed)) starlight;
struct hidpp20_led_breath {
struct hidpp20_color color;
uint16_t period_or_speed; /* period in ms, speed is device dependent */
uint8_t waveform; /* enum hidpp20_led_waveform */
uint8_t intensity; /* 1 - 100 percent, 0 means 100 */
} __attribute__((packed)) breath;
struct hidpp20_led_ripple {
struct hidpp20_color color;
uint8_t reserved;
uint16_t period;
} __attribute__((packed)) ripple;
struct hidpp20_led_custom {
uint8_t slot;
uint16_t init_frame;
uint16_t lenght;
uint16_t frame_period;
uint8_t intensity;
} __attribute__((packed)) custom;
uint8_t padding[10];
} __attribute__((packed)) effect;
};
_Static_assert(sizeof(struct hidpp20_led_fixed) == 4, "Invalid size");
_Static_assert(sizeof(struct hidpp20_led_cycle) == 8, "Invalid size");
_Static_assert(sizeof(struct hidpp20_led_starlight) == 6, "Invalid size");
_Static_assert(sizeof(struct hidpp20_led_breath) == 7, "Invalid size");
_Static_assert(sizeof(struct hidpp20_internal_led) == 11, "Invalid size");
_Static_assert(sizeof(struct hidpp20_led_ripple) == 6, "Invalid size");
_Static_assert(sizeof(struct hidpp20_led_custom) == 8, "Invalid size");
typedef uint8_t percent_t;
struct hidpp20_led {
enum hidpp20_led_mode mode;
struct hidpp20_color color;
struct hidpp20_color extra_color;
uint16_t period;
percent_t brightness;
uint8_t original[sizeof(struct hidpp20_internal_led)];
};
#define HIDPP20_MACRO_NOOP 0x01
@@ -919,6 +965,14 @@ hidpp20_onboard_profiles_allocate_sector(struct hidpp20_profiles *profiles)
return zalloc(profiles->sector_size);
}
void
hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
struct hidpp20_internal_led internal_led);
void
hidpp20_onboard_profiles_write_led(struct hidpp20_internal_led *internal_led,
struct hidpp20_led *led);
/* -------------------------------------------------------------------------- */
/* 0x8110 - Mouse Button Spy */
/* -------------------------------------------------------------------------- */

View File

@@ -346,6 +346,8 @@ parse_ledtypes(char **strv, enum ratbag_led_type *types, size_t ntypes)
types[i] = RATBAG_LED_TYPE_SIDE;
else if (streq(s, "wheel"))
types[i] = RATBAG_LED_TYPE_WHEEL;
else if (streq(s, "switches"))
types[i] = RATBAG_LED_TYPE_SWITCHES;
else
return -1;

View File

@@ -293,6 +293,7 @@ enum ratbag_led_type {
RATBAG_LED_TYPE_BATTERY,
RATBAG_LED_TYPE_DPI,
RATBAG_LED_TYPE_WHEEL,
RATBAG_LED_TYPE_SWITCHES,
};
/**

View File

@@ -295,6 +295,7 @@ struct ratbag_profile {
unsigned int hz; /**< report rate in Hz */
unsigned int rates[8]; /**< report rates available */
size_t nrates; /**< number of entries in rates */
bool rate_dirty;
unsigned int num_resolutions;
@@ -585,14 +586,14 @@ ratbag_led_set_mode_capability(struct ratbag_led *led,
}
/* list of all supported drivers */
struct ratbag_driver etekcity_driver;
struct ratbag_driver hidpp20_driver;
struct ratbag_driver hidpp10_driver;
struct ratbag_driver logitech_g300_driver;
struct ratbag_driver logitech_g600_driver;
struct ratbag_driver roccat_driver;
struct ratbag_driver gskill_driver;
struct ratbag_driver steelseries_driver;
extern struct ratbag_driver etekcity_driver;
extern struct ratbag_driver hidpp20_driver;
extern struct ratbag_driver hidpp10_driver;
extern struct ratbag_driver logitech_g300_driver;
extern struct ratbag_driver logitech_g600_driver;
extern struct ratbag_driver roccat_driver;
extern struct ratbag_driver gskill_driver;
extern struct ratbag_driver steelseries_driver;
struct ratbag_device*
ratbag_device_new(struct ratbag *ratbag, struct udev_device *udev_device,

View File

@@ -31,7 +31,7 @@
#include "libratbag-util.h"
#include "libratbag-test.h"
struct ratbag_driver test_driver;
extern struct ratbag_driver test_driver;
static inline void
ratbag_register_test_drivers(struct ratbag *ratbag)

View File

@@ -268,7 +268,7 @@ ratbag_sanity_check_device(struct ratbag_device *device)
}
nres = ratbag_profile_get_num_resolutions(profile);
if (nres == 0 || nres > 16) {
if (nres > 16) {
log_bug_libratbag(ratbag,
"%s: invalid number of resolutions (%d)\n",
device->name,
@@ -949,6 +949,8 @@ ratbag_device_commit(struct ratbag_device *device)
list_for_each(profile, &device->profiles, link) {
profile->dirty = false;
profile->rate_dirty = false;
list_for_each(button, &profile->buttons, link)
button->dirty = false;
@@ -1117,6 +1119,7 @@ ratbag_profile_set_report_rate(struct ratbag_profile *profile,
if (profile->hz != hz) {
profile->hz = hz;
profile->dirty = true;
profile->rate_dirty = true;
}
return RATBAG_SUCCESS;

View File

@@ -52,6 +52,28 @@
%typemap(freearg) (unsigned int *rates, size_t nrates) = (unsigned int *resolutions, size_t nres);
/* END OF custom typemap for handling ratbag_resolution_get_report_rate_list */
/* uintXX_t mapping: Python -> C */
%typemap(in) uint8_t {
$1 = (uint8_t) PyInt_AsLong($input);
}
%typemap(in) uint16_t {
$1 = (uint16_t) PyInt_AsLong($input);
}
%typemap(in) uint32_t {
$1 = (uint32_t) PyInt_AsLong($input);
}
/* uintXX_t mapping: C -> Python */
%typemap(out) uint8_t {
$result = PyInt_FromLong((long) $1);
}
%typemap(out) uint16_t {
$result = PyInt_FromLong((long) $1);
}
%typemap(out) uint32_t {
$result = PyInt_FromLong((long) $1);
}
/* Parse the header file to generate wrappers */
%include "libratbag.h"
%include "libratbag-enums.h"

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env python3
#
# vim: set expandtab shiftwidth=4 tabstop=4:
#
# Copyright 2017 Red Hat, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a

View File

@@ -1,5 +1,3 @@
# vim: set expandtab shiftwidth=4 tabstop=4:
#
# Copyright 2017-2019 Red Hat, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
@@ -137,7 +135,7 @@ class Ratbagd(object):
"""
def __init__(self):
def __init__(self, apiversion):
os.environ['LIBRATBAG_DATA_DIR'] = LIBRATBAG_DATA_DIR
self._ratbag = libratbag.ratbag_create_context(libratbag.interface, None)
self._devices = {}
@@ -251,13 +249,13 @@ class RatbagdDevice(metaclass=MetaRatbag):
@property
def model(self):
"""The unique identifier for this device model."""
bus = libratbag.ratbag_device_get_bus(self._device)
bus = libratbag.ratbag_device_get_bustype(self._device)
if not bus:
return "unknown"
vid = libratbag.ratbag_device_get_vendor_id(self._device)
pid = libratbag.ratbag_device_get_product_id(self._device)
version = libratbag.ratbag_device_get_product_version(self._device)
return "{}:{04x}:{04x}:{d}".format(bus, vid, pid, version)
return "{}:{:04x}:{:04x}:{:d}".format(bus, vid, pid, version)
@property
def name(self):

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env python3
#
# vim: set expandtab shiftwidth=4 tabstop=4:
#
# This file is part of libratbag.
#
# Copyright 2017 Red Hat, Inc.

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env python3
#
# vim: set expandtab shiftwidth=4 tabstop=4:
#
# Copyright 2016 Red Hat, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env python3
#
# vim: set expandtab shiftwidth=4 tabstop=4:
#
# This file is part of libratbag.
#
# Copyright 2017 Red Hat, Inc.

View File

@@ -250,11 +250,13 @@ class Ratbagd(_RatbagdDBus):
def __init__(self, api_version):
super().__init__("Manager", None)
result = self._get_dbus_property("Devices") or []
self._devices = [RatbagdDevice(objpath) for objpath in result]
self._proxy.connect("notify::g-name-owner", self._on_name_owner_changed)
result = self._get_dbus_property("Devices")
if result is None and not self._proxy.get_cached_property_names():
raise RatbagdUnavailable("Make sure it is running and your user is in the required groups.")
if self.api_version != api_version:
raise RatbagdIncompatible(self.api_version or -1, api_version)
self._devices = [RatbagdDevice(objpath) for objpath in result or []]
self._proxy.connect("notify::g-name-owner", self._on_name_owner_changed)
def _on_name_owner_changed(self, *kwargs):
self.emit("daemon-disappeared")

View File

@@ -74,6 +74,9 @@ led_type_to_str(enum ratbag_led_type type)
case RATBAG_LED_TYPE_WHEEL:
str = "wheel";
break;
case RATBAG_LED_TYPE_SWITCHES:
str = "switches";
break;
default:
assert(!"Invalid LED type");
break;

View File

@@ -88,4 +88,4 @@ str_to_special_action(const char *str);
struct ratbag_device *
ratbag_cmd_open_device(struct ratbag *ratbag, const char *path);
const struct ratbag_interface interface;
extern const struct ratbag_interface interface;

View File

@@ -1,5 +1,3 @@
# vim: set expandtab shiftwidth=4 tabstop=4:
#
# This file is part of libratbag.
#
# Copyright 2017 Red Hat, Inc.