예제 #1
0
// Polls for and processes events the specified joystick
//
static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js)
{
#if defined(__linux__)
    ssize_t offset = 0;
    char buffer[16384];

    const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));

    while (size > offset)
    {
        regmatch_t match;
        const struct inotify_event* e = (struct inotify_event*) (buffer + offset);

        if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)
        {
            char path[20];
            snprintf(path, sizeof(path), "/dev/input/%s", e->name);
            openJoystickDevice(path);
        }

        offset += sizeof(struct inotify_event) + e->len;
    }

    if (!js->present)
        return GLFW_FALSE;

    // Read all queued events (non-blocking)
    for (;;)
    {
        struct js_event e;

        errno = 0;
        if (read(js->fd, &e, sizeof(e)) < 0)
        {
            // Reset the joystick slot if the device was disconnected
            if (errno == ENODEV)
            {
                free(js->axes);
                free(js->buttons);
                free(js->name);
                free(js->path);

                memset(js, 0, sizeof(_GLFWjoystickLinux));
            }

            break;
        }

        // Clear the initial-state bit
        e.type &= ~JS_EVENT_INIT;

        if (e.type == JS_EVENT_AXIS)
            js->axes[e.number] = (float) e.value / 32767.0f;
        else if (e.type == JS_EVENT_BUTTON)
            js->buttons[e.number] = e.value ? GLFW_PRESS : GLFW_RELEASE;
    }
#endif // __linux__
    return js->present;
}
예제 #2
0
int _glfwInitJoysticks(void)
{
#ifdef _GLFW_USE_LINUX_JOYSTICKS
    int i, joy = 0;
    regex_t regex;
    DIR* dir;
    const char* dirs[] =
    {
        "/dev/input",
        "/dev"
    };

    if (regcomp(&regex, "^js[0-9]\\+$", 0) != 0)
    {
        _glfwSetError(GLFW_PLATFORM_ERROR, "X11: Failed to compile regex");
        return GL_FALSE;
    }

    for (i = 0;  i < sizeof(dirs) / sizeof(dirs[0]);  i++)
    {
        struct dirent* entry;

        dir = opendir(dirs[i]);
        if (!dir)
            continue;

        while ((entry = readdir(dir)))
        {
            char path[20];
            regmatch_t match;

            if (regexec(&regex, entry->d_name, 1, &match, 0) != 0)
                continue;

            snprintf(path, sizeof(path), "%s/%s", dirs[i], entry->d_name);
            if (openJoystickDevice(joy, path))
                joy++;
        }

        closedir(dir);
    }

    regfree(&regex);
#endif // _GLFW_USE_LINUX_JOYSTICKS

    return GL_TRUE;
}
예제 #3
0
void _glfwPollJoystickEvents(void)
{
#if defined(__linux__)
    ssize_t offset = 0;
    char buffer[16384];

    const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));

    while (size > offset)
    {
        regmatch_t match;
        const struct inotify_event* e = (struct inotify_event*) (buffer + offset);

        if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)
        {
            char path[20];
            snprintf(path, sizeof(path), "/dev/input/%s", e->name);
            openJoystickDevice(path);
        }

        offset += sizeof(struct inotify_event) + e->len;
    }
#endif
}
예제 #4
0
// Initialize joystick interface
//
int _glfwInitJoysticks(void)
{
#if defined(__linux__)
    const char* dirname = "/dev/input";
    DIR* dir;

    _glfw->linux_js.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
    if (_glfw->linux_js.inotify == -1)
    {
        _glfwInputError(GLFW_PLATFORM_ERROR,
                        "Linux: Failed to initialize inotify: %s",
                        strerror(errno));
        return GL_FALSE;
    }

    // HACK: Register for IN_ATTRIB as well to get notified when udev is done
    //       This works well in practice but the true way is libudev

    _glfw->linux_js.watch = inotify_add_watch(_glfw->linux_js.inotify,
                                             dirname,
                                             IN_CREATE | IN_ATTRIB);
    if (_glfw->linux_js.watch == -1)
    {
        _glfwInputError(GLFW_PLATFORM_ERROR,
                        "Linux: Failed to watch for joystick connections in %s: %s",
                        dirname,
                        strerror(errno));
        // Continue without device connection notifications
    }

    if (regcomp(&_glfw->linux_js.regex, "^js[0-9]\\+$", 0) != 0)
    {
        _glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
        return GL_FALSE;
    }

    dir = opendir(dirname);
    if (dir)
    {
        struct dirent* entry;

        while ((entry = readdir(dir)))
        {
            char path[20];
            regmatch_t match;

            if (regexec(&_glfw->linux_js.regex, entry->d_name, 1, &match, 0) != 0)
                continue;

            snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
            openJoystickDevice(path);
        }

        closedir(dir);
    }
    else
    {
        _glfwInputError(GLFW_PLATFORM_ERROR,
                        "Linux: Failed to open joystick device directory %s: %s",
                        dirname,
                        strerror(errno));
        // Continue with no joysticks detected
    }

#endif // __linux__

    return GL_TRUE;
}
예제 #5
0
// Polls for and processes events for all present joysticks
//
static void pollJoystickEvents(void)
{
#if defined(__linux__)
    int i;
    struct js_event e;
    ssize_t offset = 0;
    char buffer[16384];

    const ssize_t size = read(_glfw->linux_js.inotify, buffer, sizeof(buffer));

    while (size > offset)
    {
        regmatch_t match;
        const struct inotify_event* e = (struct inotify_event*) (buffer + offset);

        if (regexec(&_glfw->linux_js.regex, e->name, 1, &match, 0) == 0)
        {
            char path[20];
            snprintf(path, sizeof(path), "/dev/input/%s", e->name);
            openJoystickDevice(path);
        }

        offset += sizeof(struct inotify_event) + e->len;
    }

    for (i = 0;  i <= GLFW_JOYSTICK_LAST;  i++)
    {
        if (!_glfw->linux_js.js[i].present)
            continue;

        // Read all queued events (non-blocking)
        for (;;)
        {
            errno = 0;
            if (read(_glfw->linux_js.js[i].fd, &e, sizeof(e)) < 0)
            {
                if (errno == ENODEV)
                {
                    // The joystick was disconnected

                    free(_glfw->linux_js.js[i].axes);
                    free(_glfw->linux_js.js[i].buttons);
                    free(_glfw->linux_js.js[i].name);
                    free(_glfw->linux_js.js[i].path);

                    memset(&_glfw->linux_js.js[i], 0, sizeof(_glfw->linux_js.js[i]));
                }

                break;
            }

            // We don't care if it's an init event or not
            e.type &= ~JS_EVENT_INIT;

            switch (e.type)
            {
                case JS_EVENT_AXIS:
                    _glfw->linux_js.js[i].axes[e.number] =
                        (float) e.value / 32767.0f;
                    break;

                case JS_EVENT_BUTTON:
                    _glfw->linux_js.js[i].buttons[e.number] =
                        e.value ? GLFW_PRESS : GLFW_RELEASE;
                    break;

                default:
                    break;
            }
        }
    }
#endif // __linux__
}