Commit graph

137 commits

Author SHA1 Message Date
Peter Hutterer
6cbf971b39 Drop invalid ABS_MT_TRACKING_ID changes
Follow-up to
commit 41334b5b40
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Mar 6 11:54:00 2014 +1000

    If the tracking ID changes during SYN_DROPPED, terminate the touch first

In normal mode, we may get double tracking ID events in the same slot, but
only if we either have a user-generated event sequence (uinput) or a malicious
device that tries to send data on a slot > dev->num_slots.
Since the client is unlikely to be able to handle these events, discard the
ABS_MT_TRACKING_ID completely. This is a bug somewhere in the stack, so
complain and hobble on along.

Note: the kernel doesn't allow that, but we cap to num_slots anyway, see
66fee1bec4.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-04-03 13:31:40 +10:00
Peter Hutterer
27df93737e Move slot-related initialization down
No real effects, but improves readability

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-04-03 13:31:39 +10:00
Peter Hutterer
f8fba5b588 Drop hardcoded MAX_SLOTS in favour of pre-allocated memory
We can't allocate in sync_mt_state since it may be called in the signal
handler. So pre-allocate based on the device's number of slots, store that in
the libevdev struct and use it for the sync process.

This fixes a remaining bug with the handling of ABS_MT_TRACKING_ID. If a
device had > MAX_SLOTS and a slot above that limit would start or stop during
a SYN_DROPPED event, the slot would not be synced, and a subsequent touch in
that slot may double-terminate or double-open a touchpoint in the client.
For the effects of that see

commit 41334b5b40
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Mar 6 11:54:00 2014 +1000

    If the tracking ID changes during SYN_DROPPED, terminate the touch first

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-04-03 13:30:49 +10:00
Peter Hutterer
ca082d5fcb Only sync the initial MT state for Protocol B devices
For protocol A devices we won't get the information from the kernel anyway and
we expect all axes to be updated in the next event.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-04-03 12:08:54 +10:00
Peter Hutterer
7164e1d412 Drop unnecessary memset
The EVICOCGMTSLOTS ioctl returns all slot values for the requested code or an
error code, it doesn't return the number of bytes successfully transferred.
Thus all values in the input array are always defined (on success), we don't
need to memset it.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-04-03 12:08:28 +10:00
Peter Hutterer
fda0b3bf23 Use libevdev_reset from libevdev_free
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-04-02 12:04:46 +10:00
Peter Hutterer
79041dd602 Add quote around device name during error message
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-04-02 11:35:58 +10:00
Peter Hutterer
e8505f57a4 Fix indentation
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-04-01 14:02:41 +10:00
Peter Hutterer
982866824c Shut up another warning
Triggered with -O3

../libevdev/libevdev.c: In function ‘libevdev_get_event_value’:
../libevdev/libevdev.c:1112:6: warning: ‘value’ may be used uninitialized in
this function [-Wmaybe-uninitialized]

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-03-19 09:36:41 +10:00
Peter Hutterer
ab4fdcc0d5 Shut up compiler warning
Triggered with -O

../libevdev/libevdev.c: In function ‘libevdev_has_event_code’:
../libevdev/libevdev-util.h:58:20: warning: ‘mask’ may be used uninitialized
in this function [-Wmaybe-uninitialized]

Optimisation clearly shuffles things around here: in the code, if no max is
found, we return -1 and bail out before we access mask.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-03-19 09:36:41 +10:00
Peter Hutterer
b7bc345b40 Sanitize events when we're skipping sync as well
If a client doesn't sync expliciltly, make sure we sanitize the events when we
update the internal library state.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-03-19 09:36:41 +10:00
Peter Hutterer
41334b5b40 If the tracking ID changes during SYN_DROPPED, terminate the touch first
Most clients can't deal with tracking ID changes unless a -1 is sent first. So
if we notice that the tracking ID has changed during the sync process, send a
set of ABS_MT_TRACKING_ID -1 events for each of those, then send the rest of
the events.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-03-07 10:16:16 +10:00
Benjamin Tissoires
d3ae3da90f Send an extra ABS_MT_SLOT event to sync the client up with the current slot
If multiple slots have changed during the sync handling, the client must be
re-set to the current slot before continuing with normal events.

Signed-off-by: Benjamin Tissoires <btissoir@redhat.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-03-07 10:16:11 +10:00
Peter Hutterer
12ff51b871 Don't sync the MT state for fake MT devices
Devices with ABS_MT_SLOT-1 are fake MT devices, they merely overlap the
axis range but don't actually provide slots. The EVIOCGABS ioctl won't work to
retrieve the current value - the kernel does not store values for those axes
and the return value is always 0.

Thus, simply ignore those axes for fake MT devices and instead rely on the
next event to update the caller with the correct state for each axis.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-03-06 14:30:03 +10:00
Peter Hutterer
66fee1bec4 Cap slot values to the announced maximum
A malicious device may announce N slots but then send a slot index >= N. The
slot state is almost always allocated (definitely the case in libevdev and
true for most callers), so providing a slot number higher than the announced
maximum is likely to lead to invalid dereferences. Don't allow that.
Likewise, don't allow negative slot numbers.

Note that the kernel filters these events anyway, the only way to trigger this
is to change the device fd to something outside the kernel's control.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-03-06 14:30:03 +10:00
Peter Hutterer
24c9ca81f0 Reduce memory requirement for MT syncing
Changes the algorithm: before we'd ioctl all axes for all slots, then generate
events for all slots one-by-one.

Now we ioctl the slot state for each axis, copy the new event value into
the device and mark a bitfield that we've updated the value. Then loop through
the slots and generate events where changed.

Side-effect: this makes it easy to check if anything in the slot has updated,
so we can skip empty slot events during sync.

Min memory requirement for the state storage was:
  MAX_SLOTS  * (ABS_MT_CNT + 1) * sizeof(int) = 1980
Min memory requirement now:
  (ABS_MT_CNT + 1) * sizeof(int) + NLONGS((MAX_SLOTS * ABS_MT_CNT) bits) = 544

This is sigsafe code, so this was stack memory. Reducing the requirement
allows us to up MAX_SLOTS in the future if we need to.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-03-06 09:21:02 +10:00
Peter Hutterer
89e7998fee Dynamically allocate the slot values
Instead of relying on a static MAX_SLOTS array, allocated it based on the
number of slots we have on the device. The previous checks for MAX_SLOTS were
incomplete, causing out-of-bound reads.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-03-06 09:21:02 +10:00
Peter Hutterer
2e06aed955 Don't sync past MAX_SLOTS slots
If a device has more than MAX_SLOTS slots, we'd run out-of-bounds on the sync
array. This function is sig-safe, so we can't alloc here, merely limit the
access.

Reported-by: Jonas Ådahl <jadahl@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2014-03-06 09:21:02 +10:00
Peter Hutterer
f162f00f1d Plug a memory leak for name, uniq, phys
If a device is assigned a name, uniq and/or phys before calling
libevdev_set_fd(), those values would leak.

Change the default alloc to calloc, so name, uniq, and phys are initialized to
zero before we call libevdev_reset

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-02-27 13:19:36 +10:00
Peter Hutterer
a5a06035f9 Replace hardcoded 0 with the enum for it
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-02-25 13:05:33 +10:00
Peter Hutterer
50b82c19b5 Actually filter by log priority
If a message is higher than the current priority, filter it. And add a few
tests that the priority is handled the way it should.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
2014-02-13 08:07:30 +10:00
Peter Hutterer
642c91fc6a Warn about a SYN_DROPPED right after finishing a sync
If the first event after a completed device sync is a SYN_DROPPED, warn the
user that they're not fast enough handling this device.

The test for this is rather complicated since we can't write SYN_DROPPED
through uinput so we have to juggle the device fd and a pipe and switch
between the two at the right time (taking into account that libevdev will read
events from the fd whenever it can).

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-01-22 09:15:14 +10:00
Peter Hutterer
77bf0fe228 Count the number of events needed for a full sync
Make sure we have a queue that is at least large enough to do a full sync
after a SYN_DROPPED, plus store a few extra events in case some came in after
the sync.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
2014-01-22 08:28:41 +10:00
Peter Hutterer
546efc783c Don't treat devices with (ABS_MT_SLOT - 1) as multitouch devices
Some devices (PS3 sixaxis controller) merely have a bunch of axes, without the
semantic information that linux/input.h requires. For those, the ABS_MT range
may be merely another axis, not the special range that we need to treat it
with.

Use a simple heuristic: if ABS_MT_SLOT - 1 is enabled, don't treat ABS_MT as
multitouch axes. The ABS_MT_SLOT - 1 axis is not used for a real axis.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
2013-12-10 19:39:47 +10:00
Peter Hutterer
a2f842bb8a Support EV_REP values through libevdev_get_event_value
We shouldn't have a separate API for that, the whole point of libevdev is to
abstract the quirkyness of the ioctls into a common interface. So let's
export the two EV_REP values through libevdev_get_event_value.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
2013-12-09 09:49:15 +10:00
Peter Hutterer
0aae85122d Constify libevdev_get_repeat
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2013-12-09 09:49:15 +10:00
Peter Hutterer
a612ee753e Drop some leftover deprecated constants.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2013-11-28 17:50:36 +10:00
Peter Hutterer
5812ae0b7a Drop semicolons after getter/setter macros
libevdev.c:921:134: warning: ISO C does not allow extra ';' outside of a
function [-Wpedantic]

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
2013-11-22 12:28:22 +10:00
Peter Hutterer
7a38f4abc3 Drop deprecated functions
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
2013-11-22 10:38:36 +10:00
Peter Hutterer
c4111f717a Check max to see if an event type is valid
There's a gap in the range between EV_SW and EV_LED. Trying to enable one
of those bits will segfault.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
2013-10-24 15:13:41 +10:00
Peter Hutterer
521ba2300e Make sure EV_SYN is always set
Set the bit during device reset and make sure that if we're checking
for the event type we always return true for EV_SYN.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
2013-10-24 15:13:41 +10:00
Peter Hutterer
03c3e4f975 Disallow disabling EV_SYN event codes
The documentation already says that, make it happen.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
2013-10-24 15:13:41 +10:00
Peter Hutterer
b15e5987b3 Reset the struct on set_fd
libevdev_set_fd may fail at a number of points. If it does, it errors out but does nothing
otherwise. Thus, a client may call set_fd again for the same struct but on a different fd and have
it succeed. Depending on when set_fd bailed out the first time, some fields may already be set.

Thus, reset the whole struct at set_fd time to make sure we're nulled out appropriately.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
2013-10-23 09:04:41 +10:00
Peter Hutterer
306f856f67 Work around missing EVIOCGMTSLOTS ioctl
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2013-10-23 09:04:41 +10:00
Peter Hutterer
f9bdb66ab4 When running against a kernel without properties, continue as usual
Missing out on properties is not fatal.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2013-10-23 09:04:41 +10:00
Peter Hutterer
0dbf1ea4f8 Don't allow a negative fd in libevdev_set_fd
Everything else responds with -EBADF, let's do so here as well.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2013-10-14 14:20:55 +10:00
Peter Hutterer
e8920d2fd4 Allow -1 as valid fd in libevdev_change_fd
Add a new flag for "initialized" and separate that from the fd logic. This way,
we can call libevdev_change_fd(dev, -1) to signal that the current fd should be
dropped.

Otherwise libevdev can't be told to release the fd and always keeps a reference
to it.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2013-10-14 14:20:55 +10:00
Peter Hutterer
90fa52f4f6 Print an error on an invalid log priority
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2013-09-18 14:37:35 +10:00
Peter Hutterer
1e81ac1e28 wrap EVIOCSCLOCKID into an API call
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-09-13 09:28:00 +10:00
Peter Hutterer
661602fe3b Name-space the read flags better
Rename from LIBEVDEV_READ_foo to LIBEVDEV_READ_FLAG_foo to differentiate
better from LIBEVDEV_READ_STATUS_foo.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-09-11 12:10:15 +10:00
Peter Hutterer
5d2fc78138 Enumerate libevdev_next_event() return codes
Improved readability in callers, changing magic numbers 0 and 1 to

rc = libevdev_next_event();
if (rc == LIBEVDEV_READ_STATUS_SUCCESS)
    do_something();
else if (rc == LIBEVDEV_READ_STATUS_SYNC)
    do_something_else()

No ABI changes, the enum values are the previously documented values,
this is just a readability improvement.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-09-11 12:10:12 +10:00
Peter Hutterer
ab2f20bfd6 Revamp the API once again
Another look at the current API showed some inconsistencies, rectified
in this commit:

libevdev_kernel_*: modify the underlying kernel device
libevdev_event_type_*: something with an event type
libevdev_event_code_*: something with an event code
libevdev_event_*: struct input_event-related functions (i.e. not device-related)
libevdev_property_*: something with a property
libevdev_*: anything applying to a device

Hopefully that's the last API change. Current symbols deprecated and aliased.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-09-10 11:25:09 +10:00
Peter Hutterer
ad709cf953 Log to stderr by default
The logging we do use atm inside the library is largely
to spot application errors. Log that to stderr by default so
it doesn't get lost.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-09-10 09:37:59 +10:00
Peter Hutterer
a6e25fab76 Log a few errors, specifically application bugs
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-09-03 17:01:40 +10:00
Peter Hutterer
55d67a340b Drop per-device logging function, use per-library one instead
There's no need to have separate logging function for each device created.
More likely, libevdev will be hooked up once into the logging system and
expected to deal with it.

Plus, this allows us to log from the uinput code where we don't
have the context anyway.

Requires a rename to libevdev_set_log_function to avoid ABI breaks, and
while we're breaking the ABI make the logging function more sophisticated
to log line, number, etc.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-09-03 16:58:54 +10:00
Peter Hutterer
22d2a735c4 Return -EBADF for functions that need the fd initialized
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-08-31 13:17:56 +10:00
Peter Hutterer
2c101977b7 Return EBADF when trying to read from an uninitalized device
All other functions that check the fd for validity return EBADF, which also makes it
easier to debug if the actual device goes away.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-08-31 13:17:26 +10:00
Peter Hutterer
9675287062 Use ENOMEM instead of ENOSPC
From errno(3):
   ENOMEM          Not enough space (POSIX.1)
   ENOSPC          No space left on device (POSIX.1)

when we run out memory the reason is a failed malloc, for which ENOMEM
seems more appropriate.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-08-31 12:27:23 +10:00
Peter Hutterer
4417a6a1c1 memcpy instead of invidual bittoggle
The ioctls return the number of bytes copied into the destination, so just
copy them into the device state instead of individually flipping bits.

For easier review: rc is the return value of the EVIOCG* ioctl, which is
the number of bytes copied.

state variables must be initialized to 0 now, in case the kernel's FOO_MAX
is smaller than libevdev's FOO_MAX. If not initialized to 0, the bytes
between the two max values is undefined and we may end up generating bogus
events.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-08-31 09:40:17 +10:00
Peter Hutterer
b77fea9c89 Fix off-by-one errors when dealing with *_MAX values.
LED_MAX, KEY_MAX, ABS_MT_MAX, etc. are all valid event codes

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2013-08-30 17:40:54 +10:00