mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
Input merger
This component merges the input events of multiple sources. Example configuration: <start name="input_merger"> <resource name="RAM" quantum="1M" /> <provides> <service name="Input" /> </provides> <config> <input label="ps2" /> <input label="usb_hid" /> </config> <route> <service name="Input"> <if-arg key="label" value="ps2" /> <child name="ps2_drv" /> </service> <service name="Input"> <if-arg key="label" value="usb_hid" /> <child name="usb_drv" /> </service> <any-service> <parent /> <any-child /> </any-service> </route> </start> For each 'input' config node, the component opens an 'Input' session with the configured label. This label is then evaluated by 'init' to route the session request to a specific input source component. Fixes #1259.
This commit is contained in:
parent
3befb64afe
commit
81af714949
27
repos/os/src/server/input_merger/README
Normal file
27
repos/os/src/server/input_merger/README
Normal file
@ -0,0 +1,27 @@
|
||||
This component merges the input events of multiple sources.
|
||||
|
||||
Example configuration:
|
||||
|
||||
<start name="input_merger">
|
||||
<resource name="RAM" quantum="1M" />
|
||||
<provides>
|
||||
<service name="Input" />
|
||||
</provides>
|
||||
<config>
|
||||
<input label="ps2" />
|
||||
<input label="usb_hid" />
|
||||
</config>
|
||||
<route>
|
||||
<service name="Input">
|
||||
<if-arg key="label" value="ps2" /> <child name="ps2_drv" />
|
||||
</service>
|
||||
<service name="Input">
|
||||
<if-arg key="label" value="usb_hid" /> <child name="usb_drv" />
|
||||
</service>
|
||||
<any-service> <parent /> <any-child /> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
For each 'input' config node, the component opens an 'Input' session with the
|
||||
configured label. This label is then evaluated by 'init' to route the session
|
||||
request to a specific input source component.
|
169
repos/os/src/server/input_merger/main.cc
Normal file
169
repos/os/src/server/input_merger/main.cc
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* \brief Input event merger
|
||||
* \author Christian Prochaska
|
||||
* \date 2014-09-29
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <input/component.h>
|
||||
#include <input_session/connection.h>
|
||||
#include <os/attached_dataspace.h>
|
||||
#include <os/config.h>
|
||||
#include <os/server.h>
|
||||
#include <os/static_root.h>
|
||||
#include <util/list.h>
|
||||
|
||||
|
||||
namespace Input_merger
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
class Input_source : public List<Input_source>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Input::Session_capability _create_session(const char *label)
|
||||
{
|
||||
char session_args[sizeof(Parent::Session_args)];
|
||||
|
||||
Arg_string::set_arg(session_args, sizeof(Parent::Session_args),
|
||||
"ram_quota", "16K");
|
||||
Arg_string::set_arg(session_args, sizeof(Parent::Session_args),
|
||||
"label", label);
|
||||
|
||||
return env()->parent()->session<Input::Session>(session_args);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Input::Session_client session_client;
|
||||
Attached_dataspace dataspace;
|
||||
|
||||
Input_source(const char *label)
|
||||
: session_client(_create_session(label)),
|
||||
dataspace(session_client.dataspace()) { }
|
||||
|
||||
~Input_source()
|
||||
{
|
||||
env()->parent()->close(session_client);
|
||||
}
|
||||
};
|
||||
|
||||
struct Main;
|
||||
}
|
||||
|
||||
|
||||
/******************
|
||||
** Main program **
|
||||
******************/
|
||||
|
||||
struct Input_merger::Main
|
||||
{
|
||||
Server::Entrypoint &ep;
|
||||
List<Input_source> input_source_list;
|
||||
|
||||
/*
|
||||
* Input session provided to our client
|
||||
*/
|
||||
Input::Session_component input_session_component;
|
||||
|
||||
/*
|
||||
* Attach root interface to the entry point
|
||||
*/
|
||||
Static_root<Input::Session> input_root { ep.manage(input_session_component) };
|
||||
|
||||
void handle_input(unsigned)
|
||||
{
|
||||
for (Input_source *input_source = input_source_list.first();
|
||||
input_source;
|
||||
input_source = input_source->next()) {
|
||||
|
||||
Input::Event const * const events =
|
||||
input_source->dataspace.local_addr<Input::Event>();
|
||||
|
||||
unsigned const num = input_source->session_client.flush();
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
input_session_component.submit(events[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Signal_rpc_member<Main> input_dispatcher =
|
||||
{ ep, *this, &Main::handle_input};
|
||||
|
||||
|
||||
void handle_config_update(unsigned)
|
||||
{
|
||||
Genode::config()->reload();
|
||||
|
||||
for (Input_source *input_source;
|
||||
(input_source = input_source_list.first()); ) {
|
||||
input_source_list.remove(input_source);
|
||||
destroy(env()->heap(), input_source);
|
||||
}
|
||||
|
||||
try {
|
||||
for (Xml_node input_node = config()->xml_node().sub_node("input");
|
||||
;
|
||||
input_node = input_node.next("input")) {
|
||||
|
||||
char label_buf[128];
|
||||
input_node.attribute("label").value(label_buf, sizeof(label_buf));
|
||||
|
||||
Input_source *input_source(new (env()->heap()) Input_source(label_buf));
|
||||
|
||||
input_source_list.insert(input_source);
|
||||
|
||||
input_source->session_client.sigh(input_dispatcher);
|
||||
}
|
||||
} catch (Xml_node::Nonexistent_sub_node) { }
|
||||
|
||||
}
|
||||
|
||||
Signal_rpc_member<Main> config_update_dispatcher =
|
||||
{ ep, *this, &Main::handle_config_update};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Main(Server::Entrypoint &ep) : ep(ep)
|
||||
{
|
||||
input_session_component.event_queue().enabled(true);
|
||||
|
||||
/*
|
||||
* Apply initial configuration
|
||||
*/
|
||||
handle_config_update(0);
|
||||
|
||||
/*
|
||||
* Register signal handler
|
||||
*/
|
||||
Genode::config()->sigh(config_update_dispatcher);
|
||||
|
||||
/*
|
||||
* Announce service
|
||||
*/
|
||||
Genode::env()->parent()->announce(ep.manage(input_root));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/************
|
||||
** Server **
|
||||
************/
|
||||
|
||||
namespace Server {
|
||||
|
||||
char const *name() { return "input_merger_ep"; }
|
||||
|
||||
size_t stack_size() { return 4*1024*sizeof(addr_t); }
|
||||
|
||||
void construct(Entrypoint &ep) { static Input_merger::Main inst(ep); }
|
||||
}
|
3
repos/os/src/server/input_merger/target.mk
Normal file
3
repos/os/src/server/input_merger/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
TARGET = input_merger
|
||||
SRC_CC = main.cc
|
||||
LIBS = base config server
|
Loading…
x
Reference in New Issue
Block a user