mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-27 01:11:06 +00:00
201 lines
4.2 KiB
C
201 lines
4.2 KiB
C
|
/*
|
||
|
* \brief Platform abstraction
|
||
|
* \date 2005-10-24
|
||
|
* \author Norman Feske <norman.feske@genode-labs.com>
|
||
|
*
|
||
|
* This interface specifies the target-platform-specific functions.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Copyright (C) 2005-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 _INCLUDE__SCOUT__PLATFORM_H_
|
||
|
#define _INCLUDE__SCOUT__PLATFORM_H_
|
||
|
|
||
|
#include <base/env.h>
|
||
|
#include <base/semaphore.h>
|
||
|
#include <timer_session/connection.h>
|
||
|
#include <input_session/input_session.h>
|
||
|
#include <input/event.h>
|
||
|
#include <scout/event.h>
|
||
|
#include <scout/canvas.h>
|
||
|
|
||
|
namespace Scout {
|
||
|
|
||
|
typedef Genode::Point<> Point;
|
||
|
typedef Genode::Area<> Area;
|
||
|
typedef Genode::Rect<> Rect;
|
||
|
|
||
|
class Platform;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline void *operator new(Genode::size_t size)
|
||
|
{
|
||
|
using Genode::env;
|
||
|
void *addr = env()->heap()->alloc(size);
|
||
|
if (!addr) {
|
||
|
PERR("env()->heap() has consumed %zd", env()->heap()->consumed());
|
||
|
PERR("env()->ram_session()->quota = %zd", env()->ram_session()->quota());
|
||
|
throw Genode::Allocator::Out_of_memory();
|
||
|
}
|
||
|
return addr;
|
||
|
}
|
||
|
|
||
|
|
||
|
class Scout::Platform
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
/*****************
|
||
|
** Event queue **
|
||
|
*****************/
|
||
|
|
||
|
class Event_queue
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
static const int queue_size = 1024;
|
||
|
|
||
|
int _head;
|
||
|
int _tail;
|
||
|
Genode::Semaphore _sem;
|
||
|
Genode::Lock _head_lock; /* synchronize add */
|
||
|
|
||
|
Event _queue[queue_size];
|
||
|
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
* Constructor
|
||
|
*/
|
||
|
Event_queue(): _head(0), _tail(0)
|
||
|
{
|
||
|
Genode::memset(_queue, 0, sizeof(_queue));
|
||
|
}
|
||
|
|
||
|
void add(Event ev)
|
||
|
{
|
||
|
Genode::Lock::Guard lock_guard(_head_lock);
|
||
|
|
||
|
if ((_head + 1)%queue_size != _tail) {
|
||
|
|
||
|
_queue[_head] = ev;
|
||
|
_head = (_head + 1)%queue_size;
|
||
|
_sem.up();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Event get()
|
||
|
{
|
||
|
_sem.down();
|
||
|
Event ev = _queue[_tail];
|
||
|
_tail = (_tail + 1)%queue_size;
|
||
|
return ev;
|
||
|
}
|
||
|
|
||
|
int pending() const { return _head != _tail; }
|
||
|
|
||
|
} _event_queue;
|
||
|
|
||
|
/******************
|
||
|
** Timer thread **
|
||
|
******************/
|
||
|
|
||
|
class Timer_thread : public Genode::Thread<4096>
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
Timer::Connection _timer;
|
||
|
Input::Session &_input;
|
||
|
Input::Event *_ev_buf = { Genode::env()->rm_session()->attach(_input.dataspace()) };
|
||
|
Event_queue &_event_queue;
|
||
|
int _mx, _my;
|
||
|
unsigned long _ticks = { 0 };
|
||
|
|
||
|
void _import_events()
|
||
|
{
|
||
|
if (_input.is_pending() == false) return;
|
||
|
|
||
|
for (int i = 0, num = _input.flush(); i < num; i++)
|
||
|
{
|
||
|
Event ev;
|
||
|
Input::Event e = _ev_buf[i];
|
||
|
|
||
|
if (e.type() == Input::Event::RELEASE
|
||
|
|| e.type() == Input::Event::PRESS) {
|
||
|
_mx = e.ax();
|
||
|
_my = e.ay();
|
||
|
ev.assign(e.type() == Input::Event::PRESS ? Event::PRESS : Event::RELEASE,
|
||
|
e.ax(), e.ay(), e.code());
|
||
|
_event_queue.add(ev);
|
||
|
}
|
||
|
|
||
|
if (e.type() == Input::Event::MOTION) {
|
||
|
_mx = e.ax();
|
||
|
_my = e.ay();
|
||
|
ev.assign(Event::MOTION, e.ax(), e.ay(), e.code());
|
||
|
_event_queue.add(ev);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
* Constructor
|
||
|
*
|
||
|
* Start thread immediately on construction.
|
||
|
*/
|
||
|
Timer_thread(Input::Session &input, Event_queue &event_queue)
|
||
|
: Thread("timer"), _input(input), _event_queue(event_queue)
|
||
|
{ start(); }
|
||
|
|
||
|
void entry()
|
||
|
{
|
||
|
while (1) {
|
||
|
Event ev;
|
||
|
ev.assign(Event::TIMER, _mx, _my, 0);
|
||
|
_event_queue.add(ev);
|
||
|
|
||
|
_import_events();
|
||
|
|
||
|
_timer.msleep(10);
|
||
|
_ticks += 10;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned long ticks() const { return _ticks; }
|
||
|
} _timer_thread;
|
||
|
|
||
|
public:
|
||
|
|
||
|
Platform(Input::Session &input) : _timer_thread(input, _event_queue) { }
|
||
|
|
||
|
/**
|
||
|
* Get timer ticks in miilliseconds
|
||
|
*/
|
||
|
unsigned long timer_ticks() const { return _timer_thread.ticks(); }
|
||
|
|
||
|
/**
|
||
|
* Return true if an event is pending
|
||
|
*/
|
||
|
bool event_pending() const { return _event_queue.pending(); }
|
||
|
|
||
|
/**
|
||
|
* Request event
|
||
|
*
|
||
|
* \param e destination where to store event information.
|
||
|
*
|
||
|
* If there is no event pending, this function blocks
|
||
|
* until there is an event to deliver.
|
||
|
*/
|
||
|
Event get_event() { return _event_queue.get(); }
|
||
|
};
|
||
|
|
||
|
#endif /* _INCLUDE__SCOUT__PLATFORM_H_ */
|