os: introduce C API for generating Genode events

This patch introduces a C API to be used by input drivers to generate
Genode events. The initial version is limited to multitouch events only.

Fixes #4273
This commit is contained in:
Norman Feske
2021-09-29 16:14:12 +02:00
parent f4cb5cc299
commit 32c283d26f
2 changed files with 230 additions and 0 deletions

View File

@ -0,0 +1,134 @@
/*
* \brief C interface to Genode's event session
* \author Norman Feske
* \date 2021-09-29
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/registry.h>
#include <base/log.h>
#include <base/session_label.h>
#include <event_session/connection.h>
#include <genode_c_api/event.h>
using namespace Genode;
static Env *_env_ptr;
static Allocator *_alloc_ptr;
static Registry<Registered<genode_event>> _event_sessions { };
struct genode_event : private Noncopyable, private Interface
{
private:
Env &_env;
Allocator &_alloc;
Session_label const _session_label;
Event::Connection _connection { _env, _session_label.string() };
public:
genode_event(Env &env, Allocator &alloc,
Session_label const &session_label)
:
_env(env), _alloc(alloc), _session_label(session_label)
{ }
template <typename FN>
void with_batch(FN const &fn)
{
_connection.with_batch(fn);
}
};
void genode_event_init(genode_env *env_ptr,
genode_allocator *alloc_ptr)
{
_env_ptr = env_ptr;
_alloc_ptr = alloc_ptr;
}
namespace {
struct Submit : genode_event_submit
{
Event::Session_client::Batch &batch;
template <typename FN>
static void _with_batch(struct genode_event_submit *myself, FN const &fn)
{
fn(static_cast<Submit *>(myself)->batch);
}
static void _touch(struct genode_event_submit *myself,
struct genode_event_touch_args const *args)
{
Input::Touch_id id { (int)args->finger };
_with_batch(myself, [&] (Event::Session_client::Batch &batch) {
batch.submit(Input::Touch { id, (float)args->xpos, (float)args->ypos }); });
}
static void _touch_release(struct genode_event_submit *myself,
unsigned finger)
{
Input::Touch_id id { (int)finger };
_with_batch(myself, [&] (Event::Session_client::Batch &batch) {
batch.submit(Input::Touch_release { id }); });
}
Submit(Event::Session_client::Batch &batch)
:
batch(batch)
{
touch = _touch;
touch_release = _touch_release;
};
};
}
void genode_event_generate(struct genode_event *event_session,
genode_event_generator_t generator_fn,
struct genode_event_generator_ctx *ctx)
{
event_session->with_batch([&] (Event::Session_client::Batch &batch) {
Submit submit { batch };
(*generator_fn)(ctx, &submit);
});
}
struct genode_event *genode_event_create(struct genode_event_args const *args)
{
if (!_env_ptr || !_alloc_ptr) {
error("genode_event_create: missing call of genode_event_init");
return nullptr;
}
return new (*_alloc_ptr)
Registered<genode_event>(_event_sessions, *_env_ptr, *_alloc_ptr,
Session_label(args->label));
}
void genode_event_destroy(struct genode_event *event_ptr)
{
destroy(*_alloc_ptr, event_ptr);
}