diff options
author | Mattias Andrée <maandree@kth.se> | 2022-07-28 20:31:28 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2022-07-28 20:37:42 +0200 |
commit | 402bf1269c59db4b3a78077ab095a84181181808 (patch) | |
tree | b9f445318d9f1e09a5af77ac39b23dc8e50c7a52 /libgamepad.h | |
parent | Minor code improvement (diff) | |
download | libgamepad-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.h | 180 |
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 |