# HG changeset patch # User Paul Boddie # Date 1526590175 -7200 # Node ID 1a7de85ab0cef3d4c93bbaea7e1acee3eda9460f # Parent 527946fba4a1e6d15d1c0ebd54b9f30a39fdd572 Added initial input event server support together with an example. diff -r 527946fba4a1 -r 1a7de85ab0ce conf/landfall-examples/mips-qi_lb60-input-event-client.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-qi_lb60-input-event-client.cfg Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,155 @@ +-- vim: ft=lua ts=2 et sw=2 + +-- Start Mag to multiplex the framebuffer showing only a single program. +-- This example shows the key values produced by the input event driver. +-- The target platform is the Ben NanoNote. + +local L4 = require("L4"); + +local l = L4.default_loader; + +-- Define general access to peripherals. + +local io_buses = { + cpm = l:new_channel(); + gpio = l:new_channel(); + lcd = l:new_channel(); + }; + +l:start({ + caps = { + cpm = io_buses.cpm:svr(), + gpio = io_buses.gpio:svr(), + lcd = io_buses.lcd:svr(), + + icu = L4.Env.icu, + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0), + }, + }, + "rom/io rom/hw_devices.io rom/mips-qi_lb60-input-event-client.io"); + +-- Expose a SPI peripheral as a device. + +local spi = l:new_channel(); + +l:startv({ + caps = { + vbus = io_buses.gpio, + spi = spi:svr(), + }, + }, + "rom/dev_spi_jz4740", "C23", "C22", "C21"); -- specifying clock, data, enable pin details + +-- Expose a SPI backlight device for the Ben. + +local backlight = l:new_channel(); -- exposes backlight device + +l:start({ + caps = { + spi = spi, + backlight = backlight:svr(), + }, + }, + "rom/dev_backlight_spi_qi_lb60"); + +-- Expose a display device for the Ben. + +local display = l:new_channel(); -- exposes display device + +l:start({ + caps = { + backlight = backlight, + display = display:svr(), + vbus = io_buses.gpio, + }, + }, + "rom/dev_display_qi_lb60"); + +-- Expose a panel definition for the Ben. + +local panel = l:new_channel(); -- exposes panel + +l:start({ + caps = { + panel = panel:svr(), + }, + }, + "rom/dev_panel_qi_lb60"); + +-- Expose the CPM peripheral. + +local cpm = l:new_channel(); + +l:start({ + caps = { + vbus = io_buses.cpm, + cpm = cpm:svr(), + }, + }, + "rom/dev_cpm_jz4740"); + +-- Expose a framebuffer device. + +local fbdrv_fb = l:new_channel(); + +l:start({ + caps = { + vbus = io_buses.lcd, + fb = fbdrv_fb:svr(), + cpm = cpm, + display = display, -- needed by LCD driver + panel = panel, + }, + }, + "rom/fb-drv"); + +-- Multiplex the framebuffer. + +local mag_caps = { + mag = l:new_channel(), + svc = l:new_channel(), + }; + +l:start({ + caps = { + vbus = io_buses.gpio, -- needed by input driver + fb = fbdrv_fb, + mag = mag_caps.mag:svr(), + svc = mag_caps.svc:svr(), + }, + }, + "rom/mag"); + +-- Expose the keypad matrix. + +local keypad = l:new_channel(); + +l:start({ + caps = { + vbus = io_buses.gpio, + keypad = keypad:svr(), + }, + }, + "rom/dev_keypad_qi_lb60"); + +-- Expose the keypad events. + +local ev = l:new_channel(); + +l:start({ + caps = { + keypad = keypad, + ev = ev:svr(), + }, + }, + "rom/dev_input_keypad_qi_lb60"); + +-- Show key event values. + +l:startv({ + caps = { + fb = mag_caps.svc:create(L4.Proto.Goos, "g=320x230+0+0", "barheight=10"), + ev = ev, + }, + }, + "rom/ex_input_event_client", "chars"); diff -r 527946fba4a1 -r 1a7de85ab0ce conf/landfall-examples/mips-qi_lb60-input-event-client.io --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-qi_lb60-input-event-client.io Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,20 @@ +-- vim: ft=lua ts=2 et sw=2 + +-- Configuration file for Io. + +local hw = Io.system_bus() + +Io.add_vbus("cpm", Io.Vi.System_bus +{ + CPM = wrap(hw:match("jz4740-cpm")); +}) + +Io.add_vbus("gpio", Io.Vi.System_bus +{ + GPIO = wrap(hw:match("jz4740-gpio")); +}) + +Io.add_vbus("lcd", Io.Vi.System_bus +{ + LCD = wrap(hw:match("jz4740-lcd")); +}) diff -r 527946fba4a1 -r 1a7de85ab0ce conf/landfall-examples/mips-qi_lb60-input-event-client.list --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-qi_lb60-input-event-client.list Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,23 @@ + +modaddr 0x1100000 + +entry mips-qi_lb60-input-event-client-example +bootstrap bootstrap -serial +kernel fiasco -serial_esc +roottask moe rom/mips-qi_lb60-input-event-client.cfg +module mips-qi_lb60-input-event-client.cfg +module mips-qi_lb60-input-event-client.io +module plat-qi_lb60/hw_devices.io +module l4re +module io +module ned +module fb-drv +module mag +module dev_spi_jz4740 +module dev_backlight_spi_qi_lb60 +module dev_display_qi_lb60 +module dev_panel_qi_lb60 +module dev_cpm_jz4740 +module dev_keypad_qi_lb60 +module dev_input_keypad_qi_lb60 +module ex_input_event_client diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/Control --- a/pkg/devices/Control Mon May 14 19:16:59 2018 +0200 +++ b/pkg/devices/Control Thu May 17 22:49:35 2018 +0200 @@ -11,6 +11,7 @@ provides: libdevice-fb-client libdevice-fb-ops provides: libdevice-fb-lcd libdevice-fb-server provides: libdevice-input-keypad +provides: libdevice-input-event-client libdevice-input-event-ops provides: devices-keypad-letux400 devices-keypad-qi_lb60 provides: libdevice-keypad-client libdevice-keypad-ops provides: libdevice-keypad-server diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/include/Makefile --- a/pkg/devices/input/include/Makefile Mon May 14 19:16:59 2018 +0200 +++ b/pkg/devices/input/include/Makefile Thu May 17 22:49:35 2018 +0200 @@ -1,6 +1,6 @@ PKGDIR = ../.. L4DIR ?= $(PKGDIR)/../.. -PC_FILENAME := libdevice-input-ops +PC_FILENAME := libdevice-input-event-ops include $(L4DIR)/mk/include.mk diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/include/input-event-client.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/include/input-event-client.h Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,39 @@ +/* + * Input event client to access input event servers. + * + * (c) 2018 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#ifdef __cplusplus + +#include +#include +#include + +class Input_event_interface : public L4::Kobject_t +{ + L4_KOBJECT(Input_event_interface) + +public: + int get_buffer(L4::Cap mem) throw(); + int bind(unsigned irqnum, L4::Cap irq) throw(); +}; + +#endif diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/include/input-event-loop.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/include/input-event-loop.h Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,88 @@ +/* + * Input event loop functionality. + * + * (c) 2018 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#ifdef __cplusplus + +#include +#include +#include + +#include +#include + +/* POSIX-thread-compatible handler function type. */ + +typedef void (*Event_handler)(L4Re::Event_buffer::Event &, void *); + +/* Input event loop abstraction. */ + +class Input_event_loop +{ + /* Notification interrupt capability. */ + + L4::Cap _irq; + + /* External handler function. */ + + Event_handler _handler; + + /* Private data for the handler. */ + + void *_priv; + + /* Event buffer and notification interrupt capability. */ + + L4Re::Event_buffer _event_buffer; + + /* Thread properties. */ + + int _priority; + pthread_t _pthread; + +public: + /* Initialise the event loop with a notification interrupt, thread priority, + event handler function and private data, and an event buffer. */ + + explicit Input_event_loop(L4::Cap irq, + Event_handler handler, void *priv, + L4Re::Event_buffer event_buffer, + int priority=0x20) + : _irq(irq), _handler(handler), _priv(priv), _event_buffer(event_buffer), + _priority(priority) + { + } + + /* Static main loop function for event-handling thread. */ + + static void *event_loop(void *data); + + /* Event handler method. */ + + void handle(); + + /* Initiation function. */ + + void start(); +}; + +#endif diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/include/input-event-ops.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/include/input-event-ops.h Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,24 @@ +/* + * Input event server operations. + * + * (c) 2018 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +enum { Input_event_op_get_buffer, Input_event_op_bind }; diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/include/input-event-server.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/include/input-event-server.h Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,61 @@ +/* + * Common input event server functionality. + * + * (c) 2018 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#ifdef __cplusplus + +#include +#include +#include +#include +#include +#include + +/* Server object to provide input event source access. */ + +class Input_event_server : public L4::Server_object_t +{ +private: + L4::Cap _mem; + L4::Cap _irq; + L4Re::Event_buffer _events; + +public: + /* Initialise the server with a capability referencing the exported memory + and an event buffer through which events will be communicated. */ + + explicit Input_event_server(L4::Cap mem, L4::Cap irq, + L4Re::Event_buffer events) + : _mem(mem), _irq(irq), _events(events) + { + } + + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios); + + /* Event sending methods. */ + + void send_event(int type, int code, int value); +}; + +#endif + +int run(void); diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/src/Makefile --- a/pkg/devices/input/src/Makefile Mon May 14 19:16:59 2018 +0200 +++ b/pkg/devices/input/src/Makefile Thu May 17 22:49:35 2018 +0200 @@ -1,6 +1,10 @@ PKGDIR ?= ../.. L4DIR ?= $(PKGDIR)/../.. -TARGET := keypad +TARGET := client keypad letux400 qi_lb60 server include $(L4DIR)/mk/subdir.mk + +letux400: server +qi_lb60: server +server: keypad diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/src/client/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/src/client/Makefile Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,13 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libdevice_input_event_client.o.a +PC_FILENAME := libdevice-input-event-client + +SRC_CC := input-event-client.cc input-event-loop.cc + +PRIVATE_INCDIR += $(PKGDIR)/input/include + +REQUIRES_LIBS := l4re_c l4re_c-util + +include $(L4DIR)/mk/lib.mk diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/src/client/input-event-client.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/src/client/input-event-client.cc Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,52 @@ +/* + * Input event client to access input event servers. + * + * (c) 2018 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "input-event-client.h" +#include "input-event-ops.h" + +int +Input_event_interface::get_buffer(L4::Cap mem) throw() +{ + L4::Ipc::Iostream s(l4_utcb()); + + /* Send a "receive item" for requesting a capability. */ + + s << L4::Ipc::Small_buf(mem); + + return l4_error(s.call(cap(), Input_event_op_get_buffer)); +} + +int +Input_event_interface::bind(unsigned irqnum, L4::Cap irq) throw() +{ + L4::Ipc::Iostream s(l4_utcb()); + + s << irqnum; + + /* Send a "receive item" for requesting a capability. */ + + s << L4::Ipc::Small_buf(irq); + + return l4_error(s.call(cap(), Input_event_op_bind)); +} diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/src/client/input-event-loop.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/src/client/input-event-loop.cc Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,81 @@ +/* + * Input event loop functionality. + * + * (c) 2018 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include +#include + +#include + +/* Main loop for event threads. */ + +void * +Input_event_loop::event_loop(void *data) +{ + Input_event_loop *self = reinterpret_cast(data); + + while (1) self->handle(); + + return 0; +} + +/* Handler for incoming interrupts signalling the presence of events. */ + +void +Input_event_loop::handle() +{ + L4Re::Event_buffer::Event *event; + + if (!l4_error(_irq->receive())) + { + while ((event = _event_buffer.next())) + { + _handler(*event, _priv); + event->free(); + } + } +} + +/* Event loop initiation. */ + +void +Input_event_loop::start() +{ + pthread_attr_t thread_attr; + struct sched_param sp; + + /* Thread initialisation boilerplate. */ + + if (pthread_attr_init(&thread_attr)) + return; + + sp.sched_priority = _priority; + pthread_attr_setschedparam(&thread_attr, &sp); + pthread_attr_setschedpolicy(&thread_attr, SCHED_L4); + pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED); + + /* Provide this instance as the private data. */ + + pthread_create(&_pthread, &thread_attr, event_loop, this); + + _irq->bind_thread(Pthread::L4::cap(_pthread), 0xDEAD); +} diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/src/letux400/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/src/letux400/Makefile Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,13 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = dev_input_keypad_letux400 +PC_FILENAME := devices-input-keypad-letux400 + +SRC_CC := input-keypad-letux400.cc + +PRIVATE_INCDIR += $(PKGDIR)/input/include + +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-input-keypad-server libdrivers-keypad-letux400 + +include $(L4DIR)/mk/prog.mk diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/src/letux400/input-keypad-letux400.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/src/letux400/input-keypad-letux400.cc Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,29 @@ +/* + * Export the keypad for the Letux 400 via the "ev" capability. + * + * (c) 2018 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "input-event-server.h" + +/* Main program. */ + +int main() +{ + return run(); +} diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/src/qi_lb60/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/src/qi_lb60/Makefile Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,13 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = dev_input_keypad_qi_lb60 +PC_FILENAME := devices-input-keypad-qi_lb60 + +SRC_CC := input-keypad-qi_lb60.cc + +PRIVATE_INCDIR += $(PKGDIR)/input/include + +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-input-keypad-server libdrivers-keypad-qi_lb60 + +include $(L4DIR)/mk/prog.mk diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/src/qi_lb60/input-keypad-qi_lb60.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/src/qi_lb60/input-keypad-qi_lb60.cc Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,29 @@ +/* + * Export the keypad for the Ben NanoNote via the "ev" capability. + * + * (c) 2018 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "input-event-server.h" + +/* Main program. */ + +int main() +{ + return run(); +} diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/src/server/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/src/server/Makefile Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,13 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libdevice_input_keypad_server.o.a +PC_FILENAME := libdevice-input-keypad-server + +SRC_CC := input-keypad-server.cc + +PRIVATE_INCDIR += $(PKGDIR)/input/include + +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-input-keypad libdevice-util + +include $(L4DIR)/mk/lib.mk diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/devices/input/src/server/input-keypad-server.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/input/src/server/input-keypad-server.cc Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,146 @@ +/* + * Provide access to keypad events on the configured device. + * + * (c) 2018 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include "input-event-client.h" +#include "input-event-server.h" +#include "input-event-ops.h" +#include "input-keypad-client.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Handle invocations. */ + +int +Input_event_server::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios) +{ + l4_msgtag_t tag; + + (void) obj; + ios >> tag; + + switch (tag.label()) + { + case L4::Meta::Protocol: + return L4::Util::handle_meta_request(ios); + + /* Reset the buffer state and return the buffer memory capability. */ + + case Input_event_op_get_buffer: + _events.reset(); + ios << _mem; + return L4_EOK; + + /* Just return the interrupt capability. */ + + case Input_event_op_bind: + ios << _irq; + return L4_EOK; + + default: + return -L4_EBADPROTO; + } +} + + + +/* Event sending methods. */ + +void +Input_event_server::send_event(int type, int code, int value) +{ + L4Re::Event_buffer::Event event; + + event.time = l4_kip_clock(l4re_kip()); + event.payload.stream_id = 0; + event.payload.type = type; + event.payload.code = code; + event.payload.value = value; + + /* Queue the event and trigger the interrupt. */ + + _events.put(event); + _irq->trigger(); +} + + + +static void handler(Input_event event, void *priv) +{ + Input_event_server *server = (Input_event_server *) priv; + + server->send_event(event.type, event.code, event.value); +} + + + +static L4Re::Util::Registry_server<> server; + + + +int run(void) +{ + Keypad *keypad = Keypad::get_keypad(); + Input_keypad_client client(keypad); + void *buffer; + + // Memory allocation capability for the event data. + + L4::Cap mem = allocate_data(L4_PAGESIZE, &buffer); + if (!mem.is_valid()) return 1; + + /* Obtain a capability for the interrupt. */ + + L4::Cap irq = L4Re::Util::cap_alloc.alloc(); + if (!irq.is_valid()) return 1; + + /* Create an interrupt object. */ + + if (l4_error(L4Re::Env::env()->factory()->create(irq))) return 1; + + // Event buffer for the data. + + L4Re::Event_buffer events(buffer, L4_PAGESIZE); + + // Initialise and register a server object. + + Input_event_server server_obj(mem, irq, events); + server.registry()->register_obj(&server_obj, "ev"); + + // Attach the event handler and wait for events. + + client.attach(handler, (void *) &server_obj); + + // Enter the IPC server loop. + + server.loop(); + return 0; +} diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/landfall-examples/input_event_client/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/input_event_client/Makefile Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,9 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = ex_input_event_client +SRC_CC = input_event_client.cc +SRC_DATA = unifont.tff +REQUIRES_LIBS = libio l4re_c-util mag-gfx libevent libdevice-input-event-client + +include $(L4DIR)/mk/prog.mk diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/landfall-examples/input_event_client/input_event_client.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/input_event_client/input_event_client.cc Thu May 17 22:49:35 2018 +0200 @@ -0,0 +1,303 @@ +/* + * Access an input device via a capability. + * + * (c) 2018 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + * + * + * Font definitions and licence (see unifont.tff for bitmap data derived from + * GNU Unifont's unifont.hex file): + * + * Copyright (C) 1998-2003 Roman Czyborra (http://czyborra.com/) + * + * All glyphs are released under the GNU General Public License + * (GPL) version 2 or (at your option) a later version, with the + * GNU font embedding exception: + * + * ** GPL v2.0 license with font embedding exception: + * + * As a special exception, if you create a document which + * uses this font, and embed this font or unaltered portions + * of this font into the document, this font does not by + * itself cause the resulting document to be covered by + * the GNU General Public License. This exception does not + * however invalidate any other reasons why the document + * might be covered by the GNU General Public License. + * If you modify this font, you may extend this exception + * to your version of the font, but you are not obligated + * to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +/* Video abstractions. */ + +static l4re_util_video_goos_fb_t gfb; +static l4re_video_view_info_t view_info; +static void *fb = 0; + +/* Bundled font data. */ + +extern char const _binary_unifont_tff_start[]; + +/* Screen abstractions. */ + +using namespace Mag_gfx; + +static Font *_font = 0; +static Canvas *_screen = 0; + + + +/* Factories for certain pixel formats. */ + +static Mem::Factory _rgb16; +static Mem::Factory _rgb32; + + + +/* Key to character conversion function. */ + +static const char *keys_to_strings[] = { + + 0, "Escape", "1", "2", "3", "4", "5", "6", "7", "8", + + "9", "0", "-", "=", "Backspace", "Tab", "Q", "W", "E", "R", + + "T", "Y", "U", "I", "O", "P", "[", "]", "Enter", "Left Ctrl", + + "A", "S", "D", "F", "G", "H", "J", "K", "L", ";", + + "'", "`", "Left Shift", "\\", "Z", "X", "C", "V", "B", "N", + + "M", ",", ".", "/", "Right Shift", "Keypad *", "Left Alt", "Space", + "Caps Lock", "F1", + + "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "Num Lock", + + "Scroll Lock", "Keypad 7", "Keypad 8", "Keypad 9", "Keypad -", "Keypad 4", + "Keypad 5", "Keypad 6", "Keypad +", "Keypad 1", + + "Keypad 2", "Keypad 3", "Keypad 0", "Keypad .", 0, 0, "#102", "F11", "F12", 0, + + 0, 0, 0, 0, 0, 0, "Keypad Enter", "Right Ctrl", "Keypad /", "SysRq", + + "Right Alt", "Line Feed", "Home", "Up", "Page Up", "Left", "Right", "End", + "Down", "Page Down", + + "Insert", "Delete", "Macro", "Mute", "Volume Down", "Volume Up", "Power", + "Keypad =", "Keypad +-", "Pause", +}; + +static const char null_string[] = "Unknown"; + +const int keys_to_strings_length = 120; + +static const char *key_to_string(int key) +{ + return key < keys_to_strings_length ? keys_to_strings[key] : 0; +} + + + +/* Show the keypad event status on the display. */ + +static uint8_t row = 0; +static uint32_t text_x = 0, text_y = 0, next_y = 0; + +static void handler(L4Re::Event_buffer::Event &event, void *priv) +{ + uint32_t colsize = view_info.width / 10, + rowsize = view_info.height / 20; + uint8_t column; + uint16_t mask; + + /* Convert the key code into a bit pattern. */ + + if (!priv) + { + for (column = 0, mask = (1 << 9); column < 10; column++, mask >>= 1) + _screen->draw_box(Rect(Point(column * colsize, row * rowsize), Area(colsize, rowsize)), + event.payload.code & mask ? event.payload.value ? Rgb32::Color(0, 255, 0) : Rgb32::Color(255, 0, 0) + : Rgb32::Color(0, 0, 0)); + + /* Advance to the next row, wrapping around. */ + + row = (row + 1) % 20; + } + + /* Or produce a string. */ + + else if (event.payload.value) + { + const char *s = ((const char *(*)(int)) priv)(event.payload.code); + Rgba32::Color col; + + if (!s) + { + s = null_string; + col = Rgba32::Color(255, 0, 0, Rgba32::Color::Amax); + } + else + col = Rgba32::Color(255, 255, 255, Rgba32::Color::Amax); + + Area box = _font->str_sz(s, strlen(s)); + + /* Test for enough space horizontally. */ + + if (text_x + box.w() > view_info.width) + { + text_x = 0; + text_y = next_y; + next_y = text_y + box.h(); + } + + /* Expand the line height, if appropriate. */ + + else if (text_y + box.h() > next_y) + next_y += box.h(); + + /* Test for enough space vertically. */ + + if (next_y > view_info.height) + { + text_x = 0; + text_y = 0; + next_y = box.h(); + } + + Point p(text_x, text_y); + + _screen->draw_box(Rect(p, box), Rgb32::Color(0, 0, 0)); + _screen->draw_string(p, _font, col, s, strlen(s)); + + /* Move to the next position. */ + + text_x += box.w(); + } + + /* Refresh the display. */ + + l4re_util_video_goos_fb_refresh(&gfb, 0, 0, view_info.width, view_info.height); +} + + + +/* Event buffer memory. */ + +static void *evmem = 0; + + + +/* Arguments: [ chars ] */ + +int main(int argc, char *argv[]) +{ + if (l4re_util_video_goos_fb_setup_name(&gfb, "fb")) + return 1; + + if (l4re_util_video_goos_fb_view_info(&gfb, &view_info)) + return 1; + + if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb))) + return 1; + + /* Obtain a canvas for the framebuffer. */ + + Factory *factory; + + if (view_info.pixel_info.bytes_per_pixel == 2) + factory = &_rgb16; + else + factory = &_rgb32; + + Canvas *screen = factory->create_canvas((void *) ((unsigned long) fb + view_info.buffer_offset), + Area(view_info.width, view_info.height), + view_info.bytes_per_line); + + Font font(&_binary_unifont_tff_start[0]); + + _screen = screen; + _font = &font; + + /* Obtain a reference to the event source. */ + + L4::Cap event_server = L4Re::Env::env()->get_cap("ev"); + if (!event_server.is_valid()) return 1; + + /* Obtain a capability for the event buffer. */ + + L4::Cap mem = L4Re::Util::cap_alloc.alloc(); + if (!mem.is_valid()) return 1; + + if (event_server->get_buffer(mem)) return 1; + + /* Attach the event buffer to this task. */ + + if (L4Re::Env::env()->rm()->attach(&evmem, mem->size(), L4Re::Rm::Search_addr, + L4::Ipc::make_cap_rw(mem))) + return 1; + + L4Re::Event_buffer event_buffer = L4Re::Event_buffer(evmem, mem->size()); + + /* Obtain an interrupt capability. */ + + L4::Cap irq = L4Re::Util::cap_alloc.alloc(); + if (!irq.is_valid()) return 1; + + /* Bind the interrupt to the event capability. */ + + if (event_server->bind(0, irq)) return 1; + + /* Private data for the handler function. */ + + void *priv = 0; + + if ((argc > 1) && (!strcmp(argv[1], "chars"))) + priv = (void *) key_to_string; + + /* Create an event handler and wait for events. */ + + Input_event_loop loop(irq, handler, priv, event_buffer); + + loop.start(); + l4_sleep_forever(); + + return 0; +} diff -r 527946fba4a1 -r 1a7de85ab0ce pkg/landfall-examples/input_event_client/unifont.tff Binary file pkg/landfall-examples/input_event_client/unifont.tff has changed