aboutsummaryrefslogtreecommitdiffstats
path: root/libgamepad_open_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgamepad_open_device.c')
-rw-r--r--libgamepad_open_device.c53
1 files changed, 22 insertions, 31 deletions
diff --git a/libgamepad_open_device.c b/libgamepad_open_device.c
index 22163a4..27c5600 100644
--- a/libgamepad_open_device.c
+++ b/libgamepad_open_device.c
@@ -1,10 +1,12 @@
/* See LICENSE file for copyright and license details. */
#include "common.h"
-#define ELEMS_REQUIRED(BITS, TYPE) ((BITS + BITSOF(TYPE) - 1) / BITSOF(TYPE))
#define MAX2(A, B) ((A) > (B) ? (A) : (B))
#define MAX4(A, B, C, D) (MAX2(MAX2(A, B), MAX2(C, D)))
+#define DEFER_EINTR(ERROR_CONDITION, GOTO_ON_FAILURE)\
+ DEFER_EINTR_(devicep, ERROR_CONDITION, GOTO_ON_FAILURE)
+
static void
store_uint(uint64_t value, char *buf)
@@ -128,7 +130,7 @@ libgamepad_open_device(struct libgamepad_device *devicep, int dirfd, const char
ELEMSOF(devicep->absolute_axis_map),
ELEMSOF(devicep->relative_axis_map),
ELEMSOF(devicep->force_feedback_support)), long int)];
- int err, r;
+ int r, saved_errno = errno;
int16_t j;
uint16_t n;
unsigned int i, max;
@@ -139,6 +141,7 @@ libgamepad_open_device(struct libgamepad_device *devicep, int dirfd, const char
memset(devicep, 0, sizeof(*devicep));
devicep->fd = dirfd;
+ devicep->auto_sync = 1;
devicep->internals = calloc(1, sizeof(*devicep->internals));
if (!devicep->internals)
@@ -153,28 +156,17 @@ libgamepad_open_device(struct libgamepad_device *devicep, int dirfd, const char
}
- if (ioctl(devicep->fd, EVIOCGID, &id) < 0)
- goto fail;
+ DEFER_EINTR(ioctl(devicep->fd, EVIOCGID, &id) < 0, fail);
devicep->bus_type = (unsigned int)id.bustype;
devicep->vendor = (unsigned int)id.vendor;
devicep->product = (unsigned int)id.product;
devicep->version = (unsigned int)id.version;
- err = libevdev_new_from_fd(devicep->fd, &devicep->internals->dev);
- if (err < 0) {
- libgamepad_close_device(devicep);
- errno = -err;
- return -1;
- }
-
-
#define GET_STRING(EVIOCMACRO, OUTPUT)\
do {\
for (;;) {\
- r = ioctl(devicep->fd, EVIOCMACRO(bufsize), buf);\
- if (r < 0)\
- goto fail_free_buf;\
+ DEFER_EINTR((r = ioctl(devicep->fd, EVIOCMACRO(bufsize), buf)) < 0, fail_free_buf);\
if ((size_t)r < bufsize)\
break;\
new = realloc(buf, bufsize += 32);\
@@ -196,9 +188,7 @@ libgamepad_open_device(struct libgamepad_device *devicep, int dirfd, const char
#define CREATE_MAPS(EVENTS, SINGULAR, PLURAL)\
do {\
/* Code-to-index map */\
- r = ioctl(devicep->fd, EVIOCGBIT(EVENTS, sizeof(bits)), bits);\
- if (r < 0)\
- goto fail;\
+ DEFER_EINTR((r = ioctl(devicep->fd, EVIOCGBIT(EVENTS, sizeof(bits)), bits)) < 0, fail);\
max = (unsigned int)r * 8;\
devicep->n##PLURAL = 0;\
for (i = 0; i < ELEMSOF(devicep->SINGULAR##_map); i++) {\
@@ -217,7 +207,6 @@ libgamepad_open_device(struct libgamepad_device *devicep, int dirfd, const char
devicep->PLURAL[n++] = (uint16_t)i;\
}\
} while (0)
-
CREATE_MAPS(EV_KEY, button, buttons);
CREATE_MAPS(EV_ABS, absolute_axis, absolute_axes);
CREATE_MAPS(EV_REL, relative_axis, relative_axes);
@@ -228,18 +217,23 @@ libgamepad_open_device(struct libgamepad_device *devicep, int dirfd, const char
if (!devicep->internals->absinfo)
goto fail;
}
- for (i = 0; i < devicep->nabsolute_axes; i++)
- if (ioctl(devicep->fd, EVIOCGABS((unsigned int)devicep->absolute_axes[i]), &devicep->internals->absinfo[i]) < 0)
- goto fail;
+ for (i = 0; i < devicep->nabsolute_axes; i++) {
+ DEFER_EINTR(ioctl(devicep->fd, EVIOCGABS((unsigned int)devicep->absolute_axes[i]),
+ &devicep->internals->absinfo[i]) < 0, fail);
+ if (devicep->internals->absinfo[i].minimum == devicep->internals->absinfo[i].maximum) {
+ if (devicep->absolute_axes[i] == ABS_MT_TRACKING_ID) {
+ devicep->internals->absinfo[i].minimum = -1;
+ devicep->internals->absinfo[i].maximum = 0xFFFF;
+ }
+ }
+ }
if (devicep->nbuttons) {
devicep->internals->buttons = calloc((devicep->nbuttons + 7) / 8, sizeof(*devicep->internals->buttons));
if (!devicep->internals->buttons)
goto fail;
- r = ioctl(devicep->fd, EVIOCGKEY(sizeof(bits)), bits);
- if (r < 0)
- goto fail;
+ DEFER_EINTR((r = ioctl(devicep->fd, EVIOCGKEY(sizeof(bits)), bits)) < 0, fail);
max = (unsigned int)r * 8;
for (i = 0; i < max && i < ELEMSOF(devicep->button_map); i++) {
j = devicep->button_map[i];
@@ -249,9 +243,7 @@ libgamepad_open_device(struct libgamepad_device *devicep, int dirfd, const char
}
- r = ioctl(devicep->fd, EVIOCGBIT(EV_FF, sizeof(bits)), bits);
- if (r < 0)
- goto fail;
+ DEFER_EINTR((r = ioctl(devicep->fd, EVIOCGBIT(EV_FF, sizeof(bits)), bits)) < 0, fail);
max = (unsigned int)r * 8;
for (i = 0; i < BITSOF(devicep->force_feedback_support); i++)
if (i < max && ((bits[i / BITSOF(*bits)] >> (i % BITSOF(*bits))) & 1))
@@ -261,13 +253,12 @@ libgamepad_open_device(struct libgamepad_device *devicep, int dirfd, const char
if (get_fingerprint(devicep, devicep->fingerprint, devicep->fingerprint_unique))
goto fail;
- /* TODO get actual KEY/ABS state */
-
+ errno = saved_errno;
return 0;
fail_free_buf:
free(buf);
fail:
- libgamepad_close_device(devicep);
+ libgamepad_close_device(devicep); /* sets `errno` to `EINTR` if it was deferred */
return -1;
}