remove input_remap in favor of input_merger

This commit is contained in:
Emery Hemingway
2017-11-27 19:29:55 -06:00
parent 762c13ccfa
commit 869522b100
10 changed files with 15 additions and 618 deletions

View File

@@ -15,7 +15,6 @@ set build_components {
drivers/timer
libretro/nxengine
server/fb_upscale
server/input_remap
}
source ${genode_dir}/repos/base/run/platform_drv.inc
@@ -109,30 +108,6 @@ append config {
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="input_remap">
<resource name="RAM" quantum="2M"/>
<provides> <service name="Input"/> </provides>
<config>
<!-- Retroarch mappings -->
<map from="KEY_Z" to="BTN_B"/>
<map from="KEY_A" to="BTN_Y"/>
<map from="KEY_X" to="BTN_A"/>
<map from="KEY_S" to="BTN_X"/>
<map from="KEY_Q" to="BTN_TL"/>
<map from="KEY_W" to="BTN_TR"/>
<map from="KEY_ENTER" to="BTN_START"/>
<map from="KEY_RIGHTSHIFT" to="BTN_SELECT"/>
<map from="KEY_LEFT" to="BTN_LEFT"/>
<map from="KEY_RIGHT" to="BTN_RIGHT"/>
<map from="KEY_UP" to="BTN_FORWARD"/>
<map from="KEY_DOWN" to="BTN_BACK"/>
</config>
<route>
<service name="Input">
<child name="input_drv"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="report_rom">
<resource name="RAM" quantum="4M"/>
<provides> <service name="Report"/> </provides>
@@ -141,6 +116,18 @@ append config {
<start name="retro_frontend">
<resource name="RAM" quantum="64M"/>
<config core="nxengine_libretro.lib.so">
<controller port="0" device="1">
<map from="KEY_LEFT" to="LEFT"/>
<map from="KEY_RIGHT" to="RIGHT"/>
<map from="KEY_UP" to="UP"/>
<map from="KEY_DOWN" to="DOWN"/>
<map from="KEY_Z" to="B"/>
<map from="KEY_X" to="A"/>
<map from="KEY_ENTER" to="START"/>
<map from="KEY_RIGHTSHIFT" to="SELECT"/>
</controller>
<libc stdout="/dev/log" stderr="/dev/log"/>
<vfs>
<dir name="dev"> <log/> </dir>
@@ -152,7 +139,7 @@ append config {
<service name="Framebuffer">
<child name="fb_upscale"/> </service>
<service name="Input">
<child name="input_remap"/> </service>
<child name="input_drv"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
@@ -174,7 +161,6 @@ append boot_modules {
core init ld.lib.so
} [audio_drv_binary] {
fb_upscale
input_remap
libc.lib.so
libm.lib.so
nxengine_libretro.lib.so

View File

@@ -1,126 +0,0 @@
#
# \brief Chroot test
# \author Emery Hemingway
# \date 2016-12-03
#
#
# Build
#
build { core init server/vfs server/chroot test/libc }
create_boot_directory
#
# Generate config
#
set config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="vfs">
<resource name="RAM" quantum="12M"/>
<provides> <service name="File_system"/> </provides>
<config>
<vfs>
<dir name="test-libc-1">
<log label="chroot-1"/>
</dir>
<dir name="test-libc-2">
<log label="chroot-2"/>
</dir>
<dir name="test-libc-3">
<log label="chroot-3"/>
</dir>
</vfs>
<policy label_prefix="chroot" root="/" writeable="yes"/>
</config>
</start>
<start name="chroot">
<resource name="RAM" quantum="2M"/>
<provides> <service name="File_system"/> </provides>
<route>
<any-service>
<child name="vfs"/> <parent/>
</any-service>
</route>
</start>
<start name="test-libc-1">
<binary name="test-libc"/>
<resource name="RAM" quantum="4M"/>
<config>
<libc stdout="/log"/>
<vfs> <fs/> </vfs>
</config>
<route>
<any-service>
<child name="chroot"/> <parent/>
</any-service>
</route>
</start>
<start name="test-libc-2">
<binary name="test-libc"/>
<resource name="RAM" quantum="4M"/>
<config>
<libc stdout="/log"/>
<vfs> <fs/> </vfs>
</config>
<route>
<any-service>
<child name="chroot"/> <parent/>
</any-service>
</route>
</start>
<start name="test-libc-3">
<binary name="test-libc"/>
<resource name="RAM" quantum="4M"/>
<config>
<libc stdout="/log"/>
<vfs> <fs/> </vfs>
</config>
<route>
<any-service>
<child name="chroot"/> <parent/>
</any-service>
</route>
</start>
</config>
}
install_config $config
#
# Boot modules
#
build_boot_image {
core init vfs chroot
ld.lib.so libc.lib.so libm.lib.so posix.lib.so
test-libc
}
#
# Execute test case
#
append qemu_args " -nographic "
run_genode_until {child "test-libc-3" exited with exit value 0} 60
# vi: set ft=tcl :

View File

@@ -17,7 +17,6 @@ set build_components {
drivers/audio
libretro/meteor
server/fb_upscale
server/input_remap
}
source ${genode_dir}/repos/base/run/platform_drv.inc
@@ -165,7 +164,6 @@ if {![file exists bin/game.gba]} {
# generic modules
append boot_modules {
fb_upscale
input_remap
libc.lib.so
libm.lib.so
meteor_libretro.lib.so

View File

@@ -114,8 +114,8 @@ The 'from' attribute on a 'map' node indicates a Genode input code and the
determined externally using the 'test-input' component and Libretro input
codes may be found in 'input' report described later. Mappings may only
be made within the base device. Mapping keyboards to joypads is supported
but remapping keyboard keys is not. The 'input_merger' or 'input_remap'
component may be used to externally remap the Libretro keyboard type.
but remapping keyboard keys is not. The 'input_merger' component may be
used to externally remap the Libretro keyboard type.
Variables

View File

@@ -1,33 +0,0 @@
This component intercepts File_system requests and changes
the root directory of the request using the session label.
In this example if cli_monitor had a child named "X", every
file system session from "X" would be rooted to the directory
"/cli_monitor/X" at "fs_server".
! <start name="fs_server">
! <provides> <service name="File_system"/> </provides>
! ...
! </start>
!
! <start name="chroot">
! <provides> <service name="File_system"/> </provides>
! <config>
! <policy label_prefix="cli_monitor ->" merge="yes"/>
! </config>
! <route>
! <any-service>
! <child name="fs_server"/> <parent/>
! </any-service>
! </route>
! ...
! </start>
!
! <start name="cli_monitior">
! <route>
! <any-service>
! <child name="chroot"/> <parent/>
! </any-service>
! </route>
! ...
! </start>

View File

@@ -1,274 +0,0 @@
/*
* \brief Change session root server
* \author Emery Hemingway
* \date 2016-03-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 <file_system/util.h>
#include <file_system_session/connection.h>
#include <os/path.h>
#include <os/session_policy.h>
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
#include <parent/parent.h>
#include <base/service.h>
#include <base/allocator_avl.h>
#include <base/heap.h>
namespace Chroot {
using namespace Genode;
struct Main;
template <unsigned MAX_LEN>
static void path_from_label(Path<MAX_LEN> &path, char const *label)
{
char tmp[MAX_LEN];
size_t len = strlen(label);
size_t i = 0;
for (size_t j = 1; j < len; ++j) {
if (!strcmp(" -> ", label+j, 4)) {
path.append("/");
strncpy(tmp, label+i, (j-i)+1);
/* rewrite any directory seperators */
for (size_t k = 0; k < MAX_LEN; ++k)
if (tmp[k] == '/')
tmp[k] = '_';
path.append(tmp);
j += 4;
i = j;
}
}
path.append("/");
strncpy(tmp, label+i, MAX_LEN);
/* rewrite any directory seperators */
for (size_t k = 0; k < MAX_LEN; ++k)
if (tmp[k] == '/')
tmp[k] = '_';
path.append(tmp);
}
}
struct Chroot::Main
{
enum { PATH_MAX_LEN = 128 };
typedef Genode::Path<PATH_MAX_LEN> Path;
struct Session : Parent::Server
{
Parent::Client parent_client;
Id_space<Parent::Client>::Element client_id;
Id_space<Parent::Server>::Element server_id;
Session(Id_space<Parent::Client> &client_space,
Id_space<Parent::Server> &server_space,
Parent::Server::Id server_id)
:
client_id(parent_client, client_space),
server_id(*this, server_space, server_id) { }
};
Genode::Env &env;
Id_space<Parent::Server> server_id_space;
Heap heap { env.ram(), env.rm() };
Allocator_avl fs_tx_block_alloc { &heap };
File_system::Connection fs { fs_tx_block_alloc, 1 };
Attached_rom_dataspace session_requests { env, "session_requests" };
Attached_rom_dataspace config_rom { env, "config" };
void handle_session_request(Xml_node request);
void handle_session_requests()
{
if (config_sig_rec.pending()) {
do { config_sig_rec.pending_signal(); }
while (config_sig_rec.pending());
config_rom.update();
}
session_requests.update();
Xml_node const requests = session_requests.xml();
requests.for_each_sub_node([&] (Xml_node request) {
handle_session_request(request);
});
}
Signal_handler<Main> session_request_handler {
env.ep(), *this, &Main::handle_session_requests };
Signal_context config_sig_ctx;
Signal_receiver config_sig_rec;
/**
* Constructor
*/
Main(Genode::Env &env) : env(env)
{
config_rom.sigh(config_sig_rec.manage(&config_sig_ctx));
session_requests.sigh(session_request_handler);
/* handle requests that have queued before or during construction */
handle_session_requests();
}
~Main() {
config_sig_rec.dissolve(&config_sig_ctx); }
Session_capability request_session(Parent::Client::Id const &id,
Session_state::Args const &args)
{
char tmp[PATH_MAX_LEN];
Path root_path;
Session_label label = label_from_args(args.string());
char const *label_str = label.string();
/* if policy specifies a merge, use a truncated label */
try {
Session_policy policy(label, config_rom.xml());
if (policy.has_attribute("label_prefix")
&& policy.attribute_value("merge", false))
{
/* merge at the next element */
size_t offset = policy.attribute("label_prefix").value_size();
for (size_t i = offset; i < label.length()-4; ++i) {
if (strcmp(label_str+i, " -> ", 4))
continue;
strncpy(tmp, label_str, min(sizeof(tmp), i+1));
label_str = tmp;
break;
}
}
} catch (Session_policy::No_policy_defined) { }
/* create a new path from the label */
path_from_label(root_path, label_str);
/* extract and append the orginal root */
Arg_string::find_arg(args.string(), "root").string(
tmp, sizeof(tmp), "/");
root_path.append_element(tmp);
root_path.remove_trailing('/');
char const *new_root = root_path.base();
using namespace File_system;
/* create the new root directory if it is missing */
try { fs.close(ensure_dir(fs, new_root)); }
catch (Node_already_exists) { }
catch (Permission_denied) {
Genode::error(new_root,": permission denied"); throw; }
catch (Name_too_long) {
Genode::error(new_root,": new root too long"); throw; }
catch (No_space) {
Genode::error(new_root,": no space"); throw; }
catch (...) {
Genode::error(new_root,": unknown error"); throw; }
/* rewrite the root session argument */
enum { ARGS_MAX_LEN = 256 };
char new_args[ARGS_MAX_LEN];
strncpy(new_args, args.string(), ARGS_MAX_LEN);
/* sacrifice the label to make space for the root argument */
Arg_string::remove_arg(new_args, "label");
Arg_string::set_arg_string(new_args, ARGS_MAX_LEN, "root", new_root);
Affinity affinity;
return env.session("File_system", id, new_args, affinity);
}
};
void Chroot::Main::handle_session_request(Xml_node request)
{
if (!request.has_attribute("id"))
return;
Parent::Server::Id const server_id { request.attribute_value("id", 0UL) };
if (request.has_type("create")) {
if (!request.has_sub_node("args"))
return;
typedef Session_state::Args Args;
Args const args = request.sub_node("args").decoded_content<Args>();
Session *session = nullptr;
try {
session = new (heap)
Session(env.id_space(), server_id_space, server_id);
Session_capability cap = request_session(session->client_id.id(), args);
env.parent().deliver_session_cap(server_id, cap);
}
catch (...) {
if (session)
destroy(heap, session);
env.parent().session_response(server_id, Parent::SERVICE_DENIED);
}
}
if (request.has_type("upgrade")) {
server_id_space.apply<Session>(server_id, [&] (Session &session) {
size_t ram_quota = request.attribute_value("ram_quota", 0UL);
String<64> args("ram_quota=", ram_quota);
env.upgrade(session.client_id.id(), args.string());
env.parent().session_response(server_id, Parent::SESSION_OK);
});
}
if (request.has_type("close")) {
server_id_space.apply<Session>(server_id, [&] (Session &session) {
env.close(session.client_id.id());
destroy(heap, &session);
env.parent().session_response(server_id, Parent::SESSION_CLOSED);
});
}
}
/***************
** Component **
***************/
Genode::size_t Component::stack_size() {
return 2*1024*sizeof(Genode::addr_t); }
void Component::construct(Genode::Env &env)
{
static Chroot::Main inst(env);
env.parent().announce("File_system");
}

View File

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

View File

@@ -1,14 +0,0 @@
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

@@ -1,134 +0,0 @@
/*
* \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::Connection parent_input { env };
/*
* Input session provided to our client
*/
Input::Session_component input_session_component { env, env.ram() };
/*
* Attach root interface to the entry point
*/
Genode::Static_root<Input::Session> input_root
{ env.ep().manage(input_session_component) };
void event_flush()
{
parent_input.for_each_event([&] (Event const &e) {
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 '", Cstring(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));
}
};
/***************
** 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

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