diff --git a/repos/os/recipes/pkg/black_hole/runtime b/repos/os/recipes/pkg/black_hole/runtime
index dc95b68269..132b1705a2 100644
--- a/repos/os/recipes/pkg/black_hole/runtime
+++ b/repos/os/recipes/pkg/black_hole/runtime
@@ -11,6 +11,8 @@
+
+
@@ -23,6 +25,8 @@
+
+
diff --git a/repos/os/recipes/src/black_hole/used_apis b/repos/os/recipes/src/black_hole/used_apis
index 40f00bdfe6..19fddda69f 100644
--- a/repos/os/recipes/src/black_hole/used_apis
+++ b/repos/os/recipes/src/black_hole/used_apis
@@ -8,4 +8,6 @@ report_session
uplink_session
gpu_session
usb_session
+play_session
+record_session
os
diff --git a/repos/os/src/server/black_hole/README b/repos/os/src/server/black_hole/README
index ccb6829ce3..343495a395 100644
--- a/repos/os/src/server/black_hole/README
+++ b/repos/os/src/server/black_hole/README
@@ -13,6 +13,8 @@ in the configuration of the component.
* ROM
* Gpu
* Usb
+* Play
+* Record
@@ -24,6 +26,8 @@ in the configuration of the component.
+
+
Black hole optionally requests the following sessions as client.
diff --git a/repos/os/src/server/black_hole/config.xsd b/repos/os/src/server/black_hole/config.xsd
index 9284a4a5fa..dee3f24a34 100644
--- a/repos/os/src/server/black_hole/config.xsd
+++ b/repos/os/src/server/black_hole/config.xsd
@@ -4,6 +4,8 @@
+
+
diff --git a/repos/os/src/server/black_hole/main.cc b/repos/os/src/server/black_hole/main.cc
index da03c62182..c19793218f 100644
--- a/repos/os/src/server/black_hole/main.cc
+++ b/repos/os/src/server/black_hole/main.cc
@@ -32,6 +32,8 @@
#include "rom.h"
#include "gpu.h"
#include "usb.h"
+#include "play.h"
+#include "record.h"
/***************
@@ -57,6 +59,8 @@ struct Black_hole::Main
Genode::Constructible gpu_root { };
Genode::Constructible usb_root { };
Genode::Constructible uplink_client { };
+ Genode::Constructible play_root { };
+ Genode::Constructible record_root { };
Main(Genode::Env &env) : env(env)
{
@@ -102,6 +106,14 @@ struct Black_hole::Main
usb_root.construct(env, heap);
env.parent().announce(env.ep().manage(*usb_root));
}
+ if (_config_rom.xml().has_sub_node("play")) {
+ play_root.construct(env, heap);
+ env.parent().announce(env.ep().manage(*play_root));
+ }
+ if (_config_rom.xml().has_sub_node("record")) {
+ record_root.construct(env, heap);
+ env.parent().announce(env.ep().manage(*record_root));
+ }
if (_config_rom.xml().has_sub_node("uplink_client")) {
uplink_client.construct(env, heap);
diff --git a/repos/os/src/server/black_hole/play.h b/repos/os/src/server/black_hole/play.h
new file mode 100644
index 0000000000..91529d3fe6
--- /dev/null
+++ b/repos/os/src/server/black_hole/play.h
@@ -0,0 +1,95 @@
+/*
+ * \brief Play service of the black hole component
+ * \author Josef Soentgen
+ * \date 2024-04-02
+ */
+
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#ifndef _PLAY_SESSION_H_
+#define _PLAY_SESSION_H_
+
+#include
+#include
+#include
+
+namespace Black_hole {
+
+ using namespace Genode;
+
+ class Play_session;
+ class Play_root;
+}
+
+
+class Black_hole::Play_session : public Session_object
+{
+ private:
+
+ Env &_env;
+ Attached_ram_dataspace _ram_ds;
+
+ public:
+
+ Play_session(Env &env,
+ Resources const &resources,
+ Label const &label,
+ Diag const &diag)
+ :
+ Session_object(env.ep(), resources, label, diag),
+ _env(env),
+ _ram_ds(_env.ram(), _env.rm(), Play::Session::DATASPACE_SIZE)
+ { }
+
+ /****************************
+ ** Play session interface **
+ ****************************/
+
+ Dataspace_capability dataspace() { return _ram_ds.cap(); }
+
+ Play::Time_window schedule(Play::Time_window,
+ Play::Duration,
+ Play::Num_samples)
+ {
+ return { };
+ }
+
+ void stop() { }
+};
+
+
+class Black_hole::Play_root : public Root_component
+{
+ private:
+
+ Env &_env;
+
+ protected:
+
+ Play_session *_create_session(const char *args) override
+ {
+ if (session_resources_from_args(args).ram_quota.value < Play::Session::DATASPACE_SIZE)
+ throw Insufficient_ram_quota();
+
+ return new (md_alloc())
+ Play_session(_env,
+ session_resources_from_args(args),
+ session_label_from_args(args),
+ session_diag_from_args(args));
+ }
+
+ public:
+
+ Play_root(Env &env, Allocator &md_alloc)
+ :
+ Root_component(&env.ep().rpc_ep(), &md_alloc),
+ _env(env)
+ { }
+};
+
+#endif /* _PLAY_SESSION_H_ */
diff --git a/repos/os/src/server/black_hole/record.h b/repos/os/src/server/black_hole/record.h
new file mode 100644
index 0000000000..589efc944a
--- /dev/null
+++ b/repos/os/src/server/black_hole/record.h
@@ -0,0 +1,109 @@
+/*
+ * \brief Record service of the black hole component
+ * \author Josef Soentgen
+ * \date 2024-04-02
+ */
+
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#ifndef _RECORD_SESSION_H_
+#define _RECORD_SESSION_H_
+
+#include
+#include
+#include
+
+namespace Black_hole {
+
+ using namespace Genode;
+
+ class Record_session;
+ class Record_root;
+}
+
+
+class Black_hole::Record_session : public Session_object
+{
+ private:
+
+ Env &_env;
+ Attached_ram_dataspace _ram_ds;
+ Signal_context_capability _wakeup_sigh;
+
+ public:
+
+ Record_session(Env &env,
+ Resources const &resources,
+ Label const &label,
+ Diag const &diag)
+ :
+ Session_object(env.ep(), resources, label, diag),
+ _env(env),
+ _ram_ds(_env.ram(), _env.rm(), Record::Session::DATASPACE_SIZE),
+ _wakeup_sigh()
+ { }
+
+ void wakeup()
+ {
+ if (_wakeup_sigh.valid())
+ Signal_transmitter(_wakeup_sigh).submit();
+ }
+
+ /****************************
+ ** Record session interface **
+ ****************************/
+
+ Dataspace_capability dataspace() { return _ram_ds.cap(); }
+
+ void wakeup_sigh(Signal_context_capability sigh)
+ {
+ _wakeup_sigh = sigh;
+ wakeup(); /* initial wakeup */
+ }
+
+ Record::Session::Record_result record(Record::Num_samples)
+ {
+ return Record::Time_window { 0, 0 };
+ }
+
+ void record_at(Record::Time_window,
+ Record::Num_samples)
+ { }
+};
+
+
+class Black_hole::Record_root : public Root_component
+{
+ private:
+
+ Env &_env;
+
+ protected:
+
+ Record_session *_create_session(const char *args) override
+ {
+ if (session_resources_from_args(args).ram_quota.value < Record::Session::DATASPACE_SIZE)
+ throw Insufficient_ram_quota();
+
+ return new (md_alloc())
+ Record_session(_env,
+ session_resources_from_args(args),
+ session_label_from_args(args),
+ session_diag_from_args(args));
+ }
+
+ public:
+
+ Record_root(Env &env, Allocator &md_alloc)
+ :
+ Root_component(&env.ep().rpc_ep(), &md_alloc),
+ _env(env)
+ { }
+};
+
+#endif /* _RECORD_SESSION_H_ */