aboutsummaryrefslogtreecommitdiffstats
path: root/libgamepad.h
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2022-07-28 20:31:28 +0200
committerMattias Andrée <maandree@kth.se>2022-07-28 20:37:42 +0200
commit402bf1269c59db4b3a78077ab095a84181181808 (patch)
treeb9f445318d9f1e09a5af77ac39b23dc8e50c7a52 /libgamepad.h
parentMinor code improvement (diff)
downloadlibgamepad-402bf1269c59db4b3a78077ab095a84181181808.tar.gz
libgamepad-402bf1269c59db4b3a78077ab095a84181181808.tar.bz2
libgamepad-402bf1269c59db4b3a78077ab095a84181181808.tar.xz
Remove dependency on libevdev (mostly complete) + minor fixes
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'libgamepad.h')
-rw-r--r--libgamepad.h180
1 files changed, 148 insertions, 32 deletions
diff --git a/libgamepad.h b/libgamepad.h
index 5cee653..7a046a3 100644
--- a/libgamepad.h
+++ b/libgamepad.h
@@ -12,8 +12,6 @@
#include <time.h>
#include <unistd.h>
-#include <libevdev/libevdev.h>
-
#if defined(__GNUC__)
# define LIBGAMEPAD_PURE__ __attribute__((__pure__))
@@ -144,7 +142,7 @@ enum libgamepad_game_controller {
*/
LIBGAMEPAD_CONTROLLER_OTHER,
- /* TODO force feedback capabilities */
+ /* TODO Document force feedback capabilities */
/**
* Amazon Luna Controller
@@ -1328,17 +1326,56 @@ enum libgamepad_type {
*/
enum libgamepad_input_type {
/**
+ * Signals thatevents where dropped because
+ * the application did not read fast enough
+ *
+ * When received, the next call to `libgamepad_next_event`
+ * will drain the event queue and generate synchronisation
+ * events (which have the timestamp set to zero) to bring
+ * the applications state of the buttons/keys and absolute
+ * axes up to date
+ */
+ LIBGAMEPAD_EVENT_DROP,
+
+ /**
+ * Signals that all previous events, from the
+ * last `LIBGAMEPAD_EVENT_END` or `LIBGAMEPAD_EVENT_DROP`
+ * where part of the same report from the input device
+ *
+ * This event will always be sent, however it may have
+ * been dropped when a `LIBGAMEPAD_EVENT_DROP` is sent
+ */
+ LIBGAMEPAD_EVENT_END,
+
+ /**
* Button/key
+ *
+ * Expectation when `LIBGAMEPAD_EVENT_DROP` has been
+ * received: a full press and release, or release and
+ * press, may be missing the if read interval is longer
+ * than such an event would span
*/
LIBGAMEPAD_BUTTON,
/**
* Absolute axis
+ *
+ * Expectation when `LIBGAMEPAD_EVENT_DROP` has been
+ * received: less smooth transition between two states,
+ * and quick movements in one direction and back may
+ * be missing, but only such movements that are sorter
+ * than the read duration
*/
LIBGAMEPAD_ABSOLUTE_AXIS,
/**
* Relative axis
+ *
+ * Expectation when `LIBGAMEPAD_EVENT_DROP` has been
+ * received: movement details are lost and calculate
+ * position is off (it is possible that the driver
+ * sends synchronisations event to adjust for the
+ * position)
*/
LIBGAMEPAD_RELATIVE_AXIS
};
@@ -1349,29 +1386,30 @@ enum libgamepad_input_type {
*/
struct libgamepad_input_event {
/**
- * The affect input type
+ * The affected input type
*/
enum libgamepad_input_type type;
/**
- * Whether the event was polled in a
- * synchronisation read
- */
- short int sync_event;
-
- /**
- * The button/key or axis affect by the event
+ * The button/key or axis affected by the event
+ *
+ * Not set if `.type` is `LIBGAMEPAD_EVENT_DROP`
*/
uint16_t code;
/**
* The new value on the button/key or axis,
* or the delta if on a relative axis
+ *
+ * Not set if `.type` is `LIBGAMEPAD_EVENT_DROP`
*/
int32_t value;
/**
* Event timestamp
+ *
+ * Set to zero if not supported by the driver
+ * or if the event generated by the library
*/
struct timeval time;
};
@@ -1454,6 +1492,13 @@ struct libgamepad_device {
int fd;
/**
+ * Specifies whether the library shall automatically call
+ * `libgamepad_generate_sync_events` if events are dropped
+ * or the event queue is manually drained
+ */
+ int auto_sync;
+
+ /**
* Bus type the device is connect via, see BUS_-prefixed
* constants in <linux/input.h>
*/
@@ -1663,6 +1708,11 @@ int libgamepad_get_attachment_event(LIBGAMEPAD_ATTACHMENT_MONITOR *, char **, si
/**
* Open a subdevice
*
+ * This function may temporarily modify the file status
+ * flags (which affects all duplicate file descriptors
+ * share the same open file descriptor) of `dirfd` if
+ * `path` is `NULL` or empty
+ *
* @param devicep Output parameter for the device information and handles;
* deallocated with `libgamepad_close_device`
* @param dirfd File descriptor to path that `path` is relative to
@@ -1678,40 +1728,83 @@ int libgamepad_get_attachment_event(LIBGAMEPAD_ATTACHMENT_MONITOR *, char **, si
* @return 0 on success, -1 on failure
*
* This function may fail for any reason specified for
- * malloc(3), openat(3) or libevdev_new_from_fd(3)
+ * realloc(3), openat(3), ioctl(3), or read(3)
*/
int libgamepad_open_device(struct libgamepad_device *, int, const char *, int);
/**
* Close a subdevice
*
- * @param device Device information and handles, may be `NULL`
+ * @param device Device information and handles, may be `NULL`
+ * @return Normally 0, -1 if there was a deferred error
*/
-void libgamepad_close_device(struct libgamepad_device *);
+int libgamepad_close_device(struct libgamepad_device *);
/**
* Get the next event on a subdevice
*
- * NB! events may be queued internally (by libevdev), therefore
- * an application must either call this function in a loop in
- * its own thread, or have the device opened in non-blocking
- * mode and even the poll the device's file descriptor for
- * read-readyness and when it is ready clal this function in
- * a loop until it sets `errno` to `EAGAIN`.
+ * This function may temporarily modify the file status
+ * flags of the open file decriptor it uses to access
+ * the device
*
* @param device Device to read an event from
- * @param eventp Output parameter for the event
- * @return 1 if an event was returned,
- * 0 if no event was returned,
- * -1 on failure
+ * @param events Output buffer for the events (will be in order)
+ * @param max The number of elements `events` fit
+ * (may be 0 for error condition checking)
+ * @return The number of returned events (may be more or
+ * less than actually read), -1 on failure
*
* This function may fail for any reason specified for
- * libevdev_next_event(3), including:
+ * realloc(3) and read(3), including:
* - EAGAIN no more data currently available (non-blocking mode)
* - EINTR system call was interrupted, try again
+ * (may be deferred to `libgamepad_close_device`)
* - ENODEV device has been unplugged or access has been revoked
*/
-int libgamepad_next_event(struct libgamepad_device *, struct libgamepad_input_event *);
+ssize_t libgamepad_next_event(struct libgamepad_device *, struct libgamepad_input_event *, size_t);
+
+/**
+ * Remove all events on a subdevice queued by kernel
+ * and queue synchronisation events so that the application
+ * will have (after reading them) up to date button/key and
+ * absolute axis states
+ *
+ * This function is normally used internally, but can be
+ * useful after calling `libgamepad_set_clock`
+ *
+ * This function may temporarily modify the file status
+ * flags of the open file decriptor it uses to access
+ * the device
+ *
+ * @param device Device to drain queue for
+ * @return 0 on success, -1 on failure
+ *
+ * This function may fail for any reason specified for
+ * realloc(3) and read(3), including:
+ * - ENODEV device has been unplugged or access has been revoked
+ * except for EINTR which is deferred to the next call to
+ * `libgamepad_next_event` or `libgamepad_close_device`
+ * (whichever comes first) for the same device, and EAGAIN
+ */
+int libgamepad_drain_events(struct libgamepad_device *);
+
+/**
+ * Generates any events needed to keep the applications
+ * button/key and absolute axes states up to date
+ *
+ * This function is normally used internally, but can be
+ * useful after calling `libgamepad_drain_events` if
+ * automatic generation of synchronisation events have
+ * been disabled by modifying `device->auto_sync`
+ *
+ * This function may temporarily modify the file status
+ * flags of the open file decriptor it uses to access
+ * the device
+ *
+ * @param device Device to synchronise
+ * @return 0 on success, -1 on failure
+ */
+int libgamepad_generate_sync_events(struct libgamepad_device *);
/**
@@ -1733,7 +1826,7 @@ int libgamepad_next_event(struct libgamepad_device *, struct libgamepad_input_ev
* @param code The button/key
* @return The button/key's name, `NULL` if not found
*/
-const char *libgamepad_get_button_name(const struct libgamepad_device *, uint16_t);
+LIBGAMEPAD_PURE__ const char *libgamepad_get_button_name(const struct libgamepad_device *, uint16_t);
/**
* Get the name of an absolute axis
@@ -1754,7 +1847,7 @@ const char *libgamepad_get_button_name(const struct libgamepad_device *, uint16_
* @param code The axis
* @return The axis' name, `NULL` if not found
*/
-const char *libgamepad_get_absolute_axis_name(const struct libgamepad_device *, uint16_t);
+LIBGAMEPAD_PURE__ const char *libgamepad_get_absolute_axis_name(const struct libgamepad_device *, uint16_t);
/**
* Get the name of a relative axis
@@ -1775,7 +1868,7 @@ const char *libgamepad_get_absolute_axis_name(const struct libgamepad_device *,
* @param code The axis
* @return The axis' name, `NULL` if not found
*/
-const char *libgamepad_get_relative_axis_name(const struct libgamepad_device *, uint16_t);
+LIBGAMEPAD_PURE__ const char *libgamepad_get_relative_axis_name(const struct libgamepad_device *, uint16_t);
/**
* Get a button/key code from it's name
@@ -1875,6 +1968,10 @@ libgamepad_get_device_has_ff_effect(const struct libgamepad_device *device, uint
* libgamepad reads the current state when a device
* is opened.
*
+ * This information is not necessarily up to date
+ * before the first `LIBGAMEPAD_EVENT_END` has been
+ * reported
+ *
* @param device The device to retrieve the information for
* @param code The button/key
* @return 1 if the button/key is pressed down,
@@ -1894,12 +1991,21 @@ int libgamepad_get_button_is_pressed(struct libgamepad_device *, uint16_t);
* libgamepad reads the current state when a device
* is opened.
*
+ * The value of `.value` in the returned pointer is
+ * not necessarily up to date before the first
+ * `LIBGAMEPAD_EVENT_END` has been reported
+ *
* @param device The device to retrieve the information for
* @param code The axis
- * @return Information about the axis
+ * @return Information about the axis; this is a pointer
+ * stored inside `device`, some function calls
+ * may alter the contents of invalidate the pointer,
+ * `libgamepad_close_device(device)` will always
+ * invalidate the pointer and it is expected that
+ * `libgamepad_next_event` often alters `.value`
*/
-LIBGAMEPAD_PURE__ const struct input_absinfo *libgamepad_get_absolute_axis_info(struct libgamepad_device *, uint16_t);
-/* `struct input_absinfo` is defined in <linux/input.h> */
+LIBGAMEPAD_PURE__ /* `struct input_absinfo` is defined in <linux/input.h> */
+const struct input_absinfo *libgamepad_get_absolute_axis_info(struct libgamepad_device *, uint16_t);
/**
@@ -1940,6 +2046,16 @@ libgamepad_ungrab(struct libgamepad_device *device)
/**
* Set the clock that event timestamps shall be reported in
*
+ * If your application depends on new events using the
+ * selected clock (if any at all), call `libgamepad_drain_events`
+ * after this function
+ *
+ * Support clocks are (in Linux 5.18):
+ * - CLOCK_REALTIME
+ * - CLOCK_MONOTONIC
+ * - CLOCK_BOOTTIME
+ * As usual, CLOCK_MONOTONIC_RAW is not supported
+ *
* @param device The device to configure
* @param clockid The clock to use on event timestamps
* @return 0 on success, -1 on failure