1 /* 2 * Display the keypad matrix using the specified dimensions. 3 * 4 * (c) 2018 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 <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_idx_t keypad_server; 124 l4re_ds_t mem; 125 l4_msgtag_t tag; 126 127 /* Obtain the keypad matrix dimensions. */ 128 129 if (argc < 3) 130 return 1; 131 132 columns = atoi(argv[1]); 133 rows = atoi(argv[2]); 134 135 if (l4re_util_video_goos_fb_setup_name(&gfb, "fb")) 136 return 1; 137 138 if (l4re_util_video_goos_fb_view_info(&gfb, &fbi)) 139 return 1; 140 141 if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb))) 142 return 1; 143 144 /* Obtain a reference to the keypad. */ 145 146 keypad_server = l4re_env_get_cap("keypad"); 147 if (l4_is_invalid_cap(keypad_server)) return 1; 148 149 /* Obtain a capability for the keypad data. */ 150 151 mem = l4re_util_cap_alloc(); 152 if (l4_is_invalid_cap(mem)) return 1; 153 154 /* Obtain a reference to the keypad data. */ 155 156 l4_utcb_br()->bdr = 0; 157 l4_utcb_br()->br[0] = L4_RCV_ITEM_SINGLE_CAP | mem; 158 159 tag = l4_ipc_call(keypad_server, l4_utcb(), 160 l4_msgtag(Keypad_op_get_keypad_data, 0, 0, 0), /* zero words, zero *sent* items */ 161 L4_IPC_NEVER); 162 163 if (l4_ipc_error(tag, l4_utcb())) return 1; 164 165 /* Attach the keypad data to a region in this task. */ 166 167 if (l4re_rm_attach(&keymem, l4re_ds_size(mem), L4RE_RM_SEARCH_ADDR, mem, 0, 168 L4_PAGESHIFT)) 169 return 1; 170 171 /* Show the keypad state. */ 172 173 keypad = (uint32_t *) keymem; 174 175 while (1) show_keypad(); 176 177 return 0; 178 }