Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a ratbag_dispatch() method to allow hooking into a mainloop #359

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions ratbagd/ratbagd.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,9 +489,20 @@ static int sighandler(sd_event_source *source,
return 0;
}

static int ratbagd_dispatch(sd_event_source *s, int fd,
uint32_t revents, void *data)
{
struct ratbagd *ctx = data;

ratbag_dispatch(ctx->lib_ctx);

return 0;
}

static int ratbagd_run(struct ratbagd *ctx)
{
int r;
int fd;

/*
* TODO: We should support exit-on-idle and bus-activation. Note that
Expand All @@ -515,6 +526,12 @@ static int ratbagd_run(struct ratbagd *ctx)
sigprocmask(SIG_BLOCK, &sigset, NULL);
sd_event_add_signal(ctx->event, NULL, SIGINT, sighandler, NULL);


fd = ratbag_get_fd(ctx->lib_ctx);

sd_event_add_io(ctx->event, NULL, fd, EPOLLIN,
ratbagd_dispatch, ctx);

return sd_event_loop(ctx->event);
}

Expand Down
21 changes: 21 additions & 0 deletions src/libratbag-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,20 @@ struct ratbag_test_device;
struct ratbag_driver;
struct ratbag_button_action;

typedef void (*ratbag_source_dispatch_t)(void *data);

struct ratbag_source {
struct list link;
ratbag_source_dispatch_t dispatch;
void *userdata;
int fd;
};

struct ratbag {
const struct ratbag_interface *interface;
int epoll_fd;
struct list source_destroy_list;

void *userdata;

struct udev *udev;
Expand Down Expand Up @@ -538,3 +550,12 @@ void
ratbag_button_copy_macro(struct ratbag_button *button,
const struct ratbag_button_macro *macro);

struct ratbag_source *
ratbag_add_source(struct ratbag *ratbag,
int fd,
ratbag_source_dispatch_t dispatch,
void *userdata);

void
ratbag_remove_source(struct ratbag *ratbag,
struct ratbag_source *source);
86 changes: 86 additions & 0 deletions src/libratbag.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <sys/epoll.h>
#include <libudev.h>
#include <stdbool.h>
#include <stdio.h>
Expand Down Expand Up @@ -516,21 +517,29 @@ ratbag_create_context(const struct ratbag_interface *interface,
void *userdata)
{
struct ratbag *ratbag;
int epoll_fd;

assert(interface != NULL);
assert(interface->open_restricted != NULL);
assert(interface->close_restricted != NULL);

epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (epoll_fd < 0)
return NULL;

ratbag = zalloc(sizeof(*ratbag));
ratbag->refcount = 1;
ratbag->interface = interface;
ratbag->userdata = userdata;
ratbag->epoll_fd = epoll_fd;

list_init(&ratbag->drivers);
list_init(&ratbag->devices);
list_init(&ratbag->source_destroy_list);
ratbag->udev = udev_new();
if (!ratbag->udev) {
free(ratbag);
close(epoll_fd);
return NULL;
}

Expand All @@ -554,6 +563,17 @@ ratbag_ref(struct ratbag *ratbag)
return ratbag;
}

static inline void
ratbag_drop_destroyed_sources(struct ratbag *ratbag)
{
struct ratbag_source *source, *next;

list_for_each_safe(source, next, &ratbag->source_destroy_list, link)
free(source);

list_init(&ratbag->source_destroy_list);
}

LIBRATBAG_EXPORT struct ratbag *
ratbag_unref(struct ratbag *ratbag)
{
Expand All @@ -563,6 +583,8 @@ ratbag_unref(struct ratbag *ratbag)
assert(ratbag->refcount > 0);
ratbag->refcount--;
if (ratbag->refcount == 0) {
ratbag_drop_destroyed_sources(ratbag);
close(ratbag->epoll_fd);
ratbag->udev = udev_unref(ratbag->udev);
free(ratbag);
}
Expand Down Expand Up @@ -1794,3 +1816,67 @@ ratbag_button_macro_new(const char *name)

return macro;
}

LIBRATBAG_EXPORT int
ratbag_dispatch(struct ratbag *ratbag)
{
struct ratbag_source *source;
struct epoll_event ep[32];
int count;

count = epoll_wait(ratbag->epoll_fd, ep, ARRAY_LENGTH(ep), 0);
if (count < 0)
return -errno;

for (int i = 0; i < count; i++) {
source = ep[i].data.ptr;
if (source->fd == -1)
continue;

source->dispatch(source->userdata);
}

ratbag_drop_destroyed_sources(ratbag);

return 0;
}

LIBRATBAG_EXPORT int
ratbag_get_fd(struct ratbag *ratbag)
{
return ratbag->epoll_fd;
}

struct ratbag_source *
ratbag_add_source(struct ratbag *ratbag,
int fd,
ratbag_source_dispatch_t dispatch,
void *userdata)
{
struct ratbag_source *source;
struct epoll_event ep = {0};

source = zalloc(sizeof *source);
source->dispatch = dispatch;
source->userdata = userdata;
source->fd = fd;

ep.events = EPOLLIN;
ep.data.ptr = source;

if (epoll_ctl(ratbag->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
free(source);
source = NULL;
}

return source;
}

void
ratbag_remove_source(struct ratbag *ratbag,
struct ratbag_source *source)
{
epoll_ctl(ratbag->epoll_fd, EPOLL_CTL_DEL, source->fd, NULL);
source->fd = -1;
list_insert(&ratbag->source_destroy_list, &source->link);
}
29 changes: 29 additions & 0 deletions src/libratbag.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ ratbag_log_set_handler(struct ratbag *ratbag,
ratbag_log_handler log_handler);


typedef int (*ratbag_event_callback)(void *user_data);

/**
* @ingroup base
* @struct ratbag_interface
Expand Down Expand Up @@ -394,6 +396,33 @@ ratbag_ref(struct ratbag *ratbag);
struct ratbag *
ratbag_unref(struct ratbag *ratbag);

/**
* @ingroup base
*
* Main event dispatchment function. Reads events of the file descriptors
* and processes them internally.
*
* This function must be called immediately by the calling process whenever
* events are available on the fd returned by ratbag_get_fd().
*
* @param ratbag A previously initialized ratbag context
* @return 0 on success or a negative errno on failure
*/
int
ratbag_dispatch(struct ratbag *ratbag);

/**
* @ingroup base
*
* Returns the file descriptor for this ratbag context. The calling process
* must call ratbag_dispatch() whenever events become available on this fd.
* must be added to the caller's main loop and monitored for events.
*
* @return The file descriptor used to notify of pending events.
*/
int
ratbag_get_fd(struct ratbag *ratbag);

/**
* @ingroup base
*
Expand Down