genode/dde_linux/src/drivers/usb/signal/event.cc
Sebastian Sumpf 9f73476b37 New DDE-Linux-based USB driver
The new 'dde_linux' repository will host device drivers ported from the
Linux kernel. In contrast to the original 'linux_drivers' repository,
'dde_linux' does not contain any 3rd-party source code. To download the
Linux kernel source code and extract the drivers, execute the 'make
prepare' rule of the top-level Makefile. The initial version of the
'dde_linux' repository comes with an USB driver. The porting methodology
follows the path of the Intel GEM port. Instead of attempting to provide
a generic Linux environment that works across drivers, each driver comes
with a specially tailored DDE.

The DDE consists of Genode-specific implementations of Linux API
functions as declared in 'lx_emul.h'. Most of these functions are
dummies that must merely be provided to resolve dependencies at the
linking stage. They are called by unused code-paths.

As of now, the USB driver support UHCI, EHCI on the x86_32 platform. I
exposes USB HID devices and USB storage devices via Genode's input-session
and block-session respectively.

The USB driver is accompanied with two run scripts 'run/usb_hid.run' and
'run/usb_storage.run'.
2012-05-29 13:54:58 +02:00

168 lines
3.0 KiB
C++

/*
* \brief Signal context for completions and events
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-05-23
*/
/*
* Copyright (C) 2012 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.
*/
#include <signal.h>
#include <lx_emul.h>
static Signal_helper *_signal = 0;
/**
* Context for events
*/
class Event_context : public Driver_context
{
private:
Genode::Signal_context_capability _ctx_cap;
Event_context()
: _ctx_cap(_signal->receiver()->manage(this)) {
_signal->sender()->context(_ctx_cap); }
public:
static Event_context *e()
{
static Event_context _e;
return &_e;
}
void submit() {
_signal->sender()->submit(); }
void handle() {
Routine::schedule_all(); }
};
void Event::init(Genode::Signal_receiver *recv) {
_signal = new (Genode::env()->heap()) Signal_helper(recv); }
/************************
** linux/completion.h **
************************/
void __wake_up() { Routine::schedule_all(); }
void __wait_event() {
Service_handler::s()->process(); }
void init_completion(struct completion *work)
{
dde_kit_log(DEBUG_COMPLETION, "New completion %p", work);
work->done = 0;
}
void complete(struct completion *work)
{
dde_kit_log(DEBUG_COMPLETION, "%p", work);
work->done = 1;
/* send signal */
Event_context::e()->submit();
}
void complete_and_exit(struct completion *work, long code)
{
dde_kit_log(DEBUG_COMPLETION, "%p", work);
complete(work);
Routine::remove();
}
static void __wait_completion(struct completion *work)
{
while (!work->done)
__wait_event();
work->done = 0;
}
static unsigned long
__wait_completion_timeout(struct completion *work, unsigned long timeout)
{
unsigned long _j = jiffies + (timeout / HZ);
while (!work->done) {
__wait_event();
if (_j >= jiffies)
return 0;
}
work->done = 0;
return _j - jiffies;
}
unsigned long wait_for_completion_timeout(struct completion *work,
unsigned long timeout)
{
dde_kit_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
__wait_completion(work);
return 1;
}
int wait_for_completion_interruptible(struct completion *work)
{
dde_kit_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
__wait_completion(work);
return 0;
}
long wait_for_completion_interruptible_timeout(struct completion *work,
unsigned long timeout)
{
dde_kit_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
__wait_completion(work);
return 1;
}
void wait_for_completion(struct completion *work)
{
dde_kit_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
__wait_completion(work);
}
/*******************
** linux/timer.h **
*******************/
signed long schedule_timeout_uninterruptible(signed long timeout)
{
dde_kit_log(DEBUG_COMPLETION, "%ld\n", timeout);
__wait_event();
return 0;
}
int wake_up_process(struct task_struct *tsk)
{
Routine::schedule_all();
return 0;
}