server/input_remap

General purpose component for remapping input codes.

Fixes #25
This commit is contained in:
Emery Hemingway
2016-07-16 11:26:20 +02:00
committed by Norman Feske
parent a09410cd09
commit 1e0fa7571c
3 changed files with 164 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
Input_remap is a small shim server that remaps keys. It was intended for swapping
buttons on game controllers, but is suitable for any key code remapping.
The configuration is simple, key codes can be discovered using the
'test/input' utility in the Genode os repository.
! <config>
! <map from="BTN_X" to="BTN_A"/>
! <map from="BTN_Y" to="BTN_B"/>
! <map from="BTN_Z" to="BTN_C"/>
! <map from="BTN_A" to="BTN_X"/>
! <map from="BTN_B" to="BTN_Y"/>
! <map from="BTN_C" to="BTN_Z"/>
! <map from="KEY_SPACE" to="KEY_BACKSPACE"/>
! </config>

View File

@@ -0,0 +1,147 @@
/*
* \brief Input event remapper
* \author Emery Hemingway
* \date 2016-07-10
*/
/*
* Copyright (C) 2016 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/keycodes.h>
#include <input/component.h>
#include <input_session/connection.h>
#include <os/static_root.h>
#include <base/attached_rom_dataspace.h>
#include <base/component.h>
#include <base/log.h>
namespace Input { struct Remap; }
struct Input::Remap
{
typedef Genode::String<32> Keyname;
int code_map[Input::Keycode::KEY_MAX];
Genode::Env &env;
Genode::Attached_rom_dataspace config_rom { env, "config" };
/*
* Input session provided by our parent
*/
Input::Session_client parent_input
{ env.parent().session<Input::Session>("ram_quota=16K") };
Genode::Attached_dataspace input_dataspace { parent_input.dataspace() };
/*
* Input session provided to our client
*/
Input::Session_component input_session_component;
/*
* Attach root interface to the entry point
*/
Genode::Static_root<Input::Session> input_root
{ env.ep().manage(input_session_component) };
void event_flush()
{
Input::Event const * const events =
input_dataspace.local_addr<Input::Event>();
unsigned const num = parent_input.flush();
for (unsigned i = 0; i < num; i++) {
Event e = events[i];
if ((e.type() == Event::PRESS) || (e.type() == Event::RELEASE))
input_session_component.submit(Event(
e.type(), code_map[e.code()], e.ax(), e.ay(), e.rx(), e.ry()));
else
input_session_component.submit(e);
}
}
Genode::Signal_handler<Remap> event_flusher
{ env.ep(), *this, &Remap::event_flush };
static int lookup_code(Keyname const &name)
{
/* not the fastest way to do this, just the most terse */
for (int code = 0; code < Input::Keycode::KEY_MAX; ++code)
if (name == key_name((Keycode)code)) return code;
return KEY_UNKNOWN;
}
void remap()
{
using namespace Genode;
/* load the default mappings */
for (int code = 0; code < Input::Keycode::KEY_MAX; ++code)
code_map[code] = code;
config_rom.xml().for_each_sub_node("map", [&] (Xml_node node) {
Keyname const from = node.attribute_value("from", Keyname());
Keyname const to = node.attribute_value("to", Keyname());
if ((from == "") || (to == "")) {
char tmp[128];
strncpy(tmp, node.addr(), min(sizeof(tmp), node.size()+1));
error("ignoring mapping '", tmp, "'");
return;
}
int from_code = lookup_code(from);
int to_code = lookup_code(to);
if (from_code == KEY_UNKNOWN) {
error("unknown key ", from.string());
return;
}
if (to_code == KEY_UNKNOWN) {
error("unknown key ", to.string());
return;
}
code_map[from_code] = to_code;
});
}
Genode::Signal_handler<Remap> config_handler
{ env.ep(), *this, &Remap::remap };
/**
* Constructor
*/
Remap(Genode::Env &env) : env(env)
{
config_rom.sigh(config_handler);
parent_input.sigh(event_flusher);
remap();
input_session_component.event_queue().enabled(true);
env.parent().announce(env.ep().manage(input_root));
}
~Remap()
{
env.parent().close(parent_input);
}
};
/***************
** Component **
***************/
Genode::size_t Component::stack_size() { return 4*1024*sizeof(Genode::addr_t); }
void Component::construct(Genode::Env &env) { static Input::Remap inst(env); }

View File

@@ -0,0 +1,3 @@
TARGET = input_remap
SRC_CC = component.cc
LIBS = base