Commit graph

70 commits

Author SHA1 Message Date
Peter Hutterer
a202ed6115 Use a newtype usec_t for timestamps for better type-safety
This avoids mixing up milliseconds and usec, both by failing if
we're providing just a number somewhere we expect usecs and also
by making the API blindingly obvious that we're in usecs now.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1373>
2025-12-12 04:15:15 +00:00
Adam Sampson
931dad76a9 test: correct value type in atou64_test
This needs to be an unsigned 64-bit value, given the constants that are
stored in this field below; unsigned long is 32 bits on some platforms
(e.g. ia32).

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1288>
2025-08-01 22:34:07 +00:00
Matt Turner
7f3aa8058a test: Accept mkdir_p("/proc/foo") might return EACCES
... as it does under Gentoo's sandbox.

Fixes: 6770131e ("util: fix a memleak in mkdir_p")
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1289>
2025-08-01 11:11:31 -04:00
Peter Hutterer
f04b276ac1 util: add a helper struct for an evdev mask
Allows to keep track of a set of evdev masks, or at least the subset we
care about.

The EV_KEY range is split into two masks to save some memory. The future
use of this is for the plugins to use those masks and some of those will
set BTN_TOOL_PEN and friends. This would immediately create an 81 byte
mask of zeroes just to keep that one bit.

Splitting it into a key/btn mask with the latter starting at BTN_MISC
means we duplicate the infmask struct (2x16 bytes) but instead only use
8 bytes for the mask itself to keep the BTN_TOOL_PEN bits.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1271>
2025-08-01 14:29:44 +10:00
Peter Hutterer
d45f4493f1 util: add an infmask_t type for an infinitely-sized bitmask
Using the bitmask-size underneath but this mask can grow to any number
of bits requested. Notably, the sized of the mask is the nearest 4-byte
multiple for the highest bit ever set in the mask.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1271>
2025-08-01 14:29:44 +10:00
Peter Hutterer
8141159beb Add evdev_frame_append_one()
This is the most common usage, let's add a helper.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1245>
2025-07-02 06:53:05 +00:00
Peter Hutterer
2a1095924b Run clang-format over the code
This uses the .clang-format file in the follow-up commit, but committed
prior to that to ease review of said file and various integrations.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1246>
2025-07-01 16:42:44 +10:00
Peter Hutterer
aebf3cd491 Add trailing commas to prevent clang-format oddities
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1246>
2025-07-01 16:36:14 +10:00
Peter Hutterer
784312a494 test: add clang-format directives to prevent formatting
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1246>
2025-07-01 16:36:14 +10:00
Peter Hutterer
8974a15178 util: add a bitmask_t type for bit masks
Previously we used uint32_t for bitmasks but having a custom type means
we're less likely to confuse an int value with a mask type.

Two types of API here, the u32 api for passing in masks and a bit API
for passing in single bits.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1218>
2025-06-18 19:38:14 +10:00
Peter Hutterer
1850ea18f4 util: add safe_atou64 for 64-bit values
Copy/paste from safe_atou

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1226>
2025-06-17 13:50:58 +10:00
Peter Hutterer
41e988c99e Introduce our own evdev_event struct
In addition to the evdev_frame this struct is what contains our actual
events instead of a struct input_event. The goal of this is twofold:
slightly better memory usage per frame since we can skip the timestamp
and refer to the evdev frame's timestamp only. This also improves
handling a frame since we no longer need to care about updating
all events when the timestamp changes during appending events.

Secondly it merges the evdev type + code into a single "usage"
(term obviously and shamelessly stolen from HID). Those usages
are the same as the code names but with an extra EVDEV_ prepended,
i.e.  EV_SYN / SYN_REPORT becomes EVDEV_SYN_REPORT.

And they are wrapped in a newtype so passing it around provides
some typesafety.

This only switches one part of the processing over, the dispatch
interfaces still use a struct input_event

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1215>
2025-06-12 18:20:40 +10:00
Peter Hutterer
9f00f77bc4 Add an evdev_frame wrapper struct
The kernel only ever gives us a frame of events in one go (it flushes on
SYN_REPORT). We then need to look at that frame as a single state change
(keyboards excepted for historical reasons) so let's push this into a
proper struct we can pass around.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1215>
2025-06-12 18:20:40 +10:00
Peter Hutterer
46950de903 util: return early when listing files from a NULL directory list
For consistency with "no matching file found" return a single-null-entry
array.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1212>
2025-06-05 00:49:57 +00:00
Peter Hutterer
ec9c39da18 util: add a number of list helpers
The list_debug function is ifdef'd out, it'll be useful to debug
whenever we have some list corruption.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1209>
2025-06-03 09:10:15 +00:00
Peter Hutterer
e91e1c3111 util: add a tmpdir helper
With the __attribute__(cleanup) helper this makes it simple
enough to provide a tempdir inside a function that is (recursively)
automatically deleted when the variable is deleted.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1204>
2025-05-26 05:22:33 +00:00
Peter Hutterer
91d4f9e58e util: add an rmdir_r helper function
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1204>
2025-05-26 05:22:33 +00:00
Peter Hutterer
efea8463fe util: add a helper to find files in a set of directories
Returns a number of paths for files with a given suffix in a
priority-sorted list of directories.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1204>
2025-05-26 05:22:33 +00:00
Peter Hutterer
95a417cefa util: add a helper to find substrings in a strv
Returns true and optionally the first index of any string in strv that
contains the given substring.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1204>
2025-05-26 05:22:33 +00:00
Peter Hutterer
8177a685c2 meson.build: fix detection of C23 auto
Sadly, this detection was broken because in C everything defaults to
type int. Casting a const char* to int is permitted but generates a
warning which was promptly ignored by meson.

This result in HAVE_C23_AUTO being set on compilers that don't by
default have -Werror=implicit-int and "auto" ended up being just an
"int".

Change the detection to use gmtime() which returns a struct, and add a
basic test using one of our struct-returning utility functions, just to
be sure.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1198>
2025-05-08 23:06:58 +00:00
Peter Hutterer
d400b17bee util: add the macros required for magic vararg expansion
A set of macros that expand to different things depending on the
number of arguments passed into the macro. Can be used for anything
but in the test case we use it to differ between stringifying the single
argument or taking a custom string for that same argument.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1188>
2025-04-28 10:05:52 +10:00
Peter Hutterer
04a55d59d9 test: call rmdir for directories, not unlink
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1193>
2025-04-24 17:34:07 +10:00
Peter Hutterer
6563b66a92 utils: add strv_find()
Finds and optionally returns the index of a string in a strv

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1193>
2025-04-24 17:34:06 +10:00
Peter Hutterer
76c87d2486 util: add various helper functions to use __attribute__(cleanup)
Taken from libei, with slight modifications. The general approach is:
basic data types use _autofoo_ to call the maching foo function on
cleanup. Struct types use _unref_, _destory_, _free_, whichever applies
to that struct.

Notably: attribute syntax depends on where it's declared [1] so in the
following examles only a, b, and d have the autofree attribute:
   _autofree_ char *a, *b;
   char *c, _autofree *d;

Simplest way to ensure it's all correct to keep the declarations one per
line.

[1] https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1184>
2025-04-16 17:04:58 +10:00
Peter Hutterer
546debe926 Remove empty lines between closing braces
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1190>
2025-04-16 11:44:09 +10:00
Peter Hutterer
0e3bb4690a test: switch some xasprintf to strdup_printf()
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1186>
2025-04-15 11:07:24 +10:00
Peter Hutterer
63a8ad2ead util: add some extra strv helpers
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1178>
2025-04-04 22:19:47 +00:00
Peter Hutterer
6770131e94 util: fix a memleak in mkdir_p
In the error case path would leak.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1175>
2025-04-04 15:47:23 +00:00
Peter Hutterer
a55dd604e1 util: add a newtype macro
In a valiant approach to introduce some type-safety (after spending time
debugging a int vs double confusion) this adds a DECLARE_NEWTYPE()
macro that declares a named struct with a single typed value field.

This is basically the C version of Rusts "struct Foo(u32)" with
a few accessors auto-generated by the macro.

C is happy to silently convert between base types but it doesn't do
so for structs so this allows us to have some type safety
when we accidentally assign two incompatible fields to each other (e.g.
an axis value in device units vs a percentage value).

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1171>
2025-04-04 11:05:20 +00:00
Peter Hutterer
58315eb9d4 test: remove duplicate empty lines from the test/ directory
We've had a CI job for checking this since but it omitted the test
directory.

Fixes: bb6ff0ec00 ("gitlab CI: add a job to check for whitespace issues")
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1154>
2025-03-11 11:41:34 +00:00
Peter Hutterer
1e445f3f84 test: implement support for parametrizing tests
litest supports ranged tests but they are not enough, doubly so with
tests where we want to parametrize across multiple options.

This patch adds support for just that, in clunky C style.
The typical invocation for a test is by giving the test parameter
a name, a number of values and then the values themselves:

	struct litest_parameters *params = litest_parameters_new("axis", 's', 2, "ABS_X", "ABS_Y",
	                                                         "enabled", 'b', '2', true, false,
	                                                         "number", 'u', '2', 10, 11,
	                                                         NULL);
	litest_add_parametrized(sometest, LITEST_ANY, LITEST_ANY, params);
	litest_parameters_unref(params);

Currently supported are u (uint32), i (int32), d (double), b (bool),
c (char) and s (string).

In the test itself, the `test_env->params` variable is available and
retrieval of the parameters works like this:

	const char *axis;
	uint32_t number;
	bool enabled;
	litest_test_param_fetch(test_env->params,
	                        "axis", &axis,
	                        "enabled", &enabled,
	                        "number", &number,
	                        NULL);

Note that since this is an effectively internal test-suite only
functionality we don't do type-checking here, it's assumed that if you
write the code to pass parameters into a test you remember the type
of said params when you write the test code.

Because we don't have hashmaps or anything useful other than lists the
implementation is a bit clunky: we copy the parameter into the test
during litest_add_*, permutate it for our test list which gives us yet
another linked list C struct, and finally copy the actual value into
the test and test environment as it's executed. Not pretty, but it
works.

A few tests are switched as simple demonstration. The name of the
test has the parameters with their names and values appended now, e.g.:
   "pointer:pointer_scroll_wheel_hires_send_only_lores:ms-surface-cover:axis:ABS_X"
   "pointer:pointer_motion_relative_min_decel:mouse-roccat:direction:NW"

Filtering by parameters can be done via globs of their string
representation:
   libinput-test-suite --filter-params="axis:ABS_*,enabled:true,number:10*"

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1109>
2025-01-07 02:02:37 +00:00
Peter Hutterer
da296c9976 util: Add a multivalue special type
A stripped down version of e.g GVariant that's enough for the few
parameter types we need to support.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1109>
2025-01-07 02:02:37 +00:00
Peter Hutterer
0cfde0f95f test: make the utils test a "pure" litest-runner test
Now that we have the runner let's use it directly for this set of simple
test.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1067>
2024-10-30 23:20:42 +00:00
Peter Hutterer
d94407f810 test: fix utils test for types for litest assertions
check always typecasts to intmax_t so a lot of type mismatches were
hidden.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1067>
2024-10-30 23:20:42 +00:00
Peter Hutterer
5cbb37a3d2 test: convert utils test to litest_assert
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1067>
2024-10-30 23:20:42 +00:00
Peter Hutterer
6cac0d4d2f test: make the utils test another litest
This doesn't really gain us anything for now but it's prep work for
dropping check and the custom invocations of check.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1067>
2024-10-30 23:20:42 +00:00
Peter Hutterer
4fa5ea268e util: add a generic stringbuffer with a few helper functions
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1067>
2024-10-30 23:20:42 +00:00
Peter Hutterer
817dc42381 util: add the range handling as separate header file
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1067>
2024-10-30 23:20:42 +00:00
Peter Hutterer
99961d4bd1 test: fix missing END_TEST for strv_for_each_test
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1059>
2024-10-15 12:44:27 +10:00
Peter Hutterer
8696e80136 test: fix a data type in the utils test
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1059>
2024-10-15 12:44:27 +10:00
Peter Hutterer
54dccd66d1 Fix a few potential NULL dereferences
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1052>
2024-09-30 15:35:36 +00:00
Peter Hutterer
ea7ad8d25c util: add a strv_for_each helper function
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1038>
2024-09-05 13:54:07 +00:00
Peter Hutterer
72eca2db56 util: add a helper to normalize an axis to [0.0, 1.0]
Like the input axis, a normalized range has min/max inclusive so we
cannot use the absinfo_range() helper which assumes the max is exclusive.

Reverts parts of 4effe6b1b9
2024-01-30 14:29:25 +10:00
Yinon Burgansky
5324f425a1 Introduce custom acceleration profile
The custom acceleration profile allow the user to define custom
acceleration functions for each movement type per device, giving
full control over accelerations behavior at different speeds.

This commit introduces 2 movement types which corresponds to the
2 profiles currently in use by libinput.

regular filter is Motion type.
constant filter is Fallback type.

This allows possible expansion of new movement types for the
different devices.

The custom pointer acceleration profile gives the user full control over the
acceleration behavior at different speeds.
The user needs to provide a custom acceleration function f(x) where
the x-axis is the device speed and the y-axis is the pointer speed.

The user should take into account the native device dpi and screen dpi in
order to achieve the desired behavior/feel of the acceleration.

The custom acceleration function is defined using n points which are spaced
uniformly along the x-axis, starting from 0 and continuing in constant steps.
There by the points defining the custom function are:
(0 * step, f[0]), (1 * step, f[1]), ..., ((n-1) * step, f[n-1])
where f is a list of n unitless values defining the acceleration
factor for each velocity.
When a velocity value does not lie exactly on those points, a linear
interpolation of the two closest points will be calculated.
When a velocity value is greater than the max point defined, a linear
extrapolation of the two biggest points will be calculated.

Signed-off-by: Yinon Burgansky <51504-Yinon@users.noreply.gitlab.freedesktop.org>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2023-01-17 01:46:17 +00:00
Peter Hutterer
a7e4cbc212 quirks: allow overriding of AttrEventCode and AttrInputProp
This switches the quirk from AttrEventCodeEnable/Disable to just
AttrEventCode with a +/- prefix for each entry.
This switches the quirk from AttrInputPropEnable/Disable to just
AttrInputProp with a +/- prefix for each entry.

Previously, both event codes and input props would only apply the
last-matching section entry for a device. Furthermore, an earlier Disable entry
would take precedence over a later Enable entry. For example, a set of
sections with these lines *should* enable left, right and middle:

  [first]
  AttrEventCodeEnable=BTN_LEFT;BTN_RIGHT;BTN_MIDDLE

  [second]
  AttrEventCodeDisable=BTN_RIGHT

  [third]
  AttrEventCodeEnable=BTN_LEFT;BTN_RIGHT;

Alas: the first line was effectively ignored (quirks only returned the
last-matching one, i.e. the one from "third"). And due to implementation
details in evdev.c, the Disable attribute was processed after Enable,
i.e. the device was enabled for left + right and then disabled for
right. As a result, the device only had BTN_LEFT enabled.

Fix this by changing the attribute to carry both enable/disable
information and merging the commands together.

Internally, all quirks matching a device are simply ref'd into an array
in the struct quirks. The applied value is simply the last entry in the
array corresponding to our quirk.

For AttrEventCode and AttrInputProp instead do this:
- switch them to a tuple with the code as first entry and a boolean
  enable/disable as second entry
- if the struct quirk already has an entry for either, append the more
  recent one to the existing entry (instead of creating a new entry in
  the array). This way we have all entries that match and in-order of
  precedence - i.e. we can process them left-to-right to end up
  with the right state.

Fixes: https://gitlab.freedesktop.org/libinput/libinput/-/issues/821

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2022-11-28 08:25:41 +10:00
José Expósito
955a9cc338 util: use ck_assert_ptr_eq() instead of ck_assert_ptr_null()
The ck_assert_ptr_null() function is not available in the version of
the check library included in 20.04 LTS Focal (0.10.0).

Use ck_assert_ptr_eq() to avoid compilation errors.

Fixes: eeae8906db ("util: return the number of elements from strv_from_string")
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
2022-11-14 19:11:12 +01:00
Yinon Burgansky
eeae8906db util: return the number of elements from strv_from_string
Signed-off-by: Yinon Burgansky <51504-Yinon@users.noreply.gitlab.freedesktop.org>
2022-11-07 22:32:24 +02:00
Alexander Courtis
e0813f4825 AttrLidSwitchReliability quirk default unreliable->reliable 2022-04-26 01:55:22 +00:00
Peter Hutterer
a423d7d326 evdev: strip the device name of format directives
This fixes a format string vulnerabilty.

evdev_log_message() composes a format string consisting of a fixed
prefix (including the rendered device name) and the passed-in format
buffer. This format string is then passed with the arguments to the
actual log handler, which usually and eventually ends up being printf.

If the device name contains a printf-style format directive, these ended
up in the format string and thus get interpreted correctly, e.g. for a
device "Foo%sBar" the log message vs printf invocation ends up being:
  evdev_log_message(device, "some message %s", "some argument");
  printf("event9 - Foo%sBar: some message %s", "some argument");

This can enable an attacker to execute malicious code with the
privileges of the process using libinput.

To exploit this, an attacker needs to be able to create a kernel device
with a malicious name, e.g. through /dev/uinput or a Bluetooth device.

To fix this, convert any potential format directives in the device name
by duplicating percentages.

Pre-rendering the device to avoid the issue altogether would be nicer
but the current log level hooks do not easily allow for this. The device
name is the only user-controlled part of the format string.

A second potential issue is the sysname of the device which is also
sanitized.

This issue was found by Albin Eldstål-Ahrens and Benjamin Svensson from
Assured AB, and independently by Lukas Lamster.

Fixes #752

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2022-04-20 13:32:31 +10:00
Peter Hutterer
395d12d634 util: auto-declare the element variable in ARRAY_FOR_EACH
All cases we have in our code base have an otherwise unused variable to
loop through the array. Let's auto-declare this as part of the loop.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2022-03-09 10:16:07 +10:00