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-client.h> 23 24 #include <l4/cxx/ipc_server> 25 #include <l4/re/dataspace> 26 #include <l4/re/env> 27 #include <l4/re/rm> 28 #include <l4/re/util/cap_alloc> 29 30 #include <l4/re/c/util/video/goos_fb.h> 31 #include <l4/re/c/video/view.h> 32 33 #include <l4/util/util.h> 34 #include <stdio.h> 35 #include <unistd.h> 36 #include <stdint.h> 37 #include <stdlib.h> 38 39 /* Video abstractions. */ 40 41 static l4re_util_video_goos_fb_t gfb; 42 static l4re_video_view_info_t fbi; 43 static void *fb; 44 45 /* Keypad status and dimensions. */ 46 47 uint32_t *keypad = 0; 48 void *keymem = 0; 49 int columns, rows; 50 51 52 53 static uint32_t bitmask(uint32_t size) 54 { 55 return (1 << size) - 1; 56 } 57 58 static uint32_t truncate_channel(uint32_t value, uint32_t size) 59 { 60 return (value >> (8 - size)) & bitmask(size); 61 } 62 63 static void set_pixel(uint32_t pos, uint8_t bpp, uint32_t value) 64 { 65 if (bpp <= 8) *(uint8_t *) pos = value; 66 else if (bpp <= 16) *(uint16_t *) pos = value; 67 else *(uint32_t *) pos = value; 68 } 69 70 /* Show the state of a key on the display. */ 71 72 static void show_keystate(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t rgb) 73 { 74 uint8_t bpp = l4re_video_bits_per_pixel(&fbi.pixel_info); 75 uint8_t bytes_per_pixel = fbi.pixel_info.bytes_per_pixel; 76 uint32_t bytes_per_line = fbi.bytes_per_line; 77 uint32_t pos; 78 uint32_t col, row; 79 80 rgb = (truncate_channel(rgb >> 16, fbi.pixel_info.r.size) << fbi.pixel_info.r.shift) | 81 (truncate_channel(rgb >> 8, fbi.pixel_info.g.size) << fbi.pixel_info.g.shift) | 82 (truncate_channel(rgb, fbi.pixel_info.b.size) << fbi.pixel_info.b.shift); 83 84 for (row = 0; row < h; row++) 85 { 86 pos = (uint32_t) fb + (y + row) * bytes_per_line + x * bytes_per_pixel; 87 88 for (col = 0; col < w; col++) 89 { 90 set_pixel(pos, bpp, rgb); 91 pos += bytes_per_pixel; 92 } 93 } 94 } 95 96 /* Show the keypad status on the display. */ 97 98 static void show_keypad(void) 99 { 100 uint32_t colsize = fbi.width / columns, 101 rowsize = fbi.height / rows; 102 uint8_t column, row; 103 uint32_t mask; 104 105 for (column = 0; column < columns; column++) 106 107 for (row = 0, mask = 1 << (rows - 1); 108 row < rows; 109 row++, mask >>= 1) 110 111 show_keystate(column * colsize, row * rowsize, colsize, rowsize, 112 keypad[column] & mask ? 0xffffff : 0); 113 114 /* Refresh the display. */ 115 116 l4re_util_video_goos_fb_refresh(&gfb, 0, 0, fbi.width, fbi.height); 117 } 118 119 120 121 int main(int argc, char *argv[]) 122 { 123 L4::Cap<Keypad_device_interface> keypad_server; 124 L4::Cap<L4Re::Dataspace> mem; 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::env()->get_cap<Keypad_device_interface>("keypad"); 146 if (!keypad_server.is_valid()) return 1; 147 148 /* Obtain a capability for the keypad data. */ 149 150 mem = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>(); 151 if (!mem.is_valid()) return 1; 152 153 /* Obtain a reference to the keypad data. */ 154 155 if (keypad_server->get_keypad_data(mem)) return 1; 156 157 /* Attach the keypad data to a region in this task. */ 158 159 if (L4Re::Env::env()->rm()->attach(&keymem, mem->size(), 160 L4Re::Rm::F::Search_addr | 161 L4Re::Rm::F::R, 162 L4::Ipc::make_cap_rw(mem))) 163 return 1; 164 165 /* Show the keypad state. */ 166 167 keypad = (uint32_t *) keymem; 168 169 while (1) show_keypad(); 170 171 return 0; 172 }