diff --git a/repos/dde_linux/src/lib/usb/input/input_component.cc b/repos/dde_linux/src/lib/usb/input/input_component.cc index e4d33ca1f..b553d9bb2 100644 --- a/repos/dde_linux/src/lib/usb/input/input_component.cc +++ b/repos/dde_linux/src/lib/usb/input/input_component.cc @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -25,19 +25,27 @@ using namespace Genode; -/********************* - ** Input component ** - *********************/ +/** + * Return singleton instance of input-session component + */ +static Input::Session_component &input_session() +{ + static Input::Session_component inst; + return inst; +} -typedef Ring_buffer Input_ring_buffer; -static Input_ring_buffer ev_queue; - -namespace Input { - - void event_handling(bool enable) { } - bool event_pending() { return !ev_queue.empty(); } - Event get_event() { return ev_queue.get(); } +/** + * Return singleton instance of input-root component + * + * On the first call (from 'start_input_service'), the 'ep' argument is + * specified. All subsequent calls (from 'input_callback') just return the + * reference to the singleton instance. + */ +static Input::Root_component &input_root(Rpc_entrypoint *ep = 0) +{ + static Input::Root_component root(*ep, input_session()); + return root; } @@ -58,20 +66,20 @@ static void input_callback(enum input_event_type type, } try { - ev_queue.add(Input::Event(t, code, - absolute_x, absolute_y, - relative_x, relative_y)); - } catch (Input_ring_buffer::Overflow) { + input_session().submit(Input::Event(t, code, + absolute_x, absolute_y, + relative_x, relative_y)); + } catch (Input::Event_queue::Overflow) { PWRN("input ring buffer overflow"); } } -void start_input_service(void *ep) +void start_input_service(void *ep_ptr) { - Rpc_entrypoint *e = static_cast(ep); - static Input::Root input_root(e, env()->heap()); - env()->parent()->announce(e->manage(&input_root)); + Rpc_entrypoint *ep = static_cast(ep_ptr); + + env()->parent()->announce(ep->manage(&input_root(ep))); genode_input_register(input_callback); } diff --git a/repos/demo/src/server/liquid_framebuffer/services.cc b/repos/demo/src/server/liquid_framebuffer/services.cc index be9765e4b..f465b6524 100644 --- a/repos/demo/src/server/liquid_framebuffer/services.cc +++ b/repos/demo/src/server/liquid_framebuffer/services.cc @@ -11,77 +11,30 @@ * under the terms of the GNU General Public License version 2. */ +/* Genode include */ #include #include #include #include -#include +#include #include #include +#include +/* local includes */ #include "services.h" typedef Genode::Texture Texture_rgb565; -/***************** - ** Event queue ** - *****************/ - -class Event_queue +/** + * Return singleton instance of input session component + */ +Input::Session_component &input_session() { - private: - - enum { QUEUE_SIZE = 1024 }; - - Input::Event _queue[QUEUE_SIZE]; - int _head; - int _tail; - Genode::Semaphore _sem; - - public: - - /** - * Constructor - */ - Event_queue(): _head(0), _tail(0) - { - Scout::memset(_queue, 0, sizeof(_queue)); - } - - void post(Input::Event ev) - { - if ((_head + 1)%QUEUE_SIZE != _tail) { - _queue[_head] = ev; - _head = (_head + 1)%QUEUE_SIZE; - _sem.up(); - } - } - - Input::Event get() - { - _sem.down(); - Input::Event dst_ev = _queue[_tail]; - _tail = (_tail + 1)%QUEUE_SIZE; - return dst_ev; - } - - int pending() { return _head != _tail; } - -} _ev_queue; - - -/*************************** - ** Input service backend ** - ***************************/ - -namespace Input { - - void event_handling(bool enable) { } - bool event_pending() { return _ev_queue.pending(); } - Event get_event() { return _ev_queue.get(); } - + static Input::Session_component inst; + return inst; } @@ -93,16 +46,16 @@ class Window_content : public Scout::Element { private: - Event_queue *_ev_queue; - Scout::Point _old_mouse_position; - Element *_element; + Input::Session_component &_input_session; + Scout::Point _old_mouse_position; + Element *_element; public: - Content_event_handler(Event_queue *ev_queue, + Content_event_handler(Input::Session_component &input_session, Scout::Element *element) : - _ev_queue(ev_queue), _element(element) { } + _input_session(input_session),_element(element) { } void handle(Scout::Event &ev) { @@ -123,10 +76,10 @@ class Window_content : public Scout::Element : Input::Event::INVALID; if (type != Input::Event::INVALID) - _ev_queue->post(Input::Event(type, code, mouse_position.x(), - mouse_position.y(), - mouse_position.x() - _old_mouse_position.x(), - mouse_position.y() - _old_mouse_position.y())); + _input_session.submit(Input::Event(type, code, mouse_position.x(), + mouse_position.y(), + mouse_position.x() - _old_mouse_position.x(), + mouse_position.y() - _old_mouse_position.y())); _old_mouse_position = mouse_position; } @@ -173,9 +126,9 @@ class Window_content : public Scout::Element }; - bool _config_alpha; - Content_event_handler _ev_handler; - Fb_texture *_fb; + bool _config_alpha; + Content_event_handler _ev_handler; + Fb_texture *_fb; /** * Size of the framebuffer handed out by the next call of 'dataspace' @@ -198,11 +151,12 @@ class Window_content : public Scout::Element public: - Window_content(unsigned fb_w, unsigned fb_h, Event_queue *ev_queue, + Window_content(unsigned fb_w, unsigned fb_h, + Input::Session_component &input_session, bool config_alpha) : _config_alpha(config_alpha), - _ev_handler(ev_queue, this), + _ev_handler(input_session, this), _fb(new (Genode::env()->heap()) Fb_texture(fb_w, fb_h, _config_alpha)), _next_size(fb_w, fb_h), _designated_size(_next_size) @@ -268,76 +222,52 @@ Scout::Element *window_content() { return _window_content; } ** Implementation of the framebuffer service ** ***********************************************/ -namespace Framebuffer +namespace Framebuffer { class Session_component; } + +class Framebuffer::Session_component : public Genode::Rpc_object { - class Session_component : public Genode::Rpc_object - { - private: + private: - Window_content &_window_content; + Window_content &_window_content; - Genode::Signal_context_capability _sync_sigh; + Genode::Signal_context_capability _sync_sigh; - public: + public: - Session_component(Window_content &window_content) - : _window_content(window_content) { } + Session_component(Window_content &window_content) + : _window_content(window_content) { } - Genode::Dataspace_capability dataspace() override - { - _window_content.realloc_framebuffer(); - return _window_content.fb_ds_cap(); - } + Genode::Dataspace_capability dataspace() override + { + _window_content.realloc_framebuffer(); + return _window_content.fb_ds_cap(); + } - Mode mode() const override - { - return Mode(_window_content.mode_size().w(), - _window_content.mode_size().h(), Mode::RGB565); - } + Mode mode() const override + { + return Mode(_window_content.mode_size().w(), + _window_content.mode_size().h(), Mode::RGB565); + } - void mode_sigh(Genode::Signal_context_capability sigh) override { - _window_content.mode_sigh(sigh); } + void mode_sigh(Genode::Signal_context_capability sigh) override { + _window_content.mode_sigh(sigh); } - void sync_sigh(Genode::Signal_context_capability sigh) override { - _sync_sigh = sigh; } + void sync_sigh(Genode::Signal_context_capability sigh) override { + _sync_sigh = sigh; } - void refresh(int x, int y, int w, int h) override - { - _window_content.redraw_area(x, y, w, h); + void refresh(int x, int y, int w, int h) override + { + _window_content.redraw_area(x, y, w, h); - if (_sync_sigh.valid()) - Genode::Signal_transmitter(_sync_sigh).submit(); - } - }; - - - class Root : public Genode::Root_component - { - private: - - Window_content &_window_content; - - protected: - - Session_component *_create_session(const char *args) override { - return new (md_alloc()) Session_component(_window_content); } - - public: - - Root(Genode::Rpc_entrypoint *session_ep, - Genode::Allocator *md_alloc, - Window_content &window_content) - : - Genode::Root_component(session_ep, md_alloc), - _window_content(window_content) - { } - }; -} + if (_sync_sigh.valid()) + Genode::Signal_transmitter(_sync_sigh).submit(); + } +}; void init_window_content(unsigned fb_w, unsigned fb_h, bool config_alpha) { - static Window_content content(fb_w, fb_h, &_ev_queue, config_alpha); + static Window_content content(fb_w, fb_h, input_session(), config_alpha); _window_content = &content; } @@ -346,11 +276,10 @@ void init_services(Genode::Rpc_entrypoint &ep) { using namespace Genode; - /* - * Let the entry point serve the framebuffer and input root interfaces - */ - static Framebuffer::Root fb_root(&ep, env()->heap(), *_window_content); - static Input::Root input_root(&ep, env()->heap()); + static Framebuffer::Session_component fb_session(*_window_content); + static Static_root fb_root(ep.manage(&fb_session)); + + static Input::Root_component input_root(ep, input_session()); /* * Now, the root interfaces are ready to accept requests. diff --git a/repos/gems/src/server/d3m/input_service.h b/repos/gems/src/server/d3m/input_service.h index 771455f9e..4932afdd8 100644 --- a/repos/gems/src/server/d3m/input_service.h +++ b/repos/gems/src/server/d3m/input_service.h @@ -110,6 +110,14 @@ namespace Input { * 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); + } }; @@ -183,6 +191,12 @@ namespace Input { } return dst_count; } + + void sigh(Genode::Signal_context_capability sigh) + { + for (Source *e = _sources.first(); e; e = e->next()) + e->sigh(sigh); + } }; @@ -214,18 +228,23 @@ namespace Input { ** Input-session interface ** *****************************/ - Genode::Dataspace_capability dataspace() { return _ev_ds.cap(); } + Genode::Dataspace_capability dataspace() override { return _ev_ds.cap(); } - bool is_pending() const + bool is_pending() const override { return _source_registry.any_source_has_pending_input(); } - int flush() + int flush() override { return _source_registry.flush_sources(_ev_ds.local_addr(), MAX_EVENTS); } + + void sigh(Genode::Signal_context_capability sigh) override + { + _source_registry.sigh(sigh); + } }; /** diff --git a/repos/libports/src/app/qt5/qt_avplay/control_bar.cpp b/repos/libports/src/app/qt5/qt_avplay/control_bar.cpp index 2fb88fc6d..d40eff97c 100644 --- a/repos/libports/src/app/qt5/qt_avplay/control_bar.cpp +++ b/repos/libports/src/app/qt5/qt_avplay/control_bar.cpp @@ -17,22 +17,22 @@ /* Qoost includes */ #include -#include "input_service.h" +/* local includes */ #include "main_window.h" void Control_bar::_rewind() { /* mouse click at horizontal position 0 */ - ev_queue.add(Input::Event(Input::Event::PRESS, Input::BTN_LEFT, 0, 0, 0, 0)); - ev_queue.add(Input::Event(Input::Event::RELEASE, Input::BTN_LEFT, 0, 0, 0, 0)); + _event_queue.add(Input::Event(Input::Event::PRESS, Input::BTN_LEFT, 0, 0, 0, 0)); + _event_queue.add(Input::Event(Input::Event::RELEASE, Input::BTN_LEFT, 0, 0, 0, 0)); } void Control_bar::_pause_resume() { - ev_queue.add(Input::Event(Input::Event::PRESS, Input::KEY_SPACE, 0, 0, 0, 0)); - ev_queue.add(Input::Event(Input::Event::RELEASE, Input::KEY_SPACE, 0, 0, 0, 0)); + _event_queue.add(Input::Event(Input::Event::PRESS, Input::KEY_SPACE, 0, 0, 0, 0)); + _event_queue.add(Input::Event(Input::Event::RELEASE, Input::KEY_SPACE, 0, 0, 0, 0)); _playing = !_playing; if (_playing) @@ -51,8 +51,9 @@ void Control_bar::_stop() } -Control_bar::Control_bar() -: _playing(true) +Control_bar::Control_bar(Input::Event_queue &event_queue) +: + _event_queue(event_queue), _playing(true) { update_style_id(_play_pause_button, "play"); diff --git a/repos/libports/src/app/qt5/qt_avplay/control_bar.h b/repos/libports/src/app/qt5/qt_avplay/control_bar.h index 86f1afcf4..7a88ddf4f 100644 --- a/repos/libports/src/app/qt5/qt_avplay/control_bar.h +++ b/repos/libports/src/app/qt5/qt_avplay/control_bar.h @@ -22,6 +22,9 @@ #include #include +/* Genode includes */ +#include + struct Play_pause_button : QPushButton { Q_OBJECT }; struct Stop_button : QPushButton { Q_OBJECT }; struct Volume_label : QLabel { Q_OBJECT }; @@ -33,6 +36,8 @@ class Control_bar : public Compound_widget private: + Input::Event_queue &_event_queue; + QMember _play_pause_button; QMember _stop_button; QMember _volume_label; @@ -49,7 +54,7 @@ class Control_bar : public Compound_widget public: - Control_bar(); + Control_bar(Input::Event_queue &event_queue); Q_SIGNALS: diff --git a/repos/libports/src/app/qt5/qt_avplay/input_service.cpp b/repos/libports/src/app/qt5/qt_avplay/input_service.cpp deleted file mode 100644 index 65bb5a5c4..000000000 --- a/repos/libports/src/app/qt5/qt_avplay/input_service.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * \brief Input service - * \author Christian Prochaska - * \date 2012-03-29 - */ - -/* - * 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 - -#include "input_service.h" - -using namespace Genode; - -Event_queue ev_queue; - - -namespace Input { - - /* - * Event handling is disabled on queue creation and will be enabled later if a - * session is created. - */ - void event_handling(bool enable) - { - if (enable) - ev_queue.enable(); - else - ev_queue.disable(); - } - - bool event_pending() { return !ev_queue.empty(); } - Event get_event() { return ev_queue.get(); } -} diff --git a/repos/libports/src/app/qt5/qt_avplay/input_service.h b/repos/libports/src/app/qt5/qt_avplay/input_service.h deleted file mode 100644 index 7612f2699..000000000 --- a/repos/libports/src/app/qt5/qt_avplay/input_service.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * \brief Input service - * \author Christian Prochaska - * \date 2012-03-29 - */ - -/* - * 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 - -extern Event_queue ev_queue; - -extern void create_input_service(); - -#endif /* _INPUT_SERVICE_H_ */ diff --git a/repos/libports/src/app/qt5/qt_avplay/main.cpp b/repos/libports/src/app/qt5/qt_avplay/main.cpp index 84a751adf..de37c2a27 100644 --- a/repos/libports/src/app/qt5/qt_avplay/main.cpp +++ b/repos/libports/src/app/qt5/qt_avplay/main.cpp @@ -17,6 +17,11 @@ /* qt_avplay includes */ #include "main_window.h" +/* Genode includes */ +#include +#include +#include + static inline void load_stylesheet() { @@ -37,6 +42,14 @@ int main(int argc, char *argv[]) load_stylesheet(); + /* look for dynamic linker */ + try { + static Genode::Rom_connection ldso_rom("ld.lib.so"); + Genode::Process::dynamic_linker(ldso_rom.dataspace()); + } catch (...) { + PERR("ld.lib.so not found"); + } + QMember main_window; main_window->show(); diff --git a/repos/libports/src/app/qt5/qt_avplay/main_window.cpp b/repos/libports/src/app/qt5/qt_avplay/main_window.cpp index 163dd9ded..1659206aa 100644 --- a/repos/libports/src/app/qt5/qt_avplay/main_window.cpp +++ b/repos/libports/src/app/qt5/qt_avplay/main_window.cpp @@ -11,17 +11,10 @@ * under the terms of the GNU General Public License version 2. */ -/* Genode includes */ -#include -#include -#include -#include - /* qt_avplay includes */ #include "avplay_policy.h" #include "filter_framebuffer_policy.h" #include "framebuffer_root.h" -#include "input_service.h" #include "main_window.h" @@ -30,49 +23,23 @@ using namespace Genode; struct Framebuffer_filter { - enum { MAX_FILTER_NAME_SIZE = 32 }; - char name[MAX_FILTER_NAME_SIZE]; - Genode::Number_of_bytes ram_quota; + enum { MAX_FILTER_NAME_SIZE = 32 }; + char name[MAX_FILTER_NAME_SIZE]; + Genode::Number_of_bytes ram_quota; - Service_registry *framebuffer_out_registry; - Rpc_entrypoint *ep; - Filter_framebuffer_policy *policy; - Slave *slave; + Service_registry *framebuffer_out_registry; + Rpc_entrypoint *ep; + Filter_framebuffer_policy *policy; + Slave *slave; }; Main_window::Main_window() +: + _control_bar(_input_session.event_queue()) { - /* look for dynamic linker */ - - try { - static Rom_connection ldso_rom("ld.lib.so"); - Process::dynamic_linker(ldso_rom.dataspace()); - } catch (...) { - PERR("ld.lib.so not found"); - } - - /* get the name of the media file from the config file */ - enum { MAX_LEN_MEDIAFILE_NAME = 256 }; - static char mediafile[MAX_LEN_MEDIAFILE_NAME] = "mediafile"; - try { - config()->xml_node().sub_node("mediafile").attribute("name").value(mediafile, sizeof(mediafile)); - } catch(...) { - PWRN("no config node found, using \"mediafile\""); - } - - /* create local services */ - - enum { STACK_SIZE = 2*sizeof(addr_t)*1024 }; - static Cap_connection cap; - static Rpc_entrypoint avplay_ep(&cap, STACK_SIZE, "avplay_ep"); - static Service_registry input_registry; - static Service_registry nitpicker_framebuffer_registry; - - static Input::Root input_root(&avplay_ep, env()->heap()); - static Local_service input_service(Input::Session::service_name(), &input_root); - input_registry.insert(&input_service); - avplay_ep.manage(&input_root); + _input_registry.insert(&_input_service); + _ep.manage(&_input_root); /* find out which filtering framebuffer services to start and sort them in reverse order */ @@ -90,15 +57,15 @@ Main_window::Main_window() /* start the filtering framebuffer services */ - Service_registry *framebuffer_in_registry = &nitpicker_framebuffer_registry; + Service_registry *framebuffer_in_registry = &_nitpicker_framebuffer_registry; Q_FOREACH(Framebuffer_filter *framebuffer_filter, framebuffer_filters) { framebuffer_filter->framebuffer_out_registry = new Service_registry; - framebuffer_filter->ep = new Rpc_entrypoint(&cap, STACK_SIZE, "filter_fb_ep"); + framebuffer_filter->ep = new Rpc_entrypoint(&_cap, STACK_SIZE, "filter_fb_ep"); framebuffer_filter->policy = new Filter_framebuffer_policy(framebuffer_filter->name, *framebuffer_filter->ep, - *framebuffer_in_registry, - *framebuffer_filter->framebuffer_out_registry); + *framebuffer_in_registry, + *framebuffer_filter->framebuffer_out_registry); framebuffer_filter->slave = new Slave(*framebuffer_filter->ep, *framebuffer_filter->policy, framebuffer_filter->ram_quota); @@ -106,17 +73,17 @@ Main_window::Main_window() } Rpc_entrypoint *local_framebuffer_ep = framebuffer_filters.isEmpty() ? - &avplay_ep : + &_ep : framebuffer_filters.at(0)->ep; static Framebuffer::Root framebuffer_root(local_framebuffer_ep, env()->heap(), *_avplay_widget, 640, 480); static Local_service framebuffer_service(Framebuffer::Session::service_name(), &framebuffer_root); - nitpicker_framebuffer_registry.insert(&framebuffer_service); + _nitpicker_framebuffer_registry.insert(&framebuffer_service); /* start avplay */ - static Avplay_policy avplay_policy(avplay_ep, input_registry, *framebuffer_in_registry, mediafile); - static Genode::Slave avplay_slave(avplay_ep, avplay_policy, 32*1024*1024); + static Avplay_policy avplay_policy(_ep, _input_registry, *framebuffer_in_registry, _mediafile_name.buf); + static Genode::Slave avplay_slave(_ep, avplay_policy, 32*1024*1024); /* add widgets to layout */ diff --git a/repos/libports/src/app/qt5/qt_avplay/main_window.h b/repos/libports/src/app/qt5/qt_avplay/main_window.h index aaf869922..0b10b58cd 100644 --- a/repos/libports/src/app/qt5/qt_avplay/main_window.h +++ b/repos/libports/src/app/qt5/qt_avplay/main_window.h @@ -23,6 +23,14 @@ #include #include +/* Genode includes */ +#include +#include +#include +#include +#include + +/* local includes */ #include "control_bar.h" @@ -32,6 +40,35 @@ class Main_window : public Compound_widget private: + struct Mediafile_name + { + /* get the name of the media file from the config file */ + enum { MAX_LEN_MEDIAFILE_NAME = 256 }; + char buf[MAX_LEN_MEDIAFILE_NAME]; + + Mediafile_name() + { + Genode::strncpy(buf, "mediafile", sizeof(buf)); + try { + Genode::config()->xml_node().sub_node("mediafile") + .attribute("name").value(buf, sizeof(buf)); + } catch(...) { + PWRN("no config node found, using \"mediafile\""); + } + } + } _mediafile_name; + + enum { STACK_SIZE = 2*sizeof(Genode::addr_t)*1024 }; + Genode::Cap_connection _cap; + Genode::Rpc_entrypoint _ep { &_cap, STACK_SIZE, "avplay_ep" }; + Genode::Service_registry _input_registry; + Genode::Service_registry _nitpicker_framebuffer_registry; + + Input::Session_component _input_session; + Input::Root_component _input_root { _ep, _input_session }; + + Genode::Local_service _input_service { Input::Session::service_name(), &_input_root }; + QMember _avplay_widget; QMember _control_bar; diff --git a/repos/libports/src/app/qt5/qt_avplay/qt_avplay.pro b/repos/libports/src/app/qt5/qt_avplay/qt_avplay.pro index 8b9dc41c5..5c2c7d9d1 100644 --- a/repos/libports/src/app/qt5/qt_avplay/qt_avplay.pro +++ b/repos/libports/src/app/qt5/qt_avplay/qt_avplay.pro @@ -6,7 +6,6 @@ HEADERS = avplay_policy.h \ main_window.h SOURCES = control_bar.cpp \ framebuffer_session_component.cc \ - input_service.cpp \ main.cpp \ main_window.cpp RESOURCES = style.qrc diff --git a/repos/os/include/input/component.h b/repos/os/include/input/component.h index 06de55761..3fceef878 100644 --- a/repos/os/include/input/component.h +++ b/repos/os/include/input/component.h @@ -17,100 +17,61 @@ #include #include #include +#include #include #include -#include +#include -namespace Input { +namespace Input { class Session_component; } - /******************** - ** Input back end ** - ********************/ +class Input::Session_component : public Genode::Rpc_object +{ + private: - /** - * Enable/disable input event handling - * - * \param enable enable (true) or disable (false) back end - * - * The front end informs the back end about when to start capturing input - * events for an open session. Later, the back end may be deactivated on - * session destruction. - */ - void event_handling(bool enable); + Genode::Attached_ram_dataspace _ds { Genode::env()->ram_session(), + Event_queue::QUEUE_SIZE*sizeof(Input::Event) }; - /** - * Check if an event is pending - */ - bool event_pending(); + Event_queue _event_queue; - /** - * Wait for an event, Zzz...zz.. - */ - Input::Event get_event(); + public: + + /** + * Return reference to event queue of the session + */ + Event_queue &event_queue() { return _event_queue; } + + /** + * Submit input event to event queue + * + * \throw Input::Event_queue::Overflow + */ + void submit(Input::Event event) { _event_queue.add(event); } - /***************************** - ** Input service front end ** - *****************************/ + /****************************** + ** Input::Session interface ** + ******************************/ - class Session_component : public Genode::Rpc_object - { - private: + Genode::Dataspace_capability dataspace() override { return _ds.cap(); } - /* - * Input event buffer that is shared with the client - */ - enum { MAX_EVENTS = 1000 }; + bool is_pending() const override { return !_event_queue.empty(); } - Genode::Attached_ram_dataspace _ev_ds; + int flush() override + { + Input::Event *dst = _ds.local_addr(); + + unsigned cnt = 0; + for (; cnt < Event_queue::QUEUE_SIZE && !_event_queue.empty(); cnt++) + *dst++ = _event_queue.get(); - public: + return cnt; + } - Session_component() - : _ev_ds(Genode::env()->ram_session(), MAX_EVENTS*sizeof(Event)) { - event_handling(true); } - - ~Session_component() { - event_handling(false); } - - Genode::Dataspace_capability dataspace() { return _ev_ds.cap(); } - - bool is_pending() const { return event_pending(); } - - int flush() - { - /* dump events into event buffer dataspace */ - int i; - Input::Event *ev_ds_buf = _ev_ds.local_addr(); - for (i = 0; (i < MAX_EVENTS) && event_pending(); ++i) - ev_ds_buf[i] = get_event(); - - /* return number of flushed events */ - return i; - } - }; - - - /** - * Shortcut for single-client root component - */ - typedef Genode::Root_component Root_component; - - - class Root : public Root_component - { - protected: - - Session_component *_create_session(const char *args) { - return new (md_alloc()) Session_component(); } - - public: - - Root(Genode::Rpc_entrypoint *session_ep, - Genode::Allocator *md_alloc) - : Root_component(session_ep, md_alloc) { } - }; -} + void sigh(Genode::Signal_context_capability sigh) override + { + _event_queue.sigh(sigh); + } +}; #endif /* _INCLUDE__INPUT__COMPONENT_H_ */ diff --git a/repos/os/include/input/event_queue.h b/repos/os/include/input/event_queue.h index 82dbe0b5a..262de0984 100644 --- a/repos/os/include/input/event_queue.h +++ b/repos/os/include/input/event_queue.h @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2007-2013 Genode Labs GmbH + * Copyright (C) 2007-2014 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. @@ -14,57 +14,70 @@ #ifndef _EVENT_QUEUE_H_ #define _EVENT_QUEUE_H_ -#include +#include #include #include -/** - * Input event queue - * - * We expect the client to fetch events circa each 10ms. The PS/2 driver queues - * up to 255 events, which should be enough. Normally, PS/2 generates not more - * than 16Kbit/s, which would correspond to ca. 66 mouse events per 10ms. - */ -class Event_queue +namespace Input { class Event_queue; }; + + +class Input::Event_queue { + public: + + /** + * Input event queue + * + * We expect the client to fetch events circa each 10ms. The PS/2 driver + * queues up to 255 events, which should be enough. Normally, PS/2 + * generates not more than 16Kbit/s, which would correspond to ca. 66 mouse + * events per 10ms. + */ + enum { QUEUE_SIZE = 512U }; + private: - bool _enabled; - Ring_buffer _ev_queue; + Ring_buffer _queue; + + bool _enabled = false; + + Genode::Signal_context_capability _sigh; public: - Event_queue() : _enabled(false), _ev_queue() { } + typedef typename Ring_buffer::Overflow Overflow; - void enable() { _enabled = true; } - void disable() { _enabled = false; } + void enabled(bool enabled) { _enabled = enabled; } - void add(Input::Event e) + bool enabled() const { return _enabled; } + + void sigh(Genode::Signal_context_capability sigh) { _sigh = sigh; } + + void submit_signal() { - if (!_enabled) return; - - try { - _ev_queue.add(e); - } catch (Ring_buffer::Overflow) { - PWRN("event buffer overflow"); - } + if (_sigh.valid()) + Genode::Signal_transmitter(_sigh).submit(); } - Input::Event get() + /** + * \throw Overflow + */ + void add(Input::Event ev, bool submit_signal_immediately = true) { - if (_enabled) - return _ev_queue.get(); - else - return Input::Event(); + if (!_enabled) + return; + + _queue.add(ev); + + if (submit_signal_immediately) + submit_signal(); } - bool empty() - { - if (_enabled) - return _ev_queue.empty(); - else - return true; - } + Input::Event get() { return _queue.get(); } + + bool empty() const { return _queue.empty(); } + + int avail_capacity() const { return _queue.avail_capacity(); } }; #endif /* _EVENT_QUEUE_H_ */ diff --git a/repos/os/include/input/root.h b/repos/os/include/input/root.h new file mode 100644 index 000000000..78a658a8c --- /dev/null +++ b/repos/os/include/input/root.h @@ -0,0 +1,70 @@ +/* + * \brief Input root component + * \author Norman Feske + * \date 2014-05-31 + */ + +/* + * Copyright (C) 2014 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__ROOT_H_ +#define _INPUT__ROOT_H_ + +/* Genode includes */ +#include +#include + + +namespace Input { class Root_component; } + +/* + * This input root component tracks if the session has been opened. If a client + * is connected, the 'Event_queue::enabled' gets enabled. This is useful to + * omit the enqueuing of input events into the event queue before any client is + * interested in receiving input events. If we would not drop such early input + * events, the queue might overflow when input events are generated at boot + * times. + */ +class Input::Root_component : public Genode::Static_root +{ + private: + + Genode::Rpc_entrypoint &_ep; + Input::Session_component &_session; + + public: + + Root_component(Genode::Rpc_entrypoint &ep, Input::Session_component &session) + : + Static_root(ep.manage(&session)), + _ep(ep), _session(session) + { } + + ~Root_component() + { + _ep.dissolve(&_session); + } + + Genode::Capability + session(Genode::Root::Session_args const &args, + Genode::Affinity const &affinity) override + { + if (_session.event_queue().enabled()) + throw Root::Unavailable(); + + _session.event_queue().enabled(true); + + return Static_root::session(args, affinity); + } + + void close(Genode::Capability) + { + _session.event_queue().enabled(false); + } +}; + +#endif /* _INPUT__ROOT_H_ */ diff --git a/repos/os/include/input_session/client.h b/repos/os/include/input_session/client.h index 42e47d5c4..2577b4b96 100644 --- a/repos/os/include/input_session/client.h +++ b/repos/os/include/input_session/client.h @@ -24,14 +24,17 @@ namespace Input { explicit Session_client(Session_capability session) : Genode::Rpc_client(session) { } - Genode::Dataspace_capability dataspace() { + Genode::Dataspace_capability dataspace() override { return call(); } - bool is_pending() const { + bool is_pending() const override { return call(); } - int flush() { + int flush() override { return call(); } + + void sigh(Genode::Signal_context_capability sigh) override { + call(sigh); } }; } diff --git a/repos/os/include/input_session/input_session.h b/repos/os/include/input_session/input_session.h index e9489b41c..9b48f6a27 100644 --- a/repos/os/include/input_session/input_session.h +++ b/repos/os/include/input_session/input_session.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace Input { @@ -45,6 +46,11 @@ namespace Input { */ virtual int flush() = 0; + /** + * Register signal handler to be notified on arrival of new input + */ + virtual void sigh(Genode::Signal_context_capability) = 0; + /********************* ** RPC declaration ** @@ -53,8 +59,9 @@ namespace Input { GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); GENODE_RPC(Rpc_is_pending, bool, is_pending); GENODE_RPC(Rpc_flush, int, flush); + GENODE_RPC(Rpc_sigh, void, sigh, Genode::Signal_context_capability); - GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_is_pending, Rpc_flush); + GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_is_pending, Rpc_flush, Rpc_sigh); }; } diff --git a/repos/os/src/drivers/framebuffer/sdl/fb_sdl.cc b/repos/os/src/drivers/framebuffer/sdl/fb_sdl.cc index 15bb575d5..e61b05bc2 100644 --- a/repos/os/src/drivers/framebuffer/sdl/fb_sdl.cc +++ b/repos/os/src/drivers/framebuffer/sdl/fb_sdl.cc @@ -19,10 +19,12 @@ #include #include #include -#include #include #include -#include +#include + +/* local includes */ +#include /* @@ -44,85 +46,63 @@ static void *fb_ds_addr; ** Implementation of the framebuffer service ** ***********************************************/ -namespace Framebuffer { +namespace Framebuffer { class Session_component; } - class Session_component : public Genode::Rpc_object - { - private: +class Framebuffer::Session_component : public Genode::Rpc_object +{ + private: - Mode _mode; + Mode _mode; - Genode::Signal_context_capability _sync_sigh; + Genode::Signal_context_capability _sync_sigh; - public: + public: - /** - * Constructor - */ - Session_component() : _mode(scr_width, scr_height, Mode::RGB565) { } + /** + * Constructor + */ + Session_component() : _mode(scr_width, scr_height, Mode::RGB565) { } - Genode::Dataspace_capability dataspace() override { return fb_ds_cap; } + Genode::Dataspace_capability dataspace() override { return fb_ds_cap; } - Mode mode() const override { return _mode; } + Mode mode() const override { return _mode; } - void mode_sigh(Genode::Signal_context_capability) override { } + void mode_sigh(Genode::Signal_context_capability) override { } - void sync_sigh(Genode::Signal_context_capability sigh) override - { - _sync_sigh = sigh; + void sync_sigh(Genode::Signal_context_capability sigh) override + { + _sync_sigh = sigh; + } + + void refresh(int x, int y, int w, int h) override + { + /* clip refresh area to screen boundaries */ + int x1 = Genode::max(x, 0); + int y1 = Genode::max(y, 0); + int x2 = Genode::min(x + w - 1, scr_width - 1); + int y2 = Genode::min(y + h - 1, scr_height - 1); + + if (x1 <= x2 && y1 <= y2) { + + /* copy pixels from shared dataspace to sdl surface */ + const int start_offset = _mode.bytes_per_pixel()*(y1*scr_width + x1); + const int line_len = _mode.bytes_per_pixel()*(x2 - x1 + 1); + const int pitch = _mode.bytes_per_pixel()*scr_width; + + char *src = (char *)fb_ds_addr + start_offset; + char *dst = (char *)screen->pixels + start_offset; + + for (int i = y1; i <= y2; i++, src += pitch, dst += pitch) + Genode::memcpy(dst, src, line_len); + + /* flush pixels in sdl window */ + SDL_UpdateRect(screen, x1, y1, x2 - x1 + 1, y2 - y1 + 1); } - void refresh(int x, int y, int w, int h) override - { - /* clip refresh area to screen boundaries */ - int x1 = Genode::max(x, 0); - int y1 = Genode::max(y, 0); - int x2 = Genode::min(x + w - 1, scr_width - 1); - int y2 = Genode::min(y + h - 1, scr_height - 1); - - if (x1 <= x2 && y1 <= y2) { - - /* copy pixels from shared dataspace to sdl surface */ - const int start_offset = _mode.bytes_per_pixel()*(y1*scr_width + x1); - const int line_len = _mode.bytes_per_pixel()*(x2 - x1 + 1); - const int pitch = _mode.bytes_per_pixel()*scr_width; - - char *src = (char *)fb_ds_addr + start_offset; - char *dst = (char *)screen->pixels + start_offset; - - for (int i = y1; i <= y2; i++, src += pitch, dst += pitch) - Genode::memcpy(dst, src, line_len); - - /* flush pixels in sdl window */ - SDL_UpdateRect(screen, x1, y1, x2 - x1 + 1, y2 - y1 + 1); - } - - if (_sync_sigh.valid()) - Genode::Signal_transmitter(_sync_sigh).submit(); - } - }; - - - /** - * Shortcut for single-client root component - */ - typedef Genode::Root_component Root_component; - - - class Root : public Root_component - { - protected: - - Session_component *_create_session(const char *args) override { - return new (md_alloc()) Session_component(); } - - public: - - Root(Genode::Rpc_entrypoint *session_ep, - Genode::Allocator *md_alloc) - : Root_component(session_ep, md_alloc) { } - }; -} + if (_sync_sigh.valid()) + Genode::Signal_transmitter(_sync_sigh).submit(); + } +}; /** @@ -172,19 +152,21 @@ extern "C" int main(int, char**) static Cap_connection cap; static Rpc_entrypoint ep(&cap, STACK_SIZE, "fb_ep"); - /* - * Let the entry point serve the framebuffer and input root interfaces - */ - static Framebuffer::Root framebuffer_root(&ep, env()->heap()); - static Input::Root input_root(&ep, env()->heap()); + static Input::Session_component input_session; + static Input::Root_component input_root(ep, input_session); + + static Framebuffer::Session_component fb_session; + static Static_root fb_root(ep.manage(&fb_session)); /* * Now, the root interfaces are ready to accept requests. * This is the right time to tell mummy about our services. */ - env()->parent()->announce(ep.manage(&framebuffer_root)); + env()->parent()->announce(ep.manage(&fb_root)); env()->parent()->announce(ep.manage(&input_root)); - sleep_forever(); + for (;;) + input_session.submit(wait_for_event()); + return 0; } diff --git a/repos/os/src/drivers/framebuffer/sdl/input.cc b/repos/os/src/drivers/framebuffer/sdl/input.cc index 99e21ce44..65e5be90a 100644 --- a/repos/os/src/drivers/framebuffer/sdl/input.cc +++ b/repos/os/src/drivers/framebuffer/sdl/input.cc @@ -16,12 +16,11 @@ /* Genode */ #include - -/* Local */ -#include - #include +/* local */ +#include + /** * Convert SDL keycode to Genode keycode */ @@ -139,14 +138,7 @@ static long convert_keycode(int sdl_keycode) }; -void Input::event_handling(bool enable) { } -bool Input::event_pending() { return SDL_PollEvent(0); } - - -/** - * Wait for an event, Zzz...zz.. - */ -Input::Event Input::get_event() +Input::Event wait_for_event() { using namespace Input; diff --git a/repos/os/src/drivers/framebuffer/sdl/input.h b/repos/os/src/drivers/framebuffer/sdl/input.h new file mode 100644 index 000000000..4b52c2440 --- /dev/null +++ b/repos/os/src/drivers/framebuffer/sdl/input.h @@ -0,0 +1,24 @@ +/* + * \brief SDL input support + * \author Norman Feske + * \date 2006-08-16 + */ + +/* + * Copyright (C) 2006-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_H_ +#define _INPUT_H_ + +#include + +/** + * Wait for an event, Zzz...zz.. + */ +Input::Event wait_for_event(); + +#endif /* _INPUT_H_ */ diff --git a/repos/os/src/drivers/framebuffer/sdl/target.mk b/repos/os/src/drivers/framebuffer/sdl/target.mk index df89f8cf2..33f046170 100644 --- a/repos/os/src/drivers/framebuffer/sdl/target.mk +++ b/repos/os/src/drivers/framebuffer/sdl/target.mk @@ -3,13 +3,4 @@ LIBS = lx_hybrid REQUIRES = linux sdl SRC_CC = fb_sdl.cc input.cc LX_LIBS = sdl - -# -# Explicitly add host headers to the include-search location. Even though this -# path happens to be added via the 'lx_hybrid' library via the 'HOST_INC_DIR' -# variable, we want to give /usr/include preference for resolving 'SDL/*' -# headers. Otherwise, if libSDL is prepared in 'libports', the build system -# would pull-in the SDL headers from libports. -# -INC_DIR += /usr/include - +INC_DIR += $(PRG_DIR) diff --git a/repos/os/src/drivers/input/dummy/main.cc b/repos/os/src/drivers/input/dummy/main.cc index a460baeb0..4e5d5c313 100644 --- a/repos/os/src/drivers/input/dummy/main.cc +++ b/repos/os/src/drivers/input/dummy/main.cc @@ -15,6 +15,7 @@ /* Genode */ #include #include +#include #include #include #include @@ -41,15 +42,17 @@ namespace Input { { public: - Dataspace_capability dataspace() { return ev_ds_cap; } + Dataspace_capability dataspace() override { return ev_ds_cap; } - bool is_pending() const { return 0; } + bool is_pending() const override { return 0; } - int flush() + int flush() override { /* return number of flushed events */ return 0; } + + void sigh(Genode::Signal_context_capability) override { } }; diff --git a/repos/os/src/drivers/input/imx53/main.cc b/repos/os/src/drivers/input/imx53/main.cc index 56076d9eb..9d3444f55 100644 --- a/repos/os/src/drivers/input/imx53/main.cc +++ b/repos/os/src/drivers/input/imx53/main.cc @@ -13,41 +13,21 @@ * under the terms of the GNU General Public License version 2. */ -/* Genode */ +/* Genode includes */ #include #include #include -#include #include #include #include +#include #include +/* local includes */ #include using namespace Genode; -static Event_queue ev_queue; - -namespace Input { - - /* - * Event handling is disabled on queue creation and will be enabled later if a - * session is created. - */ - void event_handling(bool enable) - { - if (enable) - ev_queue.enable(); - else - ev_queue.disable(); - } - - bool event_pending() { return !ev_queue.empty(); } - Event get_event() { return ev_queue.get(); } -} - - int main(int argc, char **argv) { /* initialize server entry point */ @@ -55,23 +35,25 @@ int main(int argc, char **argv) static Cap_connection cap; static Rpc_entrypoint ep(&cap, STACK_SIZE, "input_ep"); + static Input::Session_component session; + Platform::Connection plat_drv; switch (plat_drv.revision()) { case Platform::Session::SMD: plat_drv.enable(Platform::Session::I2C_2); plat_drv.enable(Platform::Session::I2C_3); plat_drv.enable(Platform::Session::BUTTONS); - Input::Tablet_driver::factory(ev_queue); + Input::Tablet_driver::factory(session.event_queue()); break; default: PWRN("No input driver available for this board"); } /* entry point serving input root interface */ - static Input::Root input_root(&ep, env()->heap()); + static Input::Root_component root(ep, session); /* tell parent about the service */ - env()->parent()->announce(ep.manage(&input_root)); + env()->parent()->announce(ep.manage(&root)); /* main's done - go to sleep */ sleep_forever(); diff --git a/repos/os/src/drivers/input/ps2/pl050/main.cc b/repos/os/src/drivers/input/ps2/pl050/main.cc index c69dccf11..58eb59cc0 100644 --- a/repos/os/src/drivers/input/ps2/pl050/main.cc +++ b/repos/os/src/drivers/input/ps2/pl050/main.cc @@ -11,12 +11,15 @@ * under the terms of the GNU General Public License version 2. */ +/* Genode includes */ #include #include #include #include +#include #include +/* local includes */ #include "ps2_keyboard.h" #include "ps2_mouse.h" #include "irq_handler.h" @@ -24,26 +27,6 @@ using namespace Genode; -static Event_queue ev_queue; - -namespace Input { - - /* - * Event handling is disabled on queue creation and will be enabled later if a - * session is created. - */ - void event_handling(bool enable) - { - if (enable) - ev_queue.enable(); - else - ev_queue.disable(); - } - - bool event_pending() { return !ev_queue.empty(); } - Event get_event() { return ev_queue.get(); } -} - int main(int argc, char **argv) { @@ -52,12 +35,6 @@ int main(int argc, char **argv) Serial_interface *kbd = pl050.kbd_interface(); Serial_interface *aux = pl050.aux_interface(); - Ps2_mouse ps2_mouse(*aux, ev_queue); - Ps2_keyboard ps2_keybd(*kbd, ev_queue, true); - - Irq_handler ps2_mouse_irq(PL050_MOUSE_IRQ, aux, ps2_mouse); - Irq_handler ps2_keybd_irq(PL050_KEYBD_IRQ, kbd, ps2_keybd); - /* * Initialize server entry point */ @@ -65,11 +42,19 @@ int main(int argc, char **argv) static Cap_connection cap; static Rpc_entrypoint ep(&cap, STACK_SIZE, "ps2_ep"); + static Input::Session_component session; + static Input::Root_component root(ep, session); + + Ps2_mouse ps2_mouse(*aux, session.event_queue()); + Ps2_keyboard ps2_keybd(*kbd, session.event_queue(), true); + + Irq_handler ps2_mouse_irq(PL050_MOUSE_IRQ, aux, ps2_mouse); + Irq_handler ps2_keybd_irq(PL050_KEYBD_IRQ, kbd, ps2_keybd); + /* * Let the entry point serve the input root interface */ - static Input::Root input_root(&ep, env()->heap()); - env()->parent()->announce(ep.manage(&input_root)); + env()->parent()->announce(ep.manage(&root)); Genode::sleep_forever(); return 0; diff --git a/repos/os/src/drivers/input/ps2/ps2_keyboard.h b/repos/os/src/drivers/input/ps2/ps2_keyboard.h index d62147f1c..f4a059a7b 100644 --- a/repos/os/src/drivers/input/ps2/ps2_keyboard.h +++ b/repos/os/src/drivers/input/ps2/ps2_keyboard.h @@ -30,9 +30,9 @@ class Ps2_keyboard : public Input_driver static const bool verbose = false; static const bool verbose_scan_codes = false; - Serial_interface &_kbd; - Event_queue &_ev_queue; - bool _xlate_mode; + Serial_interface &_kbd; + Input::Event_queue &_ev_queue; + bool _xlate_mode; /** * Array for tracking the current keyboard state @@ -363,7 +363,7 @@ class Ps2_keyboard : public Input_driver * If 'xlate_mode' is true, we do not attempt to manually switch the * keyboard to scan code set 2 but just decode the scan-code set 1. */ - Ps2_keyboard(Serial_interface &kbd, Event_queue &ev_queue, bool xlate_mode) + Ps2_keyboard(Serial_interface &kbd, Input::Event_queue &ev_queue, bool xlate_mode) : _kbd(kbd), _ev_queue(ev_queue), _xlate_mode(xlate_mode) { diff --git a/repos/os/src/drivers/input/ps2/ps2_mouse.h b/repos/os/src/drivers/input/ps2/ps2_mouse.h index 23860cd55..7896a47bb 100644 --- a/repos/os/src/drivers/input/ps2/ps2_mouse.h +++ b/repos/os/src/drivers/input/ps2/ps2_mouse.h @@ -71,12 +71,12 @@ class Ps2_mouse : public Input_driver static const bool verbose = false; - Serial_interface &_aux; - Event_queue &_ev_queue; + Serial_interface &_aux; + Input::Event_queue &_ev_queue; - Type _type; + Type _type; - bool _button_state[NUM_BUTTONS]; + bool _button_state[NUM_BUTTONS]; unsigned char _packet[MAX_PACKET_LEN]; int _packet_len; @@ -149,9 +149,10 @@ class Ps2_mouse : public Input_driver public: - Ps2_mouse(Serial_interface &aux, Event_queue &ev_queue) + Ps2_mouse(Serial_interface &aux, Input::Event_queue &ev_queue) : - _aux(aux), _ev_queue(ev_queue), _type(PS2), + _aux(aux), + _ev_queue(ev_queue), _type(PS2), _packet_len(PS2_PACKET_LEN), _packet_idx(0) { for (unsigned i = 0; i < NUM_BUTTONS; ++i) diff --git a/repos/os/src/drivers/input/ps2/x86/main.cc b/repos/os/src/drivers/input/ps2/x86/main.cc index 2fb90e812..5760bc18e 100644 --- a/repos/os/src/drivers/input/ps2/x86/main.cc +++ b/repos/os/src/drivers/input/ps2/x86/main.cc @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "i8042.h" @@ -24,26 +25,6 @@ using namespace Genode; -static Event_queue ev_queue; - -namespace Input { - - /* - * Event handling is disabled on queue creation and will be enabled later if a - * session is created. - */ - void event_handling(bool enable) - { - if (enable) - ev_queue.enable(); - else - ev_queue.disable(); - } - - bool event_pending() { return !ev_queue.empty(); } - Event get_event() { return ev_queue.get(); } -} - int main(int argc, char **argv) { @@ -52,24 +33,23 @@ int main(int argc, char **argv) Serial_interface *kbd = i8042.kbd_interface(); Serial_interface *aux = i8042.aux_interface(); - Ps2_mouse ps2_mouse(*aux, ev_queue); - Ps2_keyboard ps2_keybd(*kbd, ev_queue, i8042.kbd_xlate()); + /* + * Initialize server entry point + */ + enum { STACK_SIZE = 4096 }; + static Cap_connection cap; + static Rpc_entrypoint ep(&cap, STACK_SIZE, "ps2_ep"); + + static Input::Session_component session; + static Input::Root_component root(ep, session); + + Ps2_mouse ps2_mouse(*aux, session.event_queue()); + Ps2_keyboard ps2_keybd(*kbd, session.event_queue(), i8042.kbd_xlate()); Irq_handler ps2_mouse_irq(12, ps2_mouse); Irq_handler ps2_keybd_irq( 1, ps2_keybd); - /* - * Initialize server entry point - */ - enum { STACK_SIZE = sizeof(addr_t)*1024 }; - static Cap_connection cap; - static Rpc_entrypoint ep(&cap, STACK_SIZE, "ps2_ep"); - - /* - * Let the entry point serve the input root interface - */ - static Input::Root input_root(&ep, env()->heap()); - env()->parent()->announce(ep.manage(&input_root)); + env()->parent()->announce(ep.manage(&root)); Genode::sleep_forever(); return 0; diff --git a/repos/os/src/server/loader/input.h b/repos/os/src/server/loader/input.h index 76ab5d4b1..762a9b7d5 100644 --- a/repos/os/src/server/loader/input.h +++ b/repos/os/src/server/loader/input.h @@ -66,11 +66,11 @@ namespace Input { ** Input session interface ** *****************************/ - Dataspace_capability dataspace() { return _real_input.dataspace(); } + Dataspace_capability dataspace() override { return _real_input.dataspace(); } - bool is_pending() const { return _real_input.is_pending(); } + bool is_pending() const override { return _real_input.is_pending(); } - int flush() + int flush() override { /* translate mouse position to child's coordinate system */ Transformer::Delta delta = _transformer.delta(); @@ -97,6 +97,11 @@ namespace Input { return num_ev; } + + void sigh(Signal_context_capability sigh) override + { + _real_input.sigh(sigh); + } }; } diff --git a/repos/os/src/server/nit_fb/main.cc b/repos/os/src/server/nit_fb/main.cc index b1bc2e59d..8631b5af8 100644 --- a/repos/os/src/server/nit_fb/main.cc +++ b/repos/os/src/server/nit_fb/main.cc @@ -82,11 +82,11 @@ namespace Input { ** Input session interface ** *****************************/ - Genode::Dataspace_capability dataspace() { return _to_input_ds; } + Genode::Dataspace_capability dataspace() override { return _to_input_ds; } - bool is_pending() const { return _from_input->is_pending(); } + bool is_pending() const override { return _from_input->is_pending(); } - int flush() + int flush() override { /* flush events at input session */ int num_events = _from_input->flush(); @@ -103,6 +103,11 @@ namespace Input { } return num_events; } + + void sigh(Genode::Signal_context_capability sigh) override + { + _from_input->sigh(sigh); + } }; } diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index d161d0fc8..3ff257fcc 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -257,8 +257,19 @@ class Input::Session_component : public Genode::Rpc_object Event _ev_buf[MAX_EVENTS]; unsigned _num_ev = 0; + Signal_context_capability _sigh; + public: + /** + * Wake up client + */ + void submit_signal() + { + if (_sigh.valid()) + Signal_transmitter(_sigh).submit(); + } + /** * Enqueue event into local event buffer of the input session */ @@ -269,6 +280,8 @@ class Input::Session_component : public Genode::Rpc_object /* insert event into local event buffer */ _ev_buf[_num_ev++] = *ev; + + submit_signal(); } @@ -276,11 +289,11 @@ class Input::Session_component : public Genode::Rpc_object ** Input session interface ** *****************************/ - Dataspace_capability dataspace() { return _ev_ram_ds.cap(); } + Dataspace_capability dataspace() override { return _ev_ram_ds.cap(); } - bool is_pending() const { return _num_ev > 0; } + bool is_pending() const override { return _num_ev > 0; } - int flush() + int flush() override { unsigned ev_cnt; @@ -292,6 +305,8 @@ class Input::Session_component : public Genode::Rpc_object _num_ev = 0; return ev_cnt; } + + void sigh(Genode::Signal_context_capability sigh) override { _sigh = sigh; } }; diff --git a/repos/qt4/src/app/qt_avplay/avplay_policy.h b/repos/qt4/src/app/qt_avplay/avplay_policy.h index 1bcb30df9..958938275 100644 --- a/repos/qt4/src/app/qt_avplay/avplay_policy.h +++ b/repos/qt4/src/app/qt_avplay/avplay_policy.h @@ -54,6 +54,25 @@ class Avplay_policy : public QObject, public Genode::Slave_policy arg1_node.setAttribute("value", _mediafile); config_node.appendChild(arg1_node); + /* + * Configure libc of avplay to direct output to LOG and to obtain + * the mediafile from ROM. + */ + QDomElement libc_node = config_doc.createElement("libc"); + libc_node.setAttribute("stdout", "/dev/log"); + libc_node.setAttribute("stderr", "/dev/log"); + QDomElement libc_vfs_node = config_doc.createElement("vfs"); + QDomElement libc_vfs_dev_node = config_doc.createElement("dir"); + libc_vfs_dev_node.setAttribute("name", "dev"); + QDomElement libc_vfs_dev_log_node = config_doc.createElement("log"); + libc_vfs_dev_node.appendChild(libc_vfs_dev_log_node); + libc_vfs_node.appendChild(libc_vfs_dev_node); + QDomElement libc_vfs_mediafile_node = config_doc.createElement("rom"); + libc_vfs_mediafile_node.setAttribute("name", "mediafile"); + libc_vfs_node.appendChild(libc_vfs_mediafile_node); + libc_node.appendChild(libc_vfs_node); + config_node.appendChild(libc_node); + QDomElement sdl_audio_volume_node = config_doc.createElement("sdl_audio_volume"); sdl_audio_volume_node.setAttribute("value", QString::number(_sdl_audio_volume)); config_node.appendChild(sdl_audio_volume_node); diff --git a/repos/qt4/src/app/qt_avplay/control_bar.cpp b/repos/qt4/src/app/qt_avplay/control_bar.cpp index 2fb88fc6d..d40eff97c 100644 --- a/repos/qt4/src/app/qt_avplay/control_bar.cpp +++ b/repos/qt4/src/app/qt_avplay/control_bar.cpp @@ -17,22 +17,22 @@ /* Qoost includes */ #include -#include "input_service.h" +/* local includes */ #include "main_window.h" void Control_bar::_rewind() { /* mouse click at horizontal position 0 */ - ev_queue.add(Input::Event(Input::Event::PRESS, Input::BTN_LEFT, 0, 0, 0, 0)); - ev_queue.add(Input::Event(Input::Event::RELEASE, Input::BTN_LEFT, 0, 0, 0, 0)); + _event_queue.add(Input::Event(Input::Event::PRESS, Input::BTN_LEFT, 0, 0, 0, 0)); + _event_queue.add(Input::Event(Input::Event::RELEASE, Input::BTN_LEFT, 0, 0, 0, 0)); } void Control_bar::_pause_resume() { - ev_queue.add(Input::Event(Input::Event::PRESS, Input::KEY_SPACE, 0, 0, 0, 0)); - ev_queue.add(Input::Event(Input::Event::RELEASE, Input::KEY_SPACE, 0, 0, 0, 0)); + _event_queue.add(Input::Event(Input::Event::PRESS, Input::KEY_SPACE, 0, 0, 0, 0)); + _event_queue.add(Input::Event(Input::Event::RELEASE, Input::KEY_SPACE, 0, 0, 0, 0)); _playing = !_playing; if (_playing) @@ -51,8 +51,9 @@ void Control_bar::_stop() } -Control_bar::Control_bar() -: _playing(true) +Control_bar::Control_bar(Input::Event_queue &event_queue) +: + _event_queue(event_queue), _playing(true) { update_style_id(_play_pause_button, "play"); diff --git a/repos/qt4/src/app/qt_avplay/control_bar.h b/repos/qt4/src/app/qt_avplay/control_bar.h index f4420ebe9..6bb9af57b 100644 --- a/repos/qt4/src/app/qt_avplay/control_bar.h +++ b/repos/qt4/src/app/qt_avplay/control_bar.h @@ -21,6 +21,9 @@ #include #include +/* Genode includes */ +#include + struct Play_pause_button : QPushButton { Q_OBJECT }; struct Stop_button : QPushButton { Q_OBJECT }; struct Volume_label : QLabel { Q_OBJECT }; @@ -32,6 +35,8 @@ class Control_bar : public Compound_widget private: + Input::Event_queue &_event_queue; + QMember _play_pause_button; QMember _stop_button; QMember _volume_label; @@ -48,7 +53,7 @@ class Control_bar : public Compound_widget public: - Control_bar(); + Control_bar(Input::Event_queue &event_queue); Q_SIGNALS: diff --git a/repos/qt4/src/app/qt_avplay/input_service.cpp b/repos/qt4/src/app/qt_avplay/input_service.cpp deleted file mode 100644 index 65bb5a5c4..000000000 --- a/repos/qt4/src/app/qt_avplay/input_service.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * \brief Input service - * \author Christian Prochaska - * \date 2012-03-29 - */ - -/* - * 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 - -#include "input_service.h" - -using namespace Genode; - -Event_queue ev_queue; - - -namespace Input { - - /* - * Event handling is disabled on queue creation and will be enabled later if a - * session is created. - */ - void event_handling(bool enable) - { - if (enable) - ev_queue.enable(); - else - ev_queue.disable(); - } - - bool event_pending() { return !ev_queue.empty(); } - Event get_event() { return ev_queue.get(); } -} diff --git a/repos/qt4/src/app/qt_avplay/input_service.h b/repos/qt4/src/app/qt_avplay/input_service.h deleted file mode 100644 index 7612f2699..000000000 --- a/repos/qt4/src/app/qt_avplay/input_service.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * \brief Input service - * \author Christian Prochaska - * \date 2012-03-29 - */ - -/* - * 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 - -extern Event_queue ev_queue; - -extern void create_input_service(); - -#endif /* _INPUT_SERVICE_H_ */ diff --git a/repos/qt4/src/app/qt_avplay/main.cpp b/repos/qt4/src/app/qt_avplay/main.cpp index 84a751adf..de37c2a27 100644 --- a/repos/qt4/src/app/qt_avplay/main.cpp +++ b/repos/qt4/src/app/qt_avplay/main.cpp @@ -17,6 +17,11 @@ /* qt_avplay includes */ #include "main_window.h" +/* Genode includes */ +#include +#include +#include + static inline void load_stylesheet() { @@ -37,6 +42,14 @@ int main(int argc, char *argv[]) load_stylesheet(); + /* look for dynamic linker */ + try { + static Genode::Rom_connection ldso_rom("ld.lib.so"); + Genode::Process::dynamic_linker(ldso_rom.dataspace()); + } catch (...) { + PERR("ld.lib.so not found"); + } + QMember main_window; main_window->show(); diff --git a/repos/qt4/src/app/qt_avplay/main_window.cpp b/repos/qt4/src/app/qt_avplay/main_window.cpp index 163dd9ded..1659206aa 100644 --- a/repos/qt4/src/app/qt_avplay/main_window.cpp +++ b/repos/qt4/src/app/qt_avplay/main_window.cpp @@ -11,17 +11,10 @@ * under the terms of the GNU General Public License version 2. */ -/* Genode includes */ -#include -#include -#include -#include - /* qt_avplay includes */ #include "avplay_policy.h" #include "filter_framebuffer_policy.h" #include "framebuffer_root.h" -#include "input_service.h" #include "main_window.h" @@ -30,49 +23,23 @@ using namespace Genode; struct Framebuffer_filter { - enum { MAX_FILTER_NAME_SIZE = 32 }; - char name[MAX_FILTER_NAME_SIZE]; - Genode::Number_of_bytes ram_quota; + enum { MAX_FILTER_NAME_SIZE = 32 }; + char name[MAX_FILTER_NAME_SIZE]; + Genode::Number_of_bytes ram_quota; - Service_registry *framebuffer_out_registry; - Rpc_entrypoint *ep; - Filter_framebuffer_policy *policy; - Slave *slave; + Service_registry *framebuffer_out_registry; + Rpc_entrypoint *ep; + Filter_framebuffer_policy *policy; + Slave *slave; }; Main_window::Main_window() +: + _control_bar(_input_session.event_queue()) { - /* look for dynamic linker */ - - try { - static Rom_connection ldso_rom("ld.lib.so"); - Process::dynamic_linker(ldso_rom.dataspace()); - } catch (...) { - PERR("ld.lib.so not found"); - } - - /* get the name of the media file from the config file */ - enum { MAX_LEN_MEDIAFILE_NAME = 256 }; - static char mediafile[MAX_LEN_MEDIAFILE_NAME] = "mediafile"; - try { - config()->xml_node().sub_node("mediafile").attribute("name").value(mediafile, sizeof(mediafile)); - } catch(...) { - PWRN("no config node found, using \"mediafile\""); - } - - /* create local services */ - - enum { STACK_SIZE = 2*sizeof(addr_t)*1024 }; - static Cap_connection cap; - static Rpc_entrypoint avplay_ep(&cap, STACK_SIZE, "avplay_ep"); - static Service_registry input_registry; - static Service_registry nitpicker_framebuffer_registry; - - static Input::Root input_root(&avplay_ep, env()->heap()); - static Local_service input_service(Input::Session::service_name(), &input_root); - input_registry.insert(&input_service); - avplay_ep.manage(&input_root); + _input_registry.insert(&_input_service); + _ep.manage(&_input_root); /* find out which filtering framebuffer services to start and sort them in reverse order */ @@ -90,15 +57,15 @@ Main_window::Main_window() /* start the filtering framebuffer services */ - Service_registry *framebuffer_in_registry = &nitpicker_framebuffer_registry; + Service_registry *framebuffer_in_registry = &_nitpicker_framebuffer_registry; Q_FOREACH(Framebuffer_filter *framebuffer_filter, framebuffer_filters) { framebuffer_filter->framebuffer_out_registry = new Service_registry; - framebuffer_filter->ep = new Rpc_entrypoint(&cap, STACK_SIZE, "filter_fb_ep"); + framebuffer_filter->ep = new Rpc_entrypoint(&_cap, STACK_SIZE, "filter_fb_ep"); framebuffer_filter->policy = new Filter_framebuffer_policy(framebuffer_filter->name, *framebuffer_filter->ep, - *framebuffer_in_registry, - *framebuffer_filter->framebuffer_out_registry); + *framebuffer_in_registry, + *framebuffer_filter->framebuffer_out_registry); framebuffer_filter->slave = new Slave(*framebuffer_filter->ep, *framebuffer_filter->policy, framebuffer_filter->ram_quota); @@ -106,17 +73,17 @@ Main_window::Main_window() } Rpc_entrypoint *local_framebuffer_ep = framebuffer_filters.isEmpty() ? - &avplay_ep : + &_ep : framebuffer_filters.at(0)->ep; static Framebuffer::Root framebuffer_root(local_framebuffer_ep, env()->heap(), *_avplay_widget, 640, 480); static Local_service framebuffer_service(Framebuffer::Session::service_name(), &framebuffer_root); - nitpicker_framebuffer_registry.insert(&framebuffer_service); + _nitpicker_framebuffer_registry.insert(&framebuffer_service); /* start avplay */ - static Avplay_policy avplay_policy(avplay_ep, input_registry, *framebuffer_in_registry, mediafile); - static Genode::Slave avplay_slave(avplay_ep, avplay_policy, 32*1024*1024); + static Avplay_policy avplay_policy(_ep, _input_registry, *framebuffer_in_registry, _mediafile_name.buf); + static Genode::Slave avplay_slave(_ep, avplay_policy, 32*1024*1024); /* add widgets to layout */ diff --git a/repos/qt4/src/app/qt_avplay/main_window.h b/repos/qt4/src/app/qt_avplay/main_window.h index aaf869922..0b10b58cd 100644 --- a/repos/qt4/src/app/qt_avplay/main_window.h +++ b/repos/qt4/src/app/qt_avplay/main_window.h @@ -23,6 +23,14 @@ #include #include +/* Genode includes */ +#include +#include +#include +#include +#include + +/* local includes */ #include "control_bar.h" @@ -32,6 +40,35 @@ class Main_window : public Compound_widget private: + struct Mediafile_name + { + /* get the name of the media file from the config file */ + enum { MAX_LEN_MEDIAFILE_NAME = 256 }; + char buf[MAX_LEN_MEDIAFILE_NAME]; + + Mediafile_name() + { + Genode::strncpy(buf, "mediafile", sizeof(buf)); + try { + Genode::config()->xml_node().sub_node("mediafile") + .attribute("name").value(buf, sizeof(buf)); + } catch(...) { + PWRN("no config node found, using \"mediafile\""); + } + } + } _mediafile_name; + + enum { STACK_SIZE = 2*sizeof(Genode::addr_t)*1024 }; + Genode::Cap_connection _cap; + Genode::Rpc_entrypoint _ep { &_cap, STACK_SIZE, "avplay_ep" }; + Genode::Service_registry _input_registry; + Genode::Service_registry _nitpicker_framebuffer_registry; + + Input::Session_component _input_session; + Input::Root_component _input_root { _ep, _input_session }; + + Genode::Local_service _input_service { Input::Session::service_name(), &_input_root }; + QMember _avplay_widget; QMember _control_bar; diff --git a/repos/qt4/src/app/qt_avplay/qt_avplay.pro b/repos/qt4/src/app/qt_avplay/qt_avplay.pro index 8b9dc41c5..5c2c7d9d1 100644 --- a/repos/qt4/src/app/qt_avplay/qt_avplay.pro +++ b/repos/qt4/src/app/qt_avplay/qt_avplay.pro @@ -6,7 +6,6 @@ HEADERS = avplay_policy.h \ main_window.h SOURCES = control_bar.cpp \ framebuffer_session_component.cc \ - input_service.cpp \ main.cpp \ main_window.cpp RESOURCES = style.qrc diff --git a/repos/qt4/src/app/qt_avplay/target.mk b/repos/qt4/src/app/qt_avplay/target.mk index d60ce481b..6515e9be5 100644 --- a/repos/qt4/src/app/qt_avplay/target.mk +++ b/repos/qt4/src/app/qt_avplay/target.mk @@ -6,4 +6,4 @@ include $(QT4_REP_DIR)/src/app/tmpl/target_defaults.inc include $(QT4_REP_DIR)/src/app/tmpl/target_final.inc -LIBS += qnitpickerviewwidget +LIBS += qnitpickerviewwidget qoost