/*
* \brief Connection to Platform service
* \author Stefan Kalkowski
* \date 2020-05-13
*/
/*
* Copyright (C) 2020 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 _INCLUDE__PLATFORM_SESSION__CONNECTION_H_
#define _INCLUDE__PLATFORM_SESSION__CONNECTION_H_
#include
#include
#include
#include
#include
#include
#include
namespace Platform {
struct Device;
struct Dma_buffer;
struct Connection;
}
class Platform::Connection : public Genode::Connection,
public Client
{
private:
/* 'Device' and 'Dma_buffer' access the '_env' member */
friend class Device;
friend class Dma_buffer;
Env &_env;
Rom_session_client _rom {devices_rom()};
Constructible _ds {};
Constructible> _handler {};
void _try_attach()
{
_ds.destruct();
try { _ds.construct(_env.rm(), _rom.dataspace()); }
catch (Attached_dataspace::Invalid_dataspace) {
warning("Invalid devices rom dataspace returned!");}
}
void _handle_io() {}
template
Capability _wait_for_device(FN const & fn)
{
for (;;) {
/* repeatedly check for availability of device */
Capability cap = fn();
if (cap.valid()) {
if (_handler.constructed()) {
sigh(Signal_context_capability());
_handler.destruct();
}
return cap;
}
if (!_handler.constructed()) {
_handler.construct(_env.ep(), *this,
&Connection::_handle_io);
sigh(*_handler);
}
_env.ep().wait_and_dispatch_one_io_signal();
}
}
public:
Connection(Env &env)
:
Genode::Connection(env, session(env.parent(),
"ram_quota=%u, cap_quota=%u",
RAM_QUOTA, CAP_QUOTA)),
Client(cap()),
_env(env)
{
_try_attach();
}
void update()
{
if (_ds.constructed() && _rom.update() == true)
return;
_try_attach();
}
void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); }
Capability acquire_device(Device_name const &name) override
{
return _wait_for_device([&] () {
return retry_with_upgrade(Ram_quota{6*1024}, Cap_quota{6}, [&] () {
return Client::acquire_device(name); });
});
}
Capability acquire_device()
{
return _wait_for_device([&] () {
return retry_with_upgrade(Ram_quota{6*1024}, Cap_quota{6}, [&] () {
return Client::acquire_single_device(); });
});
}
Ram_dataspace_capability alloc_dma_buffer(size_t size, Cache cache) override
{
return retry_with_upgrade(Ram_quota{size}, Cap_quota{2}, [&] () {
return Client::alloc_dma_buffer(size, cache); });
}
template
void with_xml(FN const & fn)
{
try {
if (_ds.constructed() && _ds->local_addr()) {
Xml_node xml(_ds->local_addr(), _ds->size());
fn(xml);
}
} catch (Xml_node::Invalid_syntax) {
warning("Devices rom has invalid XML syntax"); }
}
Capability device_by_type(char const * type)
{
return _wait_for_device([&] () {
using String = Genode::String<64>;
Capability cap;
with_xml([&] (Xml_node & xml) {
xml.for_each_sub_node("device", [&] (Xml_node node) {
/* already found a device? */
if (cap.valid())
return;
if (node.attribute_value("type", String()) != type)
return;
Device_name name = node.attribute_value("name", Device_name());
cap = acquire_device(name);
});
});
return cap;
});
}
};
#endif /* _INCLUDE__PLATFORM_SESSION__CONNECTION_H_ */