/* 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;
}