Landfall

pkg/landfall-examples/keypad_ds_client/keypad_ds_client_c.c

147:3d05f2d33524
17 months ago Paul Boddie Tidied and slightly improved the instructions. l4re-git-distribution
     1 /*     2  * Display the keypad matrix using the specified dimensions.     3  *     4  * Copyright (C) 2018, 2023 Paul Boddie <paul@boddie.org.uk>     5  *     6  * This program is free software; you can redistribute it and/or     7  * modify it under the terms of the GNU General Public License as     8  * published by the Free Software Foundation; either version 2 of     9  * the License, or (at your option) any later version.    10  *    11  * This program is distributed in the hope that it will be useful,    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    14  * GNU General Public License for more details.    15  *    16  * You should have received a copy of the GNU General Public License    17  * along with this program; if not, write to the Free Software    18  * Foundation, Inc., 51 Franklin Street, Fifth Floor,    19  * Boston, MA  02110-1301, USA    20  */    21     22 #include <l4/devices/keypad-ops.h>    23     24 #include <l4/re/c/rm.h>    25 #include <l4/re/c/util/cap_alloc.h>    26 #include <l4/re/env.h>    27 #include <l4/util/util.h>    28 #include <l4/sys/ipc.h>    29     30 #include <l4/re/c/util/video/goos_fb.h>    31 #include <l4/re/c/video/view.h>    32     33 #include <stdio.h>    34 #include <unistd.h>    35 #include <stdint.h>    36 #include <stdlib.h>    37     38 /* Video abstractions. */    39     40 static l4re_util_video_goos_fb_t gfb;    41 static l4re_video_view_info_t fbi;    42 static void *fb;    43     44 /* Keypad status and dimensions. */    45     46 uint32_t *keypad = 0;    47 void *keymem = 0;    48 int columns, rows;    49     50     51     52 static uint32_t bitmask(uint32_t size)    53 {    54   return (1 << size) - 1;    55 }    56     57 static uint32_t truncate_channel(uint32_t value, uint32_t size)    58 {    59   return (value >> (8 - size)) & bitmask(size);    60 }    61     62 static void set_pixel(uint32_t pos, uint8_t bpp, uint32_t value)    63 {    64   if (bpp <= 8) *(uint8_t *) pos = value;    65   else if (bpp <= 16) *(uint16_t *) pos = value;    66   else *(uint32_t *) pos = value;    67 }    68     69 /* Show the state of a key on the display. */    70     71 static void show_keystate(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t rgb)    72 {    73   uint8_t bpp = l4re_video_bits_per_pixel(&fbi.pixel_info);    74   uint8_t bytes_per_pixel = fbi.pixel_info.bytes_per_pixel;    75   uint32_t bytes_per_line = fbi.bytes_per_line;    76   uint32_t pos;    77   uint32_t col, row;    78     79   rgb = (truncate_channel(rgb >> 16, fbi.pixel_info.r.size) << fbi.pixel_info.r.shift) |    80         (truncate_channel(rgb >> 8, fbi.pixel_info.g.size) << fbi.pixel_info.g.shift) |    81         (truncate_channel(rgb, fbi.pixel_info.b.size) << fbi.pixel_info.b.shift);    82     83   for (row = 0; row < h; row++)    84   {    85     pos = (uint32_t) fb + (y + row) * bytes_per_line + x * bytes_per_pixel;    86     87     for (col = 0; col < w; col++)    88     {    89       set_pixel(pos, bpp, rgb);    90       pos += bytes_per_pixel;    91     }    92   }    93 }    94     95 /* Show the keypad status on the display. */    96     97 static void show_keypad(void)    98 {    99   uint32_t colsize = fbi.width / columns,   100            rowsize = fbi.height / rows;   101   uint8_t column, row;   102   uint32_t mask;   103    104   for (column = 0; column < columns; column++)   105    106     for (row = 0, mask = 1 << (rows - 1);   107          row < rows;   108          row++, mask >>= 1)   109    110       show_keystate(column * colsize, row * rowsize, colsize, rowsize,   111                     keypad[column] & mask ? 0xffffff : 0);   112    113   /* Refresh the display. */   114    115   l4re_util_video_goos_fb_refresh(&gfb, 0, 0, fbi.width, fbi.height);   116 }   117    118    119    120 int main(int argc, char *argv[])   121 {   122   l4_cap_idx_t keypad_server;   123   l4re_ds_t mem;   124   l4_msgtag_t tag;   125    126   /* Obtain the keypad matrix dimensions. */   127    128   if (argc < 3)   129     return 1;   130    131   columns = atoi(argv[1]);   132   rows = atoi(argv[2]);   133    134   if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))   135     return 1;   136    137   if (l4re_util_video_goos_fb_view_info(&gfb, &fbi))   138     return 1;   139    140   if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb)))   141     return 1;   142    143   /* Obtain a reference to the keypad. */   144    145   keypad_server = l4re_env_get_cap("keypad");   146   if (l4_is_invalid_cap(keypad_server)) return 1;   147    148   /* Obtain a capability for the keypad data. */   149    150   mem = l4re_util_cap_alloc();   151   if (l4_is_invalid_cap(mem)) return 1;   152    153   /* Obtain a reference to the keypad data. */   154    155   l4_utcb_br()->bdr = 0;   156   l4_utcb_br()->br[0] = L4_RCV_ITEM_SINGLE_CAP | mem;   157    158   tag = l4_ipc_call(keypad_server, l4_utcb(),   159                     l4_msgtag(Keypad_op_get_keypad_data, 0, 0, 0), /* zero words, zero *sent* items */   160                     L4_IPC_NEVER);   161    162   if (l4_ipc_error(tag, l4_utcb())) return 1;   163    164   /* Attach the keypad data to a region in this task. */   165    166   if (l4re_rm_attach(&keymem, l4re_ds_size(mem),   167                      L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_R,   168                      mem, 0,   169                      L4_PAGESHIFT))   170     return 1;   171    172   /* Show the keypad state. */   173    174   keypad = (uint32_t *) keymem;   175    176   while (1) show_keypad();   177    178   return 0;   179 }