/* See LICENSE file for copyright and license details. */ #include "common.h" int libgamepad_open_device(struct libgamepad_device *devicep, int dirfd, const char *path, int mode) { int err; unsigned int i; uint16_t n; struct input_id id; devicep->fd = dirfd; devicep->close_fd = 0; devicep->require_sync = 0; devicep->dev = NULL; devicep->buttons = NULL; devicep->absolute_axes = NULL; devicep->relative_axes = NULL; memset(devicep->force_feedback_support, 0, sizeof(devicep->force_feedback_support)); if (path && *path) { devicep->fd = openat(dirfd, path, mode); if (devicep->fd < 0) return -1; devicep->close_fd = 1; } if (ioctl(devicep->fd, EVIOCGID, &id)) { if (devicep->close_fd) { close(devicep->fd); devicep->close_fd = 0; } return -1; } err = libevdev_new_from_fd(devicep->fd, &devicep->dev); if (err < 0) { if (devicep->close_fd) { close(devicep->fd); devicep->close_fd = 0; } errno = -err; return -1; } devicep->name = libevdev_get_name(devicep->dev); devicep->unique_id = libevdev_get_uniq(devicep->dev); devicep->physical_location = libevdev_get_phys(devicep->dev); 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; devicep->nbuttons = 0; for (i = 0; i < KEY_CNT; i++) { devicep->button_map[i] = -1; if (libevdev_has_event_code(devicep->dev, EV_KEY, i)) devicep->button_map[i] = (int16_t)devicep->nbuttons++; } devicep->nabsolute_axes = 0; for (i = 0; i < ABS_CNT; i++) { devicep->absolute_axis_map[i] = -1; if (libevdev_has_event_code(devicep->dev, EV_ABS, i)) devicep->absolute_axis_map[i] = (int16_t)devicep->nabsolute_axes++; } devicep->nrelative_axes = 0; for (i = 0; i < REL_CNT; i++) { devicep->relative_axis_map[i] = -1; if (libevdev_has_event_code(devicep->dev, EV_REL, i)) devicep->relative_axis_map[i] = (int16_t)devicep->nrelative_axes++; } for (i = 0; i < FF_CNT; i++) if (libevdev_has_event_code(devicep->dev, EV_FF, i)) devicep->force_feedback_support[i / 8] |= (uint8_t)(1 << (i & 7)); if (devicep->nbuttons) { devicep->buttons = calloc(devicep->nbuttons, sizeof(*devicep->buttons)); if (!devicep->buttons) goto fail; for (i = 0, n = 0; i < KEY_CNT; i++) if (devicep->button_map[i] >= 0) devicep->buttons[n++] = (uint16_t)i; } if (devicep->nabsolute_axes) { devicep->absolute_axes = calloc(devicep->nabsolute_axes, sizeof(*devicep->absolute_axes)); if (!devicep->absolute_axes) goto fail; for (i = 0, n = 0; i < ABS_CNT; i++) if (devicep->absolute_axis_map[i] >= 0) devicep->absolute_axes[n++] = (uint16_t)i; } if (devicep->nrelative_axes) { devicep->relative_axes = calloc(devicep->nrelative_axes, sizeof(*devicep->relative_axes)); if (!devicep->relative_axes) goto fail; for (i = 0, n = 0; i < REL_CNT; i++) if (devicep->relative_axis_map[i] >= 0) devicep->relative_axes[n++] = (uint16_t)i; } return 0; fail: libgamepad_close_device(devicep); return -1; }