1 /* 2 * Access the keypad on the configured device using an input driver. 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 * Font definitions and licence (see unifont.tff for bitmap data derived from 23 * GNU Unifont's unifont.hex file): 24 * 25 * Copyright (C) 1998-2003 Roman Czyborra (http://czyborra.com/) 26 * 27 * All glyphs are released under the GNU General Public License 28 * (GPL) version 2 or (at your option) a later version, with the 29 * GNU font embedding exception: 30 * 31 * ** GPL v2.0 license with font embedding exception: 32 * 33 * As a special exception, if you create a document which 34 * uses this font, and embed this font or unaltered portions 35 * of this font into the document, this font does not by 36 * itself cause the resulting document to be covered by 37 * the GNU General Public License. This exception does not 38 * however invalidate any other reasons why the document 39 * might be covered by the GNU General Public License. 40 * If you modify this font, you may extend this exception 41 * to your version of the font, but you are not obligated 42 * to do so. If you do not wish to do so, delete this 43 * exception statement from your version. 44 */ 45 46 #include <l4/devices/input-keypad-client.h> 47 48 #include <l4/re/c/util/video/goos_fb.h> 49 #include <l4/re/c/video/view.h> 50 #include <l4/util/util.h> 51 52 #include <l4/mag-gfx/canvas> 53 #include <l4/mag-gfx/font> 54 #include <l4/mag-gfx/geometry> 55 #include <l4/mag-gfx/gfx_colors> 56 #include <l4/mag-gfx/mem_factory> 57 58 #include <stdint.h> 59 #include <string.h> 60 61 /* Video abstractions. */ 62 63 static l4re_util_video_goos_fb_t gfb; 64 static l4re_video_view_info_t view_info; 65 static void *fb = 0; 66 67 /* Bundled font data. */ 68 69 extern char const _binary_unifont_tff_start[]; 70 71 /* Screen abstractions. */ 72 73 using namespace Mag_gfx; 74 75 static Font *_font = 0; 76 static Canvas *_screen = 0; 77 78 79 80 /* Factories for certain pixel formats. */ 81 82 static Mem::Factory<Rgb16> _rgb16; 83 static Mem::Factory<Rgb32> _rgb32; 84 85 86 87 /* Key to character conversion function. */ 88 89 static const char *keys_to_strings[] = { 90 91 0, "Escape", "1", "2", "3", "4", "5", "6", "7", "8", 92 93 "9", "0", "-", "=", "Backspace", "Tab", "Q", "W", "E", "R", 94 95 "T", "Y", "U", "I", "O", "P", "[", "]", "Enter", "Left Ctrl", 96 97 "A", "S", "D", "F", "G", "H", "J", "K", "L", ";", 98 99 "'", "`", "Left Shift", "\\", "Z", "X", "C", "V", "B", "N", 100 101 "M", ",", ".", "/", "Right Shift", "Keypad *", "Left Alt", "Space", 102 "Caps Lock", "F1", 103 104 "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "Num Lock", 105 106 "Scroll Lock", "Keypad 7", "Keypad 8", "Keypad 9", "Keypad -", "Keypad 4", 107 "Keypad 5", "Keypad 6", "Keypad +", "Keypad 1", 108 109 "Keypad 2", "Keypad 3", "Keypad 0", "Keypad .", 0, 0, "#102", "F11", "F12", 0, 110 111 0, 0, 0, 0, 0, 0, "Keypad Enter", "Right Ctrl", "Keypad /", "SysRq", 112 113 "Right Alt", "Line Feed", "Home", "Up", "Page Up", "Left", "Right", "End", 114 "Down", "Page Down", 115 116 "Insert", "Delete", "Macro", "Mute", "Volume Down", "Volume Up", "Power", 117 "Keypad =", "Keypad +-", "Pause", 118 }; 119 120 static const char null_string[] = "Unknown"; 121 122 const int keys_to_strings_length = 120; 123 124 static const char *key_to_string(int key) 125 { 126 return key < keys_to_strings_length ? keys_to_strings[key] : 0; 127 } 128 129 /* Show the keypad event status on the display. */ 130 131 static uint8_t row = 0; 132 static uint32_t text_x = 0, text_y = 0, next_y = 0; 133 134 static void handler(Input_event event, void *priv) 135 { 136 uint32_t colsize = view_info.width / 10, 137 rowsize = view_info.height / 20; 138 uint8_t column; 139 uint16_t mask; 140 141 /* Convert the key code into a bit pattern. */ 142 143 if (!priv) 144 { 145 for (column = 0, mask = (1 << 9); column < 10; column++, mask >>= 1) 146 _screen->draw_box(Rect(Point(column * colsize, row * rowsize), Area(colsize, rowsize)), 147 event.code & mask ? event.value ? Rgb32::Color(0, 255, 0) : Rgb32::Color(255, 0, 0) 148 : Rgb32::Color(0, 0, 0)); 149 150 /* Advance to the next row, wrapping around. */ 151 152 row = (row + 1) % 20; 153 } 154 155 /* Or produce a string. */ 156 157 else if (event.value) 158 { 159 const char *s = ((const char *(*)(int)) priv)(event.code); 160 Rgba32::Color col; 161 162 if (!s) 163 { 164 s = null_string; 165 col = Rgba32::Color(255, 0, 0, Rgba32::Color::Amax); 166 } 167 else 168 col = Rgba32::Color(255, 255, 255, Rgba32::Color::Amax); 169 170 Area box = _font->str_sz(s, strlen(s)); 171 172 /* Test for enough space horizontally. */ 173 174 if (text_x + box.w() > view_info.width) 175 { 176 text_x = 0; 177 text_y = next_y; 178 next_y = text_y + box.h(); 179 } 180 181 /* Expand the line height, if appropriate. */ 182 183 else if (text_y + box.h() > next_y) 184 next_y += box.h(); 185 186 /* Test for enough space vertically. */ 187 188 if (next_y > view_info.height) 189 { 190 text_x = 0; 191 text_y = 0; 192 next_y = box.h(); 193 } 194 195 Point p(text_x, text_y); 196 197 _screen->draw_box(Rect(p, box), Rgb32::Color(0, 0, 0)); 198 _screen->draw_string(p, _font, col, s, strlen(s)); 199 200 /* Move to the next position. */ 201 202 text_x += box.w(); 203 } 204 205 /* Refresh the display. */ 206 207 l4re_util_video_goos_fb_refresh(&gfb, 0, 0, view_info.width, view_info.height); 208 } 209 210 /* Arguments: [ chars ] */ 211 212 int main(int argc, char *argv[]) 213 { 214 Keypad *keypad = Keypad::get_keypad(); 215 Input_keypad_client client(keypad); 216 217 if (l4re_util_video_goos_fb_setup_name(&gfb, "fb")) 218 return 1; 219 220 if (l4re_util_video_goos_fb_view_info(&gfb, &view_info)) 221 return 1; 222 223 if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb))) 224 return 1; 225 226 /* Obtain a canvas for the framebuffer. */ 227 228 Factory *factory; 229 230 if (view_info.pixel_info.bytes_per_pixel == 2) 231 factory = &_rgb16; 232 else 233 factory = &_rgb32; 234 235 Canvas *screen = factory->create_canvas((void *) ((unsigned long) fb + view_info.buffer_offset), 236 Area(view_info.width, view_info.height), 237 view_info.bytes_per_line); 238 239 Font font(&_binary_unifont_tff_start[0]); 240 241 _screen = screen; 242 _font = &font; 243 244 /* Attach the event handler and wait for events. */ 245 246 client.attach(handler, (argc > 1) && (!strcmp(argv[1], "chars")) ? (void *) key_to_string : 0); 247 248 l4_sleep_forever(); 249 250 return 0; 251 }