This patch reduces the number of exception types by facilitating globally defined exceptions for common usage patterns shared by most services. In particular, RPC functions that demand a session-resource upgrade not longer reflect this condition via a session-specific exception but via the 'Out_of_ram' or 'Out_of_caps' types. Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable', 'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args', 'Service::Unavailable', and 'Local_service::Factory::Denied' types have been replaced by the single 'Service_denied' exception type defined in 'session/session.h'. This consolidation eases the error handling (there are fewer exceptions to handle), alleviates the need to convert exceptions along the session-creation call chain, and avoids possible aliasing problems (catching the wrong type with the same name but living in a different scope).
143 lines
3.0 KiB
C++
143 lines
3.0 KiB
C++
/*
|
|
* \brief Input event merger
|
|
* \author Christian Prochaska
|
|
* \date 2014-09-29
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2014-2017 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
/* Genode includes */
|
|
#include <input/component.h>
|
|
#include <input_session/connection.h>
|
|
#include <os/static_root.h>
|
|
#include <base/component.h>
|
|
#include <base/attached_rom_dataspace.h>
|
|
#include <base/attached_dataspace.h>
|
|
#include <base/heap.h>
|
|
#include <base/session_label.h>
|
|
#include <util/list.h>
|
|
|
|
|
|
namespace Input_merger
|
|
{
|
|
using namespace Genode;
|
|
|
|
struct Input_source;
|
|
struct Main;
|
|
|
|
typedef List<Input_source> Input_sources;
|
|
typedef String<Session_label::capacity()> Label;
|
|
}
|
|
|
|
|
|
struct Input_merger::Input_source : Input_sources::Element
|
|
{
|
|
Input::Connection conn;
|
|
Input::Session_component &sink;
|
|
|
|
Genode::Signal_handler<Input_source> event_handler;
|
|
|
|
void handle_events()
|
|
{
|
|
conn.for_each_event([&] (Input::Event const &e) { sink.submit(e); });
|
|
}
|
|
|
|
Input_source(Genode::Env &env, Label const &label, Input::Session_component &sink)
|
|
:
|
|
conn(env, label.string()), sink(sink),
|
|
event_handler(env.ep(), *this, &Input_source::handle_events)
|
|
{
|
|
conn.sigh(event_handler);
|
|
}
|
|
};
|
|
|
|
|
|
/******************
|
|
** Main program **
|
|
******************/
|
|
|
|
struct Input_merger::Main
|
|
{
|
|
Env &env;
|
|
|
|
Attached_rom_dataspace config_rom { env, "config" };
|
|
|
|
Heap heap { env.ram(), env.rm() };
|
|
|
|
Input_sources input_source_list;
|
|
|
|
/*
|
|
* Input session provided to our client
|
|
*/
|
|
Input::Session_component input_session_component { env, env.ram() };
|
|
|
|
/*
|
|
* Attach root interface to the entry point
|
|
*/
|
|
Static_root<Input::Session> input_root { env.ep().manage(input_session_component) };
|
|
|
|
void handle_config_update()
|
|
{
|
|
config_rom.update();
|
|
|
|
while (Input_source *input_source = input_source_list.first()) {
|
|
input_source_list.remove(input_source);
|
|
destroy(heap, input_source);
|
|
}
|
|
|
|
config_rom.xml().for_each_sub_node("input", [&] (Xml_node input_node) {
|
|
try {
|
|
Label label;
|
|
input_node.attribute("label").value(&label);
|
|
|
|
try {
|
|
Input_source *input_source = new (heap)
|
|
Input_source(env, label.string(), input_session_component);
|
|
|
|
input_source_list.insert(input_source);
|
|
|
|
} catch (Genode::Service_denied) {
|
|
error("parent denied input source '", label, "'");
|
|
}
|
|
} catch (Xml_node::Nonexistent_attribute) {
|
|
error("ignoring invalid input node '", input_node);
|
|
}
|
|
});
|
|
}
|
|
|
|
Signal_handler<Main> config_update_handler
|
|
{ env.ep(), *this, &Main::handle_config_update };
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
Main(Genode::Env &env) : env(env)
|
|
{
|
|
input_session_component.event_queue().enabled(true);
|
|
|
|
/*
|
|
* Apply initial configuration
|
|
*/
|
|
handle_config_update();
|
|
|
|
/*
|
|
* Register signal handler
|
|
*/
|
|
config_rom.sigh(config_update_handler);
|
|
|
|
/*
|
|
* Announce service
|
|
*/
|
|
env.parent().announce(env.ep().manage(input_root));
|
|
}
|
|
|
|
};
|
|
|
|
|
|
void Component::construct(Genode::Env &env) { static Input_merger::Main inst(env); }
|