mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-02 16:52:52 +00:00
gems: remove d3m
D3m is superseded by now. Altough there is no direct replacement combining various other components is equal to its functionality. Issue #1456.
This commit is contained in:
parent
2c39c75e1c
commit
7a8c088fc6
@ -1,149 +0,0 @@
|
|||||||
#
|
|
||||||
# \brief Boot test for the demo device driver manager
|
|
||||||
# \author Norman Feske
|
|
||||||
# \date 2012-01-17
|
|
||||||
#
|
|
||||||
# This test exercises the auto-probing of the boot medium performed by d3m.
|
|
||||||
# D3m support booting from both CD-ROM and USB storage. Both options are
|
|
||||||
# tested via different qemu arguments.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Sanity checks
|
|
||||||
#
|
|
||||||
# The test does only work for platforms that use qemu to boot. Because the test
|
|
||||||
# uses x86-specific drivers, it won't execute on other architectures.
|
|
||||||
#
|
|
||||||
if {[have_spec linux]} { puts "Does not run on Linux"; exit 0 }
|
|
||||||
if {![have_spec x86_32]} { puts "Runs only on x86_32"; exit 0 }
|
|
||||||
|
|
||||||
#
|
|
||||||
# Build
|
|
||||||
#
|
|
||||||
build {
|
|
||||||
core
|
|
||||||
init
|
|
||||||
drivers/timer
|
|
||||||
drivers/pci
|
|
||||||
drivers/framebuffer/vesa
|
|
||||||
drivers/input/ps2
|
|
||||||
drivers/atapi
|
|
||||||
drivers/nic
|
|
||||||
drivers/usb
|
|
||||||
server/d3m
|
|
||||||
server/iso9660
|
|
||||||
}
|
|
||||||
|
|
||||||
create_boot_directory
|
|
||||||
|
|
||||||
#
|
|
||||||
# Config
|
|
||||||
#
|
|
||||||
set config {
|
|
||||||
<config verbose="yes">
|
|
||||||
<parent-provides>
|
|
||||||
<service name="ROM"/>
|
|
||||||
<service name="RAM"/>
|
|
||||||
<service name="IRQ"/>
|
|
||||||
<service name="IO_MEM"/>
|
|
||||||
<service name="IO_PORT"/>
|
|
||||||
<service name="CAP"/>
|
|
||||||
<service name="PD"/>
|
|
||||||
<service name="RM"/>
|
|
||||||
<service name="CPU"/>
|
|
||||||
<service name="LOG"/>
|
|
||||||
<service name="SIGNAL"/>
|
|
||||||
</parent-provides>
|
|
||||||
<default-route>
|
|
||||||
<any-service> <any-child/> <parent/> </any-service>
|
|
||||||
</default-route>
|
|
||||||
<start name="pci_drv">
|
|
||||||
<resource name="RAM" quantum="1M"/>
|
|
||||||
<provides><service name="PCI"/></provides>
|
|
||||||
</start>
|
|
||||||
<start name="timer">
|
|
||||||
<resource name="RAM" quantum="1M"/>
|
|
||||||
<provides><service name="Timer"/></provides>
|
|
||||||
</start>
|
|
||||||
<start name="d3m">
|
|
||||||
<resource name="RAM" quantum="26M"/>
|
|
||||||
<provides>
|
|
||||||
<service name="Input"/>
|
|
||||||
<service name="Nic"/>
|
|
||||||
<service name="Block"/>
|
|
||||||
</provides>
|
|
||||||
<route>
|
|
||||||
<service name="ROM"> <parent/> </service>
|
|
||||||
<any-service> <any-child/> <parent/> </any-service>
|
|
||||||
</route>
|
|
||||||
</start>
|
|
||||||
<start name="iso9660">
|
|
||||||
<resource name="RAM" quantum="8M"/>
|
|
||||||
<provides><service name="ROM"/></provides>
|
|
||||||
</start>
|
|
||||||
</config>
|
|
||||||
}
|
|
||||||
|
|
||||||
install_config $config
|
|
||||||
|
|
||||||
# create magic tag file on iso image, which marks the boot medium
|
|
||||||
exec touch [run_dir]/libc.lib.so
|
|
||||||
|
|
||||||
#
|
|
||||||
# Boot modules
|
|
||||||
#
|
|
||||||
build_boot_image {
|
|
||||||
core init
|
|
||||||
pci_drv fb_drv ps2_drv atapi_drv timer nic_drv usb_drv
|
|
||||||
d3m iso9660 }
|
|
||||||
|
|
||||||
#
|
|
||||||
# Customized variant of spawn_qemu function, which lets us define all qemu
|
|
||||||
# arguments via the 'qemu_args' variable.
|
|
||||||
#
|
|
||||||
proc spawn_qemu { wait_for_re timeout_value } {
|
|
||||||
global output
|
|
||||||
global qemu_args
|
|
||||||
global qemu
|
|
||||||
global spawn_id
|
|
||||||
set qemu "qemu-system-i386"
|
|
||||||
|
|
||||||
set timeout $timeout_value
|
|
||||||
set pid [eval "spawn $qemu $qemu_args"]
|
|
||||||
if {$wait_for_re == "forever"} { interact $pid }
|
|
||||||
expect {
|
|
||||||
-re $wait_for_re { }
|
|
||||||
timeout { puts stderr "Error: Test execution timed out"; exit -2 }
|
|
||||||
}
|
|
||||||
set output $expect_out(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Inherit qemu arguments specified at the build configuration
|
|
||||||
#
|
|
||||||
set common_qemu_args "$qemu_args -serial mon:stdio -nographic -m 512 "
|
|
||||||
|
|
||||||
#
|
|
||||||
# First, try to use the ISO image as CD-ROM. We expect the ATAPI driver to
|
|
||||||
# detect the boot image.
|
|
||||||
#
|
|
||||||
set qemu_args "$common_qemu_args -cdrom [run_dir].iso"
|
|
||||||
run_genode_until {.*"iso9660" announces service "ROM".*\n} 30
|
|
||||||
close $spawn_id
|
|
||||||
|
|
||||||
puts "\nBooting from CD-ROM succeeded\n"
|
|
||||||
|
|
||||||
#
|
|
||||||
# Second, try to use the ISO image as USB stick. We expect the USB driver to
|
|
||||||
# detect the boot image.
|
|
||||||
#
|
|
||||||
# The timeout is a bit larger because using isolinux takes a while.
|
|
||||||
#
|
|
||||||
set qemu_args "$common_qemu_args -usbdevice disk::[run_dir].iso"
|
|
||||||
run_genode_until {.*"iso9660" announces service "ROM".*\n} 60
|
|
||||||
close $spawn_id
|
|
||||||
|
|
||||||
puts "\nBooting from USB storage device succeeded\n"
|
|
||||||
|
|
||||||
puts "Test succeeded"
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
|||||||
D3m stands for demo device driver manager. It is the service responsible for
|
|
||||||
implementing device-driver policies such as probing for a boot device or
|
|
||||||
merging user input coming from different input devices (USB HID and PS/2).
|
|
||||||
|
|
||||||
The actual device drivers are executed as child processes of d3m. At the
|
|
||||||
current stage, d3m is primarily geared towards bootable live CD images.
|
|
@ -1,322 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief D3m block service
|
|
||||||
* \author Norman Feske
|
|
||||||
* \author Christian Helmuth
|
|
||||||
* \date 2012-01-25
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2012-2013 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BLOCK_SERVICE_H_
|
|
||||||
#define _BLOCK_SERVICE_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <util/list.h>
|
|
||||||
#include <block_session/capability.h>
|
|
||||||
#include <root/component.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Facility to probe a block session for the presence of a specific file
|
|
||||||
*
|
|
||||||
* The 'Iso9660_boot_probe' utility is used to select an iso9660 formatted
|
|
||||||
* block device to boot from by checking for the presence of a magic file.
|
|
||||||
*/
|
|
||||||
class Iso9660_boot_probe
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Policy for iso9660 server when executed as slave service
|
|
||||||
*
|
|
||||||
* The policy supplies a predefined block root capability to the iso9660
|
|
||||||
* server.
|
|
||||||
*/
|
|
||||||
struct Iso9660_policy : Genode::Slave_policy
|
|
||||||
{
|
|
||||||
Genode::Lock &_annouce_lock;
|
|
||||||
Genode::Capability<Block::Session> _block_session;
|
|
||||||
Genode::Root_capability _rom_root;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pseudo service, handing out a predefined session capability
|
|
||||||
*/
|
|
||||||
struct Proxy_service : Genode::Service
|
|
||||||
{
|
|
||||||
Genode::Session_capability _session;
|
|
||||||
|
|
||||||
Proxy_service(Genode::Session_capability session)
|
|
||||||
: Genode::Service("proxy"), _session(session) { }
|
|
||||||
|
|
||||||
Genode::Session_capability session(char const *,
|
|
||||||
Genode::Affinity const &)
|
|
||||||
{ return _session; }
|
|
||||||
|
|
||||||
void upgrade(Genode::Session_capability session, const char *) { }
|
|
||||||
|
|
||||||
} _block_proxy_service;
|
|
||||||
|
|
||||||
Iso9660_policy(Genode::Rpc_entrypoint &entrypoint,
|
|
||||||
Genode::Lock &annouce_lock,
|
|
||||||
Genode::Capability<Block::Session> block_session)
|
|
||||||
:
|
|
||||||
Genode::Slave_policy("iso9660", entrypoint),
|
|
||||||
_annouce_lock(annouce_lock),
|
|
||||||
_block_session(block_session),
|
|
||||||
_block_proxy_service(block_session)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
Genode::Root_capability rom_root() { return _rom_root; }
|
|
||||||
|
|
||||||
|
|
||||||
/****************************
|
|
||||||
** Slave_policy interface **
|
|
||||||
****************************/
|
|
||||||
|
|
||||||
const char **_permitted_services() const
|
|
||||||
{
|
|
||||||
static const char *permitted_services[] = {
|
|
||||||
"CAP", "RM", "LOG", "SIGNAL", 0 };
|
|
||||||
return permitted_services;
|
|
||||||
};
|
|
||||||
|
|
||||||
Genode::Service *resolve_session_request(const char *service_name,
|
|
||||||
const char *args)
|
|
||||||
{
|
|
||||||
if (Genode::strcmp(service_name, "Block") == 0)
|
|
||||||
return &_block_proxy_service;
|
|
||||||
|
|
||||||
return Genode::Slave_policy::resolve_session_request(service_name, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool announce_service(char const *service_name,
|
|
||||||
Genode::Root_capability root,
|
|
||||||
Genode::Allocator *alloc,
|
|
||||||
Genode::Server *server)
|
|
||||||
{
|
|
||||||
if (Genode::strcmp(service_name, "ROM") != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_rom_root = root;
|
|
||||||
_annouce_lock.unlock();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Genode::Root_capability _block_root;
|
|
||||||
Block::Session_capability _block_session;
|
|
||||||
Genode::Lock _rom_announce_lock;
|
|
||||||
Genode::Cap_connection _cap;
|
|
||||||
|
|
||||||
enum { STACK_SIZE = 2*4096 };
|
|
||||||
Genode::Rpc_entrypoint _entrypoint;
|
|
||||||
|
|
||||||
Iso9660_policy _iso9660_policy;
|
|
||||||
Genode::Slave _iso9660_slave;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RAM quota to assign to the iso9660 service
|
|
||||||
*/
|
|
||||||
enum { ISO9660_RAM_QUOTA = 8*1024*1024 };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain block session from specified root interface
|
|
||||||
*/
|
|
||||||
Block::Session_capability _init_session()
|
|
||||||
{
|
|
||||||
char const *args = "ram_quota=140K, tx_buf_size=128K";
|
|
||||||
Genode::Root_client root(_block_root);
|
|
||||||
return Genode::static_cap_cast<Block::Session>
|
|
||||||
(root.session(args, Genode::Affinity()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor
|
|
||||||
*
|
|
||||||
* This constructor is used by the 'probe' function below.
|
|
||||||
*/
|
|
||||||
Iso9660_boot_probe(Genode::Root_capability root, char const *boot_tag_name)
|
|
||||||
:
|
|
||||||
_block_root(root),
|
|
||||||
_block_session(_init_session()),
|
|
||||||
_rom_announce_lock(Genode::Lock::LOCKED),
|
|
||||||
_entrypoint(&_cap, STACK_SIZE, "iso9660_slave"),
|
|
||||||
_iso9660_policy(_entrypoint, _rom_announce_lock, _block_session),
|
|
||||||
_iso9660_slave(_entrypoint, _iso9660_policy, ISO9660_RAM_QUOTA)
|
|
||||||
{
|
|
||||||
/* wait until the iso9660 server announces the ROM service */
|
|
||||||
_rom_announce_lock.lock();
|
|
||||||
|
|
||||||
/* try to open file with filename 'boot_tag_name' */
|
|
||||||
Genode::Root_client rom_root(_iso9660_policy.rom_root());
|
|
||||||
char args[Genode::Root::Session_args::MAX_SIZE];
|
|
||||||
Genode::snprintf(args, sizeof(args), "ram_quota=4K, filename=\"%s\"",
|
|
||||||
boot_tag_name);
|
|
||||||
rom_root.session(args, Genode::Affinity());
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Probe block service for the presence of a boot tag file
|
|
||||||
*
|
|
||||||
* \param root root capability of block service to probe
|
|
||||||
* \param boot_tag_name name of the file to probe for
|
|
||||||
*
|
|
||||||
* \return true if the specified tag file exists at the block session
|
|
||||||
*/
|
|
||||||
static bool probe(Genode::Root_capability root,
|
|
||||||
char const *boot_tag_name)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* In the process of creating an 'Iso9660_boot_probe', many steps
|
|
||||||
* can fail. For example, the binary of the iso9660 server may be
|
|
||||||
* missing, the block service may not contain an iso9660 file
|
|
||||||
* system, or the file may be missing. Only if all steps succeed,
|
|
||||||
* we report the probing to have succeeded.
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
/*
|
|
||||||
* Do not allocate the boot probe at the stack because this
|
|
||||||
* object may too large for the stack size of the context
|
|
||||||
* calling the probe function. We use the heap instead to
|
|
||||||
* create and subsequently destroy the boot probe.
|
|
||||||
*/
|
|
||||||
Iso9660_boot_probe *boot_probe = new (Genode::env()->heap())
|
|
||||||
Iso9660_boot_probe(root, boot_tag_name);
|
|
||||||
|
|
||||||
Genode::destroy(Genode::env()->heap(), boot_probe);
|
|
||||||
return true;
|
|
||||||
} catch (...) { }
|
|
||||||
|
|
||||||
PWRN("Could not probe file at iso9660 ROM service");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Iso9660_boot_probe()
|
|
||||||
{
|
|
||||||
/* close session at block service */
|
|
||||||
Genode::Root_client(_block_root).close(_block_session);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
namespace Block {
|
|
||||||
|
|
||||||
class Driver : public Genode::List<Driver>::Element
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
char const *_name;
|
|
||||||
Genode::Root_capability _root;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Driver() : _name(0) { }
|
|
||||||
|
|
||||||
void init(char const *name, Genode::Root_capability root)
|
|
||||||
{
|
|
||||||
_name = name;
|
|
||||||
_root = root;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *name() const { return _name; }
|
|
||||||
|
|
||||||
Genode::Root_capability root() const { return _root; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Driver_registry
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Genode::Lock _lock;
|
|
||||||
Genode::List<Driver> _drivers;
|
|
||||||
Genode::Semaphore _retry_probing_sem;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
void add_driver(Driver *driver)
|
|
||||||
{
|
|
||||||
Genode::Lock::Guard guard(_lock);
|
|
||||||
|
|
||||||
_drivers.insert(driver);
|
|
||||||
|
|
||||||
PDBG("\ninsert new driver %s", driver->name());
|
|
||||||
_retry_probing_sem.up();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return root capability of boot device
|
|
||||||
*
|
|
||||||
* If the boot device is not available yet, block until a matching
|
|
||||||
* driver becomes available.
|
|
||||||
*/
|
|
||||||
Genode::Root_capability root()
|
|
||||||
{
|
|
||||||
for (;;) {
|
|
||||||
{
|
|
||||||
Genode::Lock::Guard guard(_lock);
|
|
||||||
while (_drivers.first()) {
|
|
||||||
|
|
||||||
Driver *driver = _drivers.first();
|
|
||||||
PDBG("\nprobing driver %s", driver->name());
|
|
||||||
|
|
||||||
if (!Iso9660_boot_probe::probe(driver->root(),
|
|
||||||
"libc.lib.so")) {
|
|
||||||
PWRN("probing failed, not using %s as boot device",
|
|
||||||
driver->name());
|
|
||||||
|
|
||||||
_drivers.remove(driver);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
PINF("found boot medium via %s", driver->name());
|
|
||||||
return driver->root();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Block until another driver becomes known via
|
|
||||||
* 'add_driver'
|
|
||||||
*/
|
|
||||||
_retry_probing_sem.down();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Root : public Genode::Rpc_object<Genode::Typed_root<Session> >
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Driver_registry &_driver_registry;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Root(Driver_registry &driver_registry)
|
|
||||||
: _driver_registry(driver_registry) { }
|
|
||||||
|
|
||||||
Genode::Session_capability session(Genode::Root::Session_args const &args,
|
|
||||||
Genode::Affinity const &affinity)
|
|
||||||
{
|
|
||||||
PDBG("\nsession requested args=\"%s\"", args.string());
|
|
||||||
Genode::Root_capability root = _driver_registry.root();
|
|
||||||
return Genode::Root_client(root).session(args, affinity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void upgrade(Genode::Session_capability,
|
|
||||||
Genode::Root::Upgrade_args const &) { }
|
|
||||||
|
|
||||||
void close(Genode::Session_capability session)
|
|
||||||
{
|
|
||||||
Genode::Root_capability root = _driver_registry.root();
|
|
||||||
Genode::Root_client(root).close(session);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _BLOCK_SERVICE_H_ */
|
|
@ -1,288 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief D3m input service
|
|
||||||
* \author Norman Feske
|
|
||||||
* \author Christian Helmuth
|
|
||||||
* \date 2012-01-25
|
|
||||||
*
|
|
||||||
* D3m supports merging the input events of multiple devices into one
|
|
||||||
* stream of events. Each driver corresponds to an event 'Source'. When the
|
|
||||||
* driver announces the "Input" session interface, the corresponding
|
|
||||||
* 'Source' is added to the 'Source_registry'. The d3m input serves queries
|
|
||||||
* all sources registered at the source registry for input and merges the
|
|
||||||
* streams of events.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2012-2013 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INPUT_SERVICE_H_
|
|
||||||
#define _INPUT_SERVICE_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <os/attached_ram_dataspace.h>
|
|
||||||
#include <root/component.h>
|
|
||||||
#include <util/list.h>
|
|
||||||
#include <input_session/client.h>
|
|
||||||
#include <input/event.h>
|
|
||||||
|
|
||||||
namespace Input {
|
|
||||||
|
|
||||||
class Source : public Genode::List<Source>::Element
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
class Source_unavailable { };
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Genode::Root_capability _root;
|
|
||||||
Input::Session_capability _session;
|
|
||||||
Input::Session_client _client;
|
|
||||||
Event *_ev_buf;
|
|
||||||
Genode::size_t _ev_buf_max; /* in events */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open input session via the specified root capability
|
|
||||||
*/
|
|
||||||
static Session_capability
|
|
||||||
_request_session(Genode::Root_capability root)
|
|
||||||
{
|
|
||||||
const char *args = "ram_quota=8K";
|
|
||||||
|
|
||||||
try {
|
|
||||||
using namespace Genode;
|
|
||||||
return static_cap_cast<Session>
|
|
||||||
(Root_client(root).session(args, Genode::Affinity()));
|
|
||||||
} catch (...) {
|
|
||||||
throw Source_unavailable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* At construction time, the '_client' gets initialized using the
|
|
||||||
* default-initialized (invalid) '_session' capability. The
|
|
||||||
* 'Source::session' function is not usaable before
|
|
||||||
* re-initializing the object via the 'connect' function.
|
|
||||||
*/
|
|
||||||
Source()
|
|
||||||
: _client(_session), _ev_buf(0), _ev_buf_max(0) { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the driver announces the "Input" service
|
|
||||||
*/
|
|
||||||
void connect(Genode::Root_capability root)
|
|
||||||
{
|
|
||||||
_root = root;
|
|
||||||
_session = _request_session(_root);
|
|
||||||
_client = Session_client(_session);
|
|
||||||
|
|
||||||
/* locally map input-event buffer */
|
|
||||||
Genode::Dataspace_capability ds_cap = _client.dataspace();
|
|
||||||
_ev_buf = Genode::env()->rm_session()->attach(ds_cap);
|
|
||||||
_ev_buf_max = Genode::Dataspace_client(ds_cap).size()
|
|
||||||
/ sizeof(Event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true is 'session()' is ready to use
|
|
||||||
*/
|
|
||||||
bool connected() const { return _session.valid(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if input is pending
|
|
||||||
*/
|
|
||||||
bool input_pending() const { return connected() && _client.is_pending(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return event buffer
|
|
||||||
*/
|
|
||||||
Event const *ev_buf() const { return _ev_buf; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flush input events
|
|
||||||
*/
|
|
||||||
Genode::size_t flush() { return _client.flush(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register signal handler for input notifications
|
|
||||||
*/
|
|
||||||
void sigh(Genode::Signal_context_capability sigh)
|
|
||||||
{
|
|
||||||
_client.sigh(sigh);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Source_registry
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Genode::Lock _lock;
|
|
||||||
Genode::List<Source> _sources;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a new source of input events
|
|
||||||
*
|
|
||||||
* This function is called once for each driver, when the driver
|
|
||||||
* announced its "Input" service. By adding the new source, the
|
|
||||||
* driver's input events become visible to the d3m input session.
|
|
||||||
*/
|
|
||||||
void add_source(Source *entry)
|
|
||||||
{
|
|
||||||
Genode::Lock::Guard guard(_lock);
|
|
||||||
_sources.insert(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool any_source_has_pending_input()
|
|
||||||
{
|
|
||||||
Genode::Lock::Guard guard(_lock);
|
|
||||||
|
|
||||||
for (Source *e = _sources.first(); e; e = e->next())
|
|
||||||
if (e->connected() && e->input_pending())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flush all input events from all available sources
|
|
||||||
*
|
|
||||||
* This function merges the input-event streams of all sources into
|
|
||||||
* one.
|
|
||||||
*
|
|
||||||
* \param dst destination event buffer
|
|
||||||
* \param dst_max capacility of event buffer, in number of events
|
|
||||||
*
|
|
||||||
* \return total number of available input events
|
|
||||||
*/
|
|
||||||
Genode::size_t flush_sources(Event *dst, Genode::size_t dst_max)
|
|
||||||
{
|
|
||||||
Genode::size_t dst_count = 0;
|
|
||||||
|
|
||||||
for (Source *e = _sources.first(); e; e = e->next()) {
|
|
||||||
|
|
||||||
if (!e->connected() || !e->input_pending())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy input events from driver to client buffer
|
|
||||||
*/
|
|
||||||
Event const *src = e->ev_buf();
|
|
||||||
Genode::size_t const src_max = e->flush();
|
|
||||||
for (Genode::size_t i = 0; i < src_max; i++, dst_count++) {
|
|
||||||
|
|
||||||
if (dst_count == dst_max) {
|
|
||||||
PERR("client input-buffer overflow");
|
|
||||||
return dst_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst[dst_count] = src[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dst_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sigh(Genode::Signal_context_capability sigh)
|
|
||||||
{
|
|
||||||
for (Source *e = _sources.first(); e; e = e->next())
|
|
||||||
e->sigh(sigh);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************
|
|
||||||
** Input service front end **
|
|
||||||
*****************************/
|
|
||||||
|
|
||||||
class Session_component : public Genode::Rpc_object<Session>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Source_registry &_source_registry;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input event buffer shared with the client
|
|
||||||
*/
|
|
||||||
enum { MAX_EVENTS = 1000 };
|
|
||||||
Genode::Attached_ram_dataspace _ev_ds;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Session_component(Source_registry &source_registry)
|
|
||||||
:
|
|
||||||
_source_registry(source_registry),
|
|
||||||
_ev_ds(Genode::env()->ram_session(), MAX_EVENTS*sizeof(Event))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/*****************************
|
|
||||||
** Input-session interface **
|
|
||||||
*****************************/
|
|
||||||
|
|
||||||
Genode::Dataspace_capability dataspace() override { return _ev_ds.cap(); }
|
|
||||||
|
|
||||||
bool is_pending() const override
|
|
||||||
{
|
|
||||||
return _source_registry.any_source_has_pending_input();
|
|
||||||
}
|
|
||||||
|
|
||||||
int flush() override
|
|
||||||
{
|
|
||||||
return _source_registry.flush_sources(_ev_ds.local_addr<Event>(),
|
|
||||||
MAX_EVENTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sigh(Genode::Signal_context_capability sigh) override
|
|
||||||
{
|
|
||||||
_source_registry.sigh(sigh);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut for single-client root component
|
|
||||||
*/
|
|
||||||
typedef Genode::Root_component<Session_component, Genode::Single_client> Root_component;
|
|
||||||
|
|
||||||
class Root : public Root_component
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Source_registry &_source_registry;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
Session_component *_create_session(const char *args)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return new (md_alloc()) Session_component(_source_registry);
|
|
||||||
} catch (Genode::Allocator::Out_of_memory()) {
|
|
||||||
PERR("Out of memory");
|
|
||||||
throw Genode::Root::Quota_exceeded();
|
|
||||||
} catch (...) {
|
|
||||||
PERR("Exception in construction of NIC slave");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Root(Genode::Rpc_entrypoint *session_ep,
|
|
||||||
Genode::Allocator *md_alloc,
|
|
||||||
Source_registry &source_registry)
|
|
||||||
:
|
|
||||||
Root_component(session_ep, md_alloc),
|
|
||||||
_source_registry(source_registry)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _INPUT_SERVICE_H_ */
|
|
@ -1,317 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Demo device-driver manager (d3m)
|
|
||||||
* \author Christian Helmuth
|
|
||||||
* \author Norman Feske
|
|
||||||
* \date 2010-09-21
|
|
||||||
*
|
|
||||||
* D3m is a simple device-driver manager for demo purposes. Currently, it copes
|
|
||||||
* with the following tasks:
|
|
||||||
*
|
|
||||||
* - Merge events of input drivers for PS/2 and USB HID
|
|
||||||
* - Probe boot device using the ATAPI and USB storage drivers
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2012-2013 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 <os/slave.h>
|
|
||||||
#include <base/printf.h>
|
|
||||||
#include <base/sleep.h>
|
|
||||||
#include <base/env.h>
|
|
||||||
#include <rom_session/connection.h>
|
|
||||||
#include <cap_session/connection.h>
|
|
||||||
#include <nic_session/client.h>
|
|
||||||
|
|
||||||
/* local includes */
|
|
||||||
#include <input_service.h>
|
|
||||||
#include <nic_service.h>
|
|
||||||
#include <block_service.h>
|
|
||||||
|
|
||||||
|
|
||||||
class Ipxe_policy : public Genode::Slave_policy, public Nic::Provider
|
|
||||||
{
|
|
||||||
Genode::Root_capability _cap;
|
|
||||||
bool _announced;
|
|
||||||
Genode::Lock _lock;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
char const **_permitted_services() const
|
|
||||||
{
|
|
||||||
static char const *permitted_services[] = {
|
|
||||||
"CAP", "RM", "LOG", "SIGNAL", "Timer", "PCI",
|
|
||||||
"IO_MEM", "IO_PORT", "IRQ", 0 };
|
|
||||||
|
|
||||||
return permitted_services;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Ipxe_policy(Genode::Rpc_entrypoint &entrypoint)
|
|
||||||
:
|
|
||||||
Slave_policy("nic_drv", entrypoint),
|
|
||||||
_announced(false),
|
|
||||||
_lock(Genode::Lock::LOCKED)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
bool announce_service(const char *service_name,
|
|
||||||
Genode::Root_capability root,
|
|
||||||
Genode::Allocator *alloc,
|
|
||||||
Genode::Server *server)
|
|
||||||
{
|
|
||||||
if (Genode::strcmp(service_name, "Nic"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_cap = root;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Nic::Provider interface
|
|
||||||
*/
|
|
||||||
Genode::Root_capability root() { return _cap; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Ps2_policy : public Genode::Slave_policy
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Input::Source_registry &_input_source_registry;
|
|
||||||
Input::Source _input_source_registry_entry;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
char const **_permitted_services() const
|
|
||||||
{
|
|
||||||
static char const *allowed_services[] = {
|
|
||||||
"CAP", "RM", "IO_PORT", "IRQ", "LOG", 0 };
|
|
||||||
|
|
||||||
return allowed_services;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Ps2_policy(Genode::Rpc_entrypoint &entrypoint,
|
|
||||||
Input::Source_registry &input_source_registry)
|
|
||||||
:
|
|
||||||
Genode::Slave_policy("ps2_drv", entrypoint),
|
|
||||||
_input_source_registry(input_source_registry)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
bool announce_service(const char *service_name,
|
|
||||||
Genode::Root_capability root,
|
|
||||||
Genode::Allocator *alloc,
|
|
||||||
Genode::Server *server)
|
|
||||||
{
|
|
||||||
if (Genode::strcmp(service_name, "Input"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_input_source_registry_entry.connect(root);
|
|
||||||
_input_source_registry.add_source(&_input_source_registry_entry);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Usb_policy : public Genode::Slave_policy
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Input::Source_registry &_input_source_registry;
|
|
||||||
Input::Source _input_source_registry_entry;
|
|
||||||
|
|
||||||
Block::Driver_registry &_block_driver_registry;
|
|
||||||
Block::Driver _block_driver;
|
|
||||||
|
|
||||||
Genode::Root_capability _input_root;
|
|
||||||
Genode::Root_capability _block_root;
|
|
||||||
Genode::Lock _input_root_lock;
|
|
||||||
Genode::Lock _block_root_lock;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
const char **_permitted_services() const
|
|
||||||
{
|
|
||||||
static const char *permitted_services[] = {
|
|
||||||
"CAP", "RM", "IO_PORT", "IO_MEM", "IRQ", "LOG", "PCI",
|
|
||||||
"Timer", "SIGNAL", 0 };
|
|
||||||
|
|
||||||
return permitted_services;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Usb_policy(Genode::Rpc_entrypoint &entrypoint,
|
|
||||||
Input::Source_registry &input_source_registry,
|
|
||||||
Block::Driver_registry &block_driver_registry,
|
|
||||||
Genode::Ram_session *ram,
|
|
||||||
char const *config)
|
|
||||||
:
|
|
||||||
Genode::Slave_policy("usb_drv", entrypoint, ram),
|
|
||||||
_input_source_registry(input_source_registry),
|
|
||||||
_block_driver_registry(block_driver_registry),
|
|
||||||
_input_root_lock(Genode::Lock::LOCKED),
|
|
||||||
_block_root_lock(Genode::Lock::LOCKED)
|
|
||||||
{
|
|
||||||
configure(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool announce_service(const char *service_name,
|
|
||||||
Genode::Root_capability root,
|
|
||||||
Genode::Allocator *alloc,
|
|
||||||
Genode::Server *server)
|
|
||||||
{
|
|
||||||
PINF("announce_service %s", service_name);
|
|
||||||
if (Genode::strcmp(service_name, "Input") == 0) {
|
|
||||||
_input_root = root;
|
|
||||||
_input_root_lock.unlock();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Genode::strcmp(service_name, "Block") == 0) {
|
|
||||||
_block_root = root;
|
|
||||||
_block_root_lock.unlock();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void connect_input()
|
|
||||||
{
|
|
||||||
_input_root_lock.lock();
|
|
||||||
_input_source_registry_entry.connect(_input_root);
|
|
||||||
_input_source_registry.add_source(&_input_source_registry_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
void connect_block()
|
|
||||||
{
|
|
||||||
_block_root_lock.lock();
|
|
||||||
_block_driver.init("usb_drv", _block_root);
|
|
||||||
_block_driver_registry.add_driver(&_block_driver);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Atapi_policy : public Genode::Slave_policy
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Block::Driver_registry &_block_driver_registry;
|
|
||||||
Block::Driver _block_driver;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
const char **_permitted_services() const
|
|
||||||
{
|
|
||||||
static const char *permitted_services[] = {
|
|
||||||
"CAP", "RM", "LOG", "SIGNAL", "Timer", "PCI", "IO_MEM",
|
|
||||||
"IO_PORT", "IRQ", 0 };
|
|
||||||
|
|
||||||
return permitted_services;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Atapi_policy(Genode::Rpc_entrypoint &entrypoint,
|
|
||||||
Block::Driver_registry &block_driver_registry)
|
|
||||||
:
|
|
||||||
Genode::Slave_policy("atapi_drv", entrypoint),
|
|
||||||
_block_driver_registry(block_driver_registry) { }
|
|
||||||
|
|
||||||
bool announce_service(char const *service_name,
|
|
||||||
Genode::Root_capability root,
|
|
||||||
Genode::Allocator *alloc,
|
|
||||||
Genode::Server *server)
|
|
||||||
{
|
|
||||||
if (Genode::strcmp(service_name, "Block"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_block_driver.init(name(), root);
|
|
||||||
_block_driver_registry.add_driver(&_block_driver);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
enum { STACK_SIZE = 2*4096 };
|
|
||||||
static Cap_connection cap;
|
|
||||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "d3m_ep");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Registry of input-event sources
|
|
||||||
*
|
|
||||||
* Upon startup of the USB HID and PS/2 drivers, this registry gets
|
|
||||||
* populated when each of the drivers announces its respective 'Input'
|
|
||||||
* service.
|
|
||||||
*/
|
|
||||||
static Input::Source_registry input_source_registry;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Registry for boot block device
|
|
||||||
*/
|
|
||||||
static Block::Driver_registry block_driver_registry;
|
|
||||||
|
|
||||||
/* create PS/2 driver */
|
|
||||||
static Rpc_entrypoint ps2_ep(&cap, STACK_SIZE, "ps2_slave");
|
|
||||||
static Ps2_policy ps2_policy(ps2_ep, input_source_registry);
|
|
||||||
static Genode::Slave ps2_slave(ps2_ep, ps2_policy, 768*1024);
|
|
||||||
|
|
||||||
/* create USB driver */
|
|
||||||
char const *config = "<config uhci=\"yes\" ehci=\"yes\"><hid/><storage/></config>";
|
|
||||||
static Rpc_entrypoint usb_ep(&cap, STACK_SIZE, "usb_slave");
|
|
||||||
static Usb_policy usb_policy(usb_ep, input_source_registry,
|
|
||||||
block_driver_registry, env()->ram_session(),
|
|
||||||
config);
|
|
||||||
static Genode::Slave usb_slave(usb_ep, usb_policy, 3*1024*1024);
|
|
||||||
|
|
||||||
/* create ATAPI driver */
|
|
||||||
static Rpc_entrypoint atapi_ep(&cap, STACK_SIZE, "atapi_slave");
|
|
||||||
static Atapi_policy atapi_policy(atapi_ep, block_driver_registry);
|
|
||||||
static Genode::Slave atapi_slave(atapi_ep, atapi_policy, 1024*1024);
|
|
||||||
|
|
||||||
/* initialize input service */
|
|
||||||
static Input::Root input_root(&ep, env()->heap(), input_source_registry);
|
|
||||||
env()->parent()->announce(ep.manage(&input_root));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Always announce 'Nic' service, throw 'Unavailable' during session
|
|
||||||
* request if no appropriate driver could be found.
|
|
||||||
*/
|
|
||||||
static Rpc_entrypoint nic_ep(&cap, STACK_SIZE, "nic_slave");
|
|
||||||
static Ipxe_policy nic_policy(nic_ep);
|
|
||||||
static Genode::Slave nic_slave(nic_ep, nic_policy, 2048 * 1024);
|
|
||||||
|
|
||||||
static Nic::Root nic_root(nic_policy);
|
|
||||||
env()->parent()->announce(ep.manage(&nic_root));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Announce 'Block' service
|
|
||||||
*
|
|
||||||
* We use a distinct entrypoint for the block driver because otherwise, a
|
|
||||||
* long-taking block session request may defer other session requests
|
|
||||||
* (i.e., input session). By using a different entrypoint, the GUI can
|
|
||||||
* start even if the boot-device probing failed completely.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "d3m_block_ep");
|
|
||||||
static Block::Root block_root(block_driver_registry);
|
|
||||||
env()->parent()->announce(ep.manage(&block_root));
|
|
||||||
}
|
|
||||||
|
|
||||||
usb_policy.connect_input();
|
|
||||||
usb_policy.connect_block();
|
|
||||||
|
|
||||||
Genode::sleep_forever();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief D3m NIC service
|
|
||||||
* \author Norman Feske
|
|
||||||
* \author Christian Helmuth
|
|
||||||
* \date 2012-01-25
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2012-2013 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _NIC_SERVICE_H_
|
|
||||||
#define _NIC_SERVICE_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <nic_session/nic_session.h>
|
|
||||||
#include <root/component.h>
|
|
||||||
#include <util/list.h>
|
|
||||||
|
|
||||||
namespace Nic {
|
|
||||||
|
|
||||||
struct Provider
|
|
||||||
{
|
|
||||||
bool ready_to_use() { return root().valid(); }
|
|
||||||
|
|
||||||
virtual Genode::Root_capability root() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Root interface of NIC service
|
|
||||||
*/
|
|
||||||
class Root : public Genode::Rpc_object<Genode::Typed_root<Nic::Session> >
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Provider &_nic_provider;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Genode::Session_capability session(Session_args const &args,
|
|
||||||
Genode::Affinity const &affinity)
|
|
||||||
{
|
|
||||||
if (!args.is_valid_string()) throw Invalid_args();
|
|
||||||
|
|
||||||
if (!_nic_provider.ready_to_use())
|
|
||||||
throw Unavailable();
|
|
||||||
|
|
||||||
try {
|
|
||||||
return Genode::Root_client(_nic_provider.root())
|
|
||||||
.session(args.string(), affinity);
|
|
||||||
} catch (...) {
|
|
||||||
throw Unavailable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void upgrade(Genode::Session_capability, Upgrade_args const &) { }
|
|
||||||
|
|
||||||
void close(Genode::Session_capability session)
|
|
||||||
{
|
|
||||||
Genode::Root_client(_nic_provider.root()).close(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
Root(Provider &nic_provider) : _nic_provider(nic_provider) { }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _INPUT_SERVICE_H_ */
|
|
@ -1,4 +0,0 @@
|
|||||||
TARGET = d3m
|
|
||||||
SRC_CC = main.cc
|
|
||||||
LIBS = base
|
|
||||||
INC_DIR += $(PRG_DIR)
|
|
Loading…
x
Reference in New Issue
Block a user