rtc_drv: implement set signal handling

Issue #3450
This commit is contained in:
Josef Söntgen 2019-07-15 15:06:23 +02:00 committed by Christian Helmuth
parent ea2b330158
commit a7fe4a502d
2 changed files with 101 additions and 56 deletions

View File

@ -15,6 +15,7 @@
#include <base/attached_rom_dataspace.h>
#include <base/component.h>
#include <base/heap.h>
#include <base/registry.h>
#include <root/component.h>
#include "rtc.h"
@ -35,6 +36,10 @@ struct Rtc::Session_component : public Genode::Rpc_object<Session>
Signal_context_capability _set_sig_cap { };
Session_component(Env &env) : _env(env) { }
virtual ~Session_component() { }
void set_sigh(Signal_context_capability sigh) override
{
_set_sig_cap = sigh;
@ -47,7 +52,12 @@ struct Rtc::Session_component : public Genode::Rpc_object<Session>
return ret;
}
Session_component(Env &env) : _env(env) { }
void notify_client()
{
if (_set_sig_cap.valid()) {
Signal_transmitter(_set_sig_cap).submit();
}
}
};
@ -57,11 +67,14 @@ class Rtc::Root : public Genode::Root_component<Session_component>
Env &_env;
Registry<Registered<Session_component> > _sessions { };
protected:
Session_component *_create_session(const char *) override
{
return new (md_alloc()) Session_component(_env);
return new (md_alloc())
Registered<Session_component>(_sessions, _env);
}
public:
@ -74,6 +87,13 @@ class Rtc::Root : public Genode::Root_component<Session_component>
/* trigger initial RTC read */
Rtc::get_time(_env);
}
void notify_clients()
{
_sessions.for_each([&] (Session_component &session) {
session.notify_client();
});
}
};
@ -163,6 +183,8 @@ void Rtc::Main::_handle_update()
ts.year = node.attribute_value("year", 2019u);
Rtc::set_time(env, ts);
root.notify_clients();
}

View File

@ -25,20 +25,88 @@ using namespace Genode;
struct Main
{
Main(Genode::Env &env)
{
int exit_code = 0;
Env &_env;
Rtc::Connection rtc1 { _env };
Rtc::Connection rtc2 { _env, "with_label" };
Signal_handler<Main> _set_sigh {
_env.ep(), *this, &Main::_handle_set_signal };
Rtc::Timestamp _ts { };
void _handle_set_signal()
{
Rtc::Timestamp got = rtc1.current_time();
Genode::log("Set RTC to: '", _ts, "' got: '", got,
"' (ignoring seconds)");
int exit_code = 0;
if ( _ts.year != got.year
|| _ts.month != got.month
|| _ts.day != got.day
|| _ts.hour != got.hour
|| _ts.minute != got.minute) {
error("updating RTC failed");
exit_code = 1;
}
_parent_exit(exit_code);
}
Constructible<Reporter> _reporter { };
void _test_update()
{
try {
_reporter.construct(_env, "set_rtc");
_reporter->enabled(true);
rtc1.set_sigh(_set_sigh);
Rtc::Timestamp ts = rtc1.current_time();
ts.year = 2069;
ts.month = 12;
ts.day = 31;
ts.hour = 23;
ts.minute = 55;
ts.second = 0;
_ts = ts;
Reporter::Xml_generator xml(*_reporter, [&] () {
xml.attribute("year", ts.year);
xml.attribute("month", ts.month);
xml.attribute("day", ts.day);
xml.attribute("hour", ts.hour);
xml.attribute("minute", ts.minute);
xml.attribute("second", ts.second);
});
} catch (...) {
error("could not test RTC update");
_parent_exit(1);
}
}
void _parent_exit(int exit_code)
{
Genode::log("--- RTC test finished ---");
_env.parent().exit(exit_code);
}
Main(Genode::Env &env) : _env(env)
{
Genode::log("--- RTC test started ---");
/* open sessions */
Rtc::Connection rtc[] = { { env }, { env, "with_label" } };
Timer::Connection timer(env);
for (unsigned i = 0; i < 4; ++i) {
Rtc::Timestamp now[] = { rtc[0].current_time(), rtc[1].current_time() };
Rtc::Timestamp now[] = { rtc1.current_time(), rtc2.current_time() };
for (unsigned j = 0; j < sizeof(rtc)/sizeof(*rtc); ++j)
for (unsigned j = 0; j < sizeof(now)/sizeof(now[0]); ++j)
log("RTC[", j, "]: ", now[j]);
timer.msleep(1000);
@ -48,56 +116,11 @@ struct Main
Attached_rom_dataspace config_rom { env, "config" };
bool const test_update = config_rom.xml().attribute_value("set_rtc", false);
if (test_update) {
try {
Reporter reporter { env, "set_rtc" };
reporter.enabled(true);
Rtc::Timestamp ts = rtc[0].current_time();
ts.year = 2069;
ts.month = 12;
ts.day = 31;
ts.hour = 23;
ts.minute = 55;
ts.second = 0;
Reporter::Xml_generator xml(reporter, [&] () {
xml.attribute("year", ts.year);
xml.attribute("month", ts.month);
xml.attribute("day", ts.day);
xml.attribute("hour", ts.hour);
xml.attribute("minute", ts.minute);
xml.attribute("second", ts.second);
});
/*
* Wait a reasonable amount of time for the RTC update
* to go through.
*/
timer.msleep(3000);
Rtc::Timestamp got = rtc[0].current_time();
Genode::log("Set RTC to: '", ts, "' got: '", got,
"' (ignoring seconds)");
if ( ts.year != got.year
|| ts.month != got.month
|| ts.day != got.day
|| ts.hour != got.hour
|| ts.minute != got.minute) {
error("updating RTC failed");
exit_code = 2;
}
} catch (...) {
error("could not test RTC update");
exit_code = 1;
}
_test_update();
return;
}
Genode::log("--- RTC test finished ---");
env.parent().exit(exit_code);
_parent_exit(0);
}
};