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_next_event.c | |
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_next_event.c')
-rw-r--r-- | libgamepad_next_event.c | 145 |
1 files changed, 107 insertions, 38 deletions
diff --git a/libgamepad_next_event.c b/libgamepad_next_event.c index c74d641..b9d8986 100644 --- a/libgamepad_next_event.c +++ b/libgamepad_next_event.c @@ -2,56 +2,125 @@ #include "common.h" -int -libgamepad_next_event(struct libgamepad_device *device, struct libgamepad_input_event *eventp) +static int +update_button(struct libgamepad_device *device, uint16_t code, int32_t value) { - int r; - struct input_event ev; + int16_t index; + if (code > ELEMSOF(device->button_map)) + return 0; + index = device->button_map[code]; + if (index < 0 || GETBIT(device->internals->buttons, (size_t)index) == value) + return 1; + XORBIT(device->internals->buttons, (size_t)index); + return 1; +} + + +static int +update_absolute_axis(struct libgamepad_device *device, uint16_t code, int32_t value) +{ + int16_t index; + if (code > ELEMSOF(device->absolute_axis_map)) + return 0; + index = device->absolute_axis_map[code]; + if (index < 0 || device->internals->absinfo[index].value == value) + return 0; + device->internals->absinfo[index].value = value; + return 1; +} + + +ssize_t +libgamepad_next_event(struct libgamepad_device *device, struct libgamepad_input_event *events, size_t max) +{ + size_t i, dequeued = 0; + void *new; + ssize_t r; + struct input_event *ev; + + if (device->internals->deferred_error) { + errno = device->internals->deferred_error; + device->internals->deferred_error = 0; + return -1; + } + + if (device->internals->require_sync) + if (libgamepad_drain_events(device)) + return -1; - if (!device->internals->require_sync) { - r = libevdev_next_event(device->internals->dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); - if (r < 0) { - errno = -r; + if (max > device->internals->evbuf_size) { + if (max > SIZE_MAX / sizeof(*device->internals->evbuf)) { + errno = ENOMEM; return -1; } - } else { - r = libevdev_next_event(device->internals->dev, LIBEVDEV_READ_FLAG_SYNC, &ev); - if (r == -EAGAIN) { - device->internals->require_sync = 0; /* yes, this is how it is document */ - return 0; - } else if (r < 0) { - errno = -r; + new = realloc(device->internals->evbuf, max * sizeof(*device->internals->evbuf)); + if (!new) + return -1; + device->internals->evbuf = new; + device->internals->evbuf_size = max; + } + + dequeued = device->internals->ev_queued < max ? device->internals->ev_queued : max; + if (!dequeued || dequeued < max) { + r = read(device->fd, &device->internals->evbuf[dequeued], (max - dequeued) * sizeof(*device->internals->evbuf)); + if (r <= 0) { + if (!r && (max - dequeued)) + errno = ENODEV; + return -1; + } else if ((size_t)r % sizeof(*device->internals->evbuf)) { + errno = EBADF; return -1; } - if (r != LIBEVDEV_READ_STATUS_SYNC) /* just to be safe */ - device->internals->require_sync = 0; + } else { + r = 0; } + r += (ssize_t)(dequeued * sizeof(*device->internals->evbuf)); - eventp->sync_event = (r == LIBEVDEV_READ_STATUS_SYNC); - eventp->code = ev.code; - eventp->value = ev.value; - eventp->time.tv_sec = ev.input_event_sec; - eventp->time.tv_usec = ev.input_event_usec; + i = 0; + for (ev = device->internals->evbuf; r; r -= (ssize_t)sizeof(*device->internals->evbuf), ev++) { + events[i].code = ev->code; + events[i].value = ev->value; + events[i].time.tv_sec = ev->input_event_sec; + events[i].time.tv_usec = ev->input_event_usec; - switch (ev.type) { - case EV_KEY: - eventp->type = LIBGAMEPAD_BUTTON; - return 1; + switch (ev->type) { + case EV_SYN: + events[i].code = 0; + events[i].value = 0; + if (ev->code == SYN_REPORT) { + events[i++].type = LIBGAMEPAD_EVENT_END; + } else if (ev->code == SYN_DROPPED) { + device->internals->require_sync = device->auto_sync; + events[i++].type = LIBGAMEPAD_EVENT_DROP; + goto out; + } + break; - case EV_ABS: - eventp->type = LIBGAMEPAD_ABSOLUTE_AXIS; - return 1; + case EV_KEY: + ev->value = !!ev->value; + if (update_button(device, ev->code, ev->value)) + events[i++].type = LIBGAMEPAD_BUTTON; + break; - case EV_REL: - eventp->type = LIBGAMEPAD_RELATIVE_AXIS; - return 1; + case EV_REL: + events[i++].type = LIBGAMEPAD_RELATIVE_AXIS; + break; - case EV_SYN: - if (ev.code == SYN_DROPPED) - device->internals->require_sync = 1; - return 0; + case EV_ABS: + if (update_absolute_axis(device, ev->code, ev->value)) + events[i++].type = LIBGAMEPAD_ABSOLUTE_AXIS; + break; - default: - return 0; + default: + break; + } + } + +out: + if (dequeued) { + device->internals->ev_queued -= dequeued; + memmove(&device->internals->evbuf[0], &device->internals->evbuf[dequeued], + device->internals->ev_queued * sizeof(*device->internals->evbuf)); } + return (ssize_t)i; } |