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/re/c/dataspace.h> 23 #include <l4/re/c/rm.h> 24 #include <l4/re/env.h> 25 26 #include <l4/re/c/util/video/goos_fb.h> 27 #include <l4/re/c/video/view.h> 28 29 #include <stdio.h> 30 #include <unistd.h> 31 #include <stdint.h> 32 #include <stdlib.h> 33 34 #include "keypad_client.h" 35 36 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 *keymem = 0; 47 int columns, rows; 48 49 50 51 static uint32_t bitmask(uint32_t size) 52 { 53 return (1 << size) - 1; 54 } 55 56 static uint32_t truncate_channel(uint32_t value, uint32_t size) 57 { 58 return (value >> (8 - size)) & bitmask(size); 59 } 60 61 static void set_pixel(uint32_t pos, uint8_t bpp, uint32_t value) 62 { 63 if (bpp <= 8) *(uint8_t *) pos = value; 64 else if (bpp <= 16) *(uint16_t *) pos = value; 65 else *(uint32_t *) pos = value; 66 } 67 68 /* Show the state of a key on the display. */ 69 70 static void show_keystate(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t rgb) 71 { 72 uint8_t bpp = l4re_video_bits_per_pixel(&fbi.pixel_info); 73 uint8_t bytes_per_pixel = fbi.pixel_info.bytes_per_pixel; 74 uint32_t bytes_per_line = fbi.bytes_per_line; 75 uint32_t pos; 76 uint32_t col, row; 77 78 rgb = (truncate_channel(rgb >> 16, fbi.pixel_info.r.size) << fbi.pixel_info.r.shift) | 79 (truncate_channel(rgb >> 8, fbi.pixel_info.g.size) << fbi.pixel_info.g.shift) | 80 (truncate_channel(rgb, fbi.pixel_info.b.size) << fbi.pixel_info.b.shift); 81 82 for (row = 0; row < h; row++) 83 { 84 pos = (uint32_t) fb + (y + row) * bytes_per_line + x * bytes_per_pixel; 85 86 for (col = 0; col < w; col++) 87 { 88 set_pixel(pos, bpp, rgb); 89 pos += bytes_per_pixel; 90 } 91 } 92 } 93 94 /* Show the keypad status on the display. */ 95 96 static void show_keypad(void) 97 { 98 uint32_t colsize = fbi.width / columns, 99 rowsize = fbi.height / rows; 100 uint8_t column, row; 101 uint32_t mask; 102 103 for (column = 0; column < columns; column++) 104 105 for (row = 0, mask = 1 << (rows - 1); 106 row < rows; 107 row++, mask >>= 1) 108 109 show_keystate(column * colsize, row * rowsize, colsize, rowsize, 110 keymem[column] & mask ? 0xffffff : 0); 111 112 /* Refresh the display. */ 113 114 l4re_util_video_goos_fb_refresh(&gfb, 0, 0, fbi.width, fbi.height); 115 } 116 117 118 119 int main(int argc, char *argv[]) 120 { 121 l4_cap_idx_t keypad_cap; 122 l4re_ds_t mem; 123 124 /* Obtain the keypad matrix dimensions. */ 125 126 if (argc < 3) 127 return 1; 128 129 columns = atoi(argv[1]); 130 rows = atoi(argv[2]); 131 132 if (l4re_util_video_goos_fb_setup_name(&gfb, "fb")) 133 return 1; 134 135 if (l4re_util_video_goos_fb_view_info(&gfb, &fbi)) 136 return 1; 137 138 if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb))) 139 return 1; 140 141 /* Obtain a reference to the keypad. */ 142 143 keypad_cap = l4re_env_get_cap("keypad"); 144 145 if (l4_is_invalid_cap(keypad_cap)) 146 return 1; 147 148 /* Obtain a reference to the keypad data. */ 149 150 client_Keypad keypad(keypad_cap); 151 152 if (keypad.get_keypad_data(&mem)) 153 return 1; 154 155 /* Attach the keypad data to a region in this task. */ 156 157 if (l4re_rm_attach((void **) &keymem, l4re_ds_size(mem), 158 L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_R, 159 mem, 0, 160 L4_PAGESHIFT)) 161 return 1; 162 163 /* Show the keypad state. */ 164 165 while (1) 166 show_keypad(); 167 168 return 0; 169 }