paul@0 | 1 | /* |
paul@0 | 2 | * Display the physical keypad matrix layout for the Letux 400 notebook |
paul@0 | 3 | * computer. |
paul@0 | 4 | * |
paul@142 | 5 | * Copyright (C) 2018, 2023 Paul Boddie <paul@boddie.org.uk> |
paul@0 | 6 | * |
paul@0 | 7 | * This program is free software; you can redistribute it and/or |
paul@0 | 8 | * modify it under the terms of the GNU General Public License as |
paul@0 | 9 | * published by the Free Software Foundation; either version 2 of |
paul@0 | 10 | * the License, or (at your option) any later version. |
paul@0 | 11 | * |
paul@0 | 12 | * This program is distributed in the hope that it will be useful, |
paul@0 | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@0 | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@0 | 15 | * GNU General Public License for more details. |
paul@0 | 16 | * |
paul@0 | 17 | * You should have received a copy of the GNU General Public License |
paul@0 | 18 | * along with this program; if not, write to the Free Software |
paul@0 | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@0 | 20 | * Boston, MA 02110-1301, USA |
paul@0 | 21 | */ |
paul@0 | 22 | |
paul@0 | 23 | #include <l4/re/c/rm.h> |
paul@0 | 24 | #include <l4/re/c/util/cap_alloc.h> |
paul@0 | 25 | #include <l4/re/env.h> |
paul@0 | 26 | #include <l4/util/util.h> |
paul@0 | 27 | #include <l4/sys/ipc.h> |
paul@0 | 28 | |
paul@0 | 29 | #include <l4/re/c/util/video/goos_fb.h> |
paul@0 | 30 | #include <l4/re/c/video/view.h> |
paul@0 | 31 | |
paul@0 | 32 | #include <stdio.h> |
paul@0 | 33 | #include <stdint.h> |
paul@0 | 34 | #include <stdlib.h> |
paul@0 | 35 | #include <unistd.h> |
paul@0 | 36 | |
paul@0 | 37 | enum Jz4730_keypad_gpio |
paul@0 | 38 | { |
paul@0 | 39 | Jz4730_keypad_gpio_inputs_count = 8, |
paul@0 | 40 | Jz4730_keypad_gpio_outputs_count = 17, |
paul@0 | 41 | }; |
paul@0 | 42 | |
paul@0 | 43 | /* Video abstractions. */ |
paul@0 | 44 | |
paul@0 | 45 | static l4re_util_video_goos_fb_t gfb; |
paul@0 | 46 | static l4re_video_view_info_t fbi; |
paul@0 | 47 | static void *fb; |
paul@0 | 48 | |
paul@0 | 49 | /* Keypad status and dimensions. */ |
paul@0 | 50 | |
paul@0 | 51 | uint32_t *keypad = 0; |
paul@0 | 52 | void *keymem = 0; |
paul@0 | 53 | int columns = Jz4730_keypad_gpio_outputs_count, rows = Jz4730_keypad_gpio_inputs_count; |
paul@0 | 54 | |
paul@0 | 55 | /* Position units: 0.1mm */ |
paul@0 | 56 | |
paul@0 | 57 | enum { |
paul@0 | 58 | SPC = 600, CAPS = 240, TAB = 200, LSH = 184, M = 160, S = 136, XS = 120, |
paul@0 | 59 | WIDTH = 2040, HEIGHT = 800, ROWS = 6, |
paul@0 | 60 | }; |
paul@0 | 61 | |
paul@0 | 62 | /* |
paul@0 | 63 | S(15) Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 Num Sys Ins Del |
paul@0 | 64 | XS(1)/M(12) ` 1 2 3 4 5 6 7 8 9 0 - Bsp |
paul@0 | 65 | TAB(1)/M(10)/XS(2) Tab Q W E R T Y U I O P = \ |
paul@0 | 66 | CAPS(1)/M(9)/XS(1)/CAPS(1) Caps A S D F G H J K L ; Enter |
paul@0 | 67 | LSH(1)/XS(1)/M(7)/XS(4)/S(1) Sh \ Z X C V B N M , . / Up Sh |
paul@0 | 68 | XS(5)/SPC(1)/XS(7) Fn Ctr Zzz Alt Pau Space Mnu [ ] ' Lt Dn Rt |
paul@0 | 69 | */ |
paul@0 | 70 | |
paul@0 | 71 | enum { |
paul@0 | 72 | SIZE_KEY_ESC = S, SIZE_KEY_F1 = S, SIZE_KEY_F2 = S, SIZE_KEY_F3 = S, SIZE_KEY_F4 = S, |
paul@0 | 73 | SIZE_KEY_F5 = S, SIZE_KEY_F6 = S, SIZE_KEY_F7 = S, SIZE_KEY_F8 = S, SIZE_KEY_F9 = S, |
paul@0 | 74 | SIZE_KEY_F10 = S, SIZE_KEY_NUMLOCK = S, SIZE_KEY_SYSRQ = S, SIZE_KEY_INSERT = S, |
paul@0 | 75 | SIZE_KEY_DELETE = S, |
paul@0 | 76 | |
paul@0 | 77 | SIZE_KEY_GRAVE = XS, SIZE_KEY_1 = M, SIZE_KEY_2 = M, SIZE_KEY_3 = M, SIZE_KEY_4 = M, |
paul@0 | 78 | SIZE_KEY_5 = M, SIZE_KEY_6 = M, SIZE_KEY_7 = M, SIZE_KEY_8 = M, SIZE_KEY_9 = M, |
paul@0 | 79 | SIZE_KEY_0 = M, SIZE_KEY_MINUS = M, SIZE_KEY_BACKSPACE = M, |
paul@0 | 80 | |
paul@0 | 81 | SIZE_KEY_TAB = TAB, SIZE_KEY_Q = M, SIZE_KEY_W = M, SIZE_KEY_E = M, SIZE_KEY_R = M, |
paul@0 | 82 | SIZE_KEY_T = M, SIZE_KEY_Y = M, SIZE_KEY_U = M, SIZE_KEY_I = M, SIZE_KEY_O = M, |
paul@0 | 83 | SIZE_KEY_P = M, SIZE_KEY_EQUAL = XS, SIZE_KEY_RIGHTBACKSLASH = XS, |
paul@0 | 84 | |
paul@0 | 85 | SIZE_KEY_CAPSLOCK = CAPS, SIZE_KEY_A = M, SIZE_KEY_S = M, SIZE_KEY_D = M, SIZE_KEY_F = M, |
paul@0 | 86 | SIZE_KEY_G = M, SIZE_KEY_H = M, SIZE_KEY_J = M, SIZE_KEY_K = M, SIZE_KEY_L = M, |
paul@0 | 87 | SIZE_KEY_SEMICOLON = XS, SIZE_KEY_ENTER = CAPS, |
paul@0 | 88 | |
paul@0 | 89 | SIZE_KEY_LEFTSHIFT = LSH, SIZE_KEY_LEFTBACKSLASH = XS, SIZE_KEY_Z = M, SIZE_KEY_X = M, SIZE_KEY_C = M, |
paul@0 | 90 | SIZE_KEY_V = M, SIZE_KEY_B = M, SIZE_KEY_N = M, SIZE_KEY_M = M, SIZE_KEY_COMMA = XS, |
paul@0 | 91 | SIZE_KEY_DOT = XS, SIZE_KEY_SLASH = XS, SIZE_KEY_UP = XS, SIZE_KEY_RIGHTSHIFT = S, |
paul@0 | 92 | |
paul@0 | 93 | SIZE_KEY_FN = XS, SIZE_KEY_LEFTCTRL = XS, SIZE_KEY_SLEEP = XS, SIZE_KEY_LEFTALT = XS, SIZE_KEY_PAUSE = XS, |
paul@0 | 94 | SIZE_KEY_SPACE = SPC, SIZE_KEY_MENU = XS, SIZE_KEY_LEFTBRACE = XS, SIZE_KEY_RIGHTBRACE = XS, |
paul@0 | 95 | SIZE_KEY_APOSTROPHE = XS, SIZE_KEY_LEFT = XS, SIZE_KEY_DOWN = XS, SIZE_KEY_RIGHT = XS, |
paul@0 | 96 | }; |
paul@0 | 97 | |
paul@0 | 98 | enum { |
paul@0 | 99 | XPOS_KEY_ESC = 0, XPOS_KEY_F1 = S, XPOS_KEY_F2 = 2*S, XPOS_KEY_F3 = 3*S, XPOS_KEY_F4 = 4*S, |
paul@0 | 100 | XPOS_KEY_F5 = 5*S, XPOS_KEY_F6 = 6*S, XPOS_KEY_F7 = 7*S, XPOS_KEY_F8 = 8*S, XPOS_KEY_F9 = 9*S, |
paul@0 | 101 | XPOS_KEY_F10 = 10*S, XPOS_KEY_NUMLOCK = 11*S, XPOS_KEY_SYSRQ = 12*S, XPOS_KEY_INSERT = 13*S, |
paul@0 | 102 | XPOS_KEY_DELETE = 14*S, |
paul@0 | 103 | |
paul@0 | 104 | XPOS_KEY_GRAVE = 0, XPOS_KEY_1 = XS, XPOS_KEY_2 = XS+M, XPOS_KEY_3 = XS+2*M, XPOS_KEY_4 = XS+3*M, |
paul@0 | 105 | XPOS_KEY_5 = XS+4*M, XPOS_KEY_6 = XS+5*M, XPOS_KEY_7 = XS+6*M, XPOS_KEY_8 = XS+7*M, XPOS_KEY_9 = XS+8*M, |
paul@0 | 106 | XPOS_KEY_0 = XS+9*M, XPOS_KEY_MINUS = XS+10*M, XPOS_KEY_BACKSPACE = XS+11*M, |
paul@0 | 107 | |
paul@0 | 108 | XPOS_KEY_TAB = 0, XPOS_KEY_Q = TAB, XPOS_KEY_W = TAB+M, XPOS_KEY_E = TAB+2*M, XPOS_KEY_R = TAB+3*M, |
paul@0 | 109 | XPOS_KEY_T = TAB+4*M, XPOS_KEY_Y = TAB+5*M, XPOS_KEY_U = TAB+6*M, XPOS_KEY_I = TAB+7*M, XPOS_KEY_O = TAB+8*M, |
paul@0 | 110 | XPOS_KEY_P = TAB+9*M, XPOS_KEY_EQUAL = TAB+10*M, XPOS_KEY_RIGHTBACKSLASH = TAB+10*M+XS, |
paul@0 | 111 | |
paul@0 | 112 | XPOS_KEY_CAPSLOCK = 0, XPOS_KEY_A = CAPS, XPOS_KEY_S = CAPS+M, XPOS_KEY_D = CAPS+2*M, XPOS_KEY_F = CAPS+3*M, |
paul@0 | 113 | XPOS_KEY_G = CAPS+4*M, XPOS_KEY_H = CAPS+5*M, XPOS_KEY_J = CAPS+6*M, XPOS_KEY_K = CAPS+7*M, XPOS_KEY_L = CAPS+8*M, |
paul@0 | 114 | XPOS_KEY_SEMICOLON = CAPS+9*M, XPOS_KEY_ENTER = CAPS+9*M+XS, |
paul@0 | 115 | |
paul@0 | 116 | XPOS_KEY_LEFTSHIFT = 0, XPOS_KEY_LEFTBACKSLASH = LSH, XPOS_KEY_Z = LSH+XS, XPOS_KEY_X = LSH+XS+M, XPOS_KEY_C = LSH+XS+2*M, |
paul@0 | 117 | XPOS_KEY_V = LSH+XS+3*M, XPOS_KEY_B = LSH+XS+4*M, XPOS_KEY_N = LSH+XS+5*M, XPOS_KEY_M = LSH+XS+6*M, XPOS_KEY_COMMA = LSH+XS+7*M, |
paul@0 | 118 | XPOS_KEY_DOT = LSH+XS+7*M+XS, XPOS_KEY_SLASH = LSH+XS+7*M+2*XS, XPOS_KEY_UP = LSH+XS+7*M+3*XS, XPOS_KEY_RIGHTSHIFT = LSH+XS+7*M+4*XS, |
paul@0 | 119 | |
paul@0 | 120 | XPOS_KEY_FN = 0, XPOS_KEY_LEFTCTRL = XS, XPOS_KEY_SLEEP = 2*XS, XPOS_KEY_LEFTALT = 3*XS, XPOS_KEY_PAUSE = 4*XS, |
paul@0 | 121 | XPOS_KEY_SPACE = 5*XS, XPOS_KEY_MENU = 5*XS+SPC, XPOS_KEY_LEFTBRACE = 5*XS+SPC+XS, XPOS_KEY_RIGHTBRACE = 5*XS+SPC+2*XS, |
paul@0 | 122 | XPOS_KEY_APOSTROPHE = 5*XS+SPC+3*XS, XPOS_KEY_LEFT = 5*XS+SPC+4*XS, XPOS_KEY_DOWN = 5*XS+SPC+5*XS, XPOS_KEY_RIGHT = 5*XS+SPC+6*XS, |
paul@0 | 123 | }; |
paul@0 | 124 | |
paul@0 | 125 | enum { |
paul@0 | 126 | YPOS_KEY_ESC = 0, YPOS_KEY_F1 = 0, YPOS_KEY_F2 = 0, YPOS_KEY_F3 = 0, YPOS_KEY_F4 = 0, |
paul@0 | 127 | YPOS_KEY_F5 = 0, YPOS_KEY_F6 = 0, YPOS_KEY_F7 = 0, YPOS_KEY_F8 = 0, YPOS_KEY_F9 = 0, |
paul@0 | 128 | YPOS_KEY_F10 = 0, YPOS_KEY_NUMLOCK = 0, YPOS_KEY_SYSRQ = 0, YPOS_KEY_INSERT = 0, |
paul@0 | 129 | YPOS_KEY_DELETE = 0, |
paul@0 | 130 | |
paul@0 | 131 | YPOS_KEY_GRAVE = 1, YPOS_KEY_1 = 1, YPOS_KEY_2 = 1, YPOS_KEY_3 = 1, YPOS_KEY_4 = 1, |
paul@0 | 132 | YPOS_KEY_5 = 1, YPOS_KEY_6 = 1, YPOS_KEY_7 = 1, YPOS_KEY_8 = 1, YPOS_KEY_9 = 1, |
paul@0 | 133 | YPOS_KEY_0 = 1, YPOS_KEY_MINUS = 1, YPOS_KEY_BACKSPACE = 1, |
paul@0 | 134 | |
paul@0 | 135 | YPOS_KEY_TAB = 2, YPOS_KEY_Q = 2, YPOS_KEY_W = 2, YPOS_KEY_E = 2, YPOS_KEY_R = 2, |
paul@0 | 136 | YPOS_KEY_T = 2, YPOS_KEY_Y = 2, YPOS_KEY_U = 2, YPOS_KEY_I = 2, YPOS_KEY_O = 2, |
paul@0 | 137 | YPOS_KEY_P = 2, YPOS_KEY_EQUAL = 2, YPOS_KEY_RIGHTBACKSLASH = 2, |
paul@0 | 138 | |
paul@0 | 139 | YPOS_KEY_CAPSLOCK = 3, YPOS_KEY_A = 3, YPOS_KEY_S = 3, YPOS_KEY_D = 3, YPOS_KEY_F = 3, |
paul@0 | 140 | YPOS_KEY_G = 3, YPOS_KEY_H = 3, YPOS_KEY_J = 3, YPOS_KEY_K = 3, YPOS_KEY_L = 3, |
paul@0 | 141 | YPOS_KEY_SEMICOLON = 3, YPOS_KEY_ENTER = 3, |
paul@0 | 142 | |
paul@0 | 143 | YPOS_KEY_LEFTSHIFT = 4, YPOS_KEY_LEFTBACKSLASH = 4, YPOS_KEY_Z = 4, YPOS_KEY_X = 4, YPOS_KEY_C = 4, |
paul@0 | 144 | YPOS_KEY_V = 4, YPOS_KEY_B = 4, YPOS_KEY_N = 4, YPOS_KEY_M = 4, YPOS_KEY_COMMA = 4, |
paul@0 | 145 | YPOS_KEY_DOT = 4, YPOS_KEY_SLASH = 4, YPOS_KEY_UP = 4, YPOS_KEY_RIGHTSHIFT = 4, |
paul@0 | 146 | |
paul@0 | 147 | YPOS_KEY_FN = 5, YPOS_KEY_LEFTCTRL = 5, YPOS_KEY_SLEEP = 5, YPOS_KEY_LEFTALT = 5, YPOS_KEY_PAUSE = 5, |
paul@0 | 148 | YPOS_KEY_SPACE = 5, YPOS_KEY_MENU = 5, YPOS_KEY_LEFTBRACE = 5, YPOS_KEY_RIGHTBRACE = 5, |
paul@0 | 149 | YPOS_KEY_APOSTROPHE = 5, YPOS_KEY_LEFT = 5, YPOS_KEY_DOWN = 5, YPOS_KEY_RIGHT = 5, |
paul@0 | 150 | }; |
paul@0 | 151 | |
paul@0 | 152 | /* Keypad matrix mapping. */ |
paul@0 | 153 | |
paul@0 | 154 | #define PHYS_KEY(X) {XPOS_KEY_##X, YPOS_KEY_##X, SIZE_KEY_##X} |
paul@0 | 155 | #define PHYS_NULL {0, 0, 0} |
paul@0 | 156 | |
paul@0 | 157 | static const uint32_t keypos[Jz4730_keypad_gpio_inputs_count][Jz4730_keypad_gpio_outputs_count][3] = { |
paul@0 | 158 | |
paul@0 | 159 | {PHYS_KEY(PAUSE), PHYS_KEY(Q), PHYS_KEY(W), PHYS_KEY(E), PHYS_KEY(R), PHYS_KEY(U), PHYS_KEY(I), PHYS_KEY(O), |
paul@0 | 160 | PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(P), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_NULL}, |
paul@0 | 161 | |
paul@0 | 162 | {PHYS_NULL, PHYS_KEY(TAB), PHYS_KEY(CAPSLOCK), PHYS_KEY(F3), PHYS_KEY(T), PHYS_KEY(Y), PHYS_KEY(RIGHTBRACE), PHYS_KEY(F7), |
paul@0 | 163 | PHYS_NULL, PHYS_KEY(BACKSPACE), PHYS_NULL, PHYS_KEY(LEFTBRACE), PHYS_KEY(SLEEP), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(LEFTSHIFT)}, |
paul@0 | 164 | |
paul@0 | 165 | {PHYS_NULL, PHYS_KEY(A), PHYS_KEY(S), PHYS_KEY(D), PHYS_KEY(F), PHYS_KEY(J), PHYS_KEY(K), PHYS_KEY(L), |
paul@0 | 166 | PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(SEMICOLON), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(UP), PHYS_KEY(RIGHTSHIFT)}, |
paul@0 | 167 | |
paul@0 | 168 | {PHYS_NULL, PHYS_KEY(ESC), PHYS_KEY(LEFTBACKSLASH), PHYS_KEY(F4), PHYS_KEY(G), PHYS_KEY(H), PHYS_KEY(F6), PHYS_NULL, |
paul@0 | 169 | PHYS_KEY(SPACE), PHYS_NULL, PHYS_KEY(LEFTALT), PHYS_KEY(APOSTROPHE), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(DOWN), PHYS_NULL}, |
paul@0 | 170 | |
paul@0 | 171 | {PHYS_NULL, PHYS_KEY(Z), PHYS_KEY(X), PHYS_KEY(C), PHYS_KEY(V), PHYS_KEY(M), PHYS_KEY(COMMA), PHYS_KEY(DOT), |
paul@0 | 172 | PHYS_KEY(NUMLOCK), PHYS_KEY(ENTER), PHYS_NULL, PHYS_KEY(RIGHTBACKSLASH), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(LEFT), PHYS_NULL}, |
paul@0 | 173 | |
paul@0 | 174 | {PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(B), PHYS_KEY(N), PHYS_NULL, PHYS_KEY(MENU), |
paul@0 | 175 | PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(SLASH), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(RIGHT), PHYS_NULL}, |
paul@0 | 176 | |
paul@0 | 177 | {PHYS_KEY(LEFTCTRL), PHYS_KEY(GRAVE), PHYS_NULL, PHYS_NULL, PHYS_KEY(5), PHYS_KEY(6), PHYS_KEY(EQUAL), PHYS_KEY(F8), |
paul@0 | 178 | PHYS_KEY(DELETE), PHYS_KEY(F9), PHYS_NULL, PHYS_KEY(MINUS), PHYS_NULL, PHYS_KEY(F2), PHYS_KEY(INSERT), PHYS_NULL, PHYS_KEY(F1)}, |
paul@0 | 179 | |
paul@0 | 180 | {PHYS_KEY(F5), PHYS_KEY(1), PHYS_KEY(2), PHYS_KEY(3), PHYS_KEY(4), PHYS_KEY(7), PHYS_KEY(8), PHYS_KEY(9), |
paul@0 | 181 | PHYS_NULL, PHYS_NULL, PHYS_KEY(SYSRQ), PHYS_KEY(0), PHYS_KEY(F10), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(FN)} |
paul@0 | 182 | }; |
paul@0 | 183 | |
paul@0 | 184 | |
paul@0 | 185 | |
paul@0 | 186 | static uint32_t bitmask(uint32_t size) |
paul@0 | 187 | { |
paul@0 | 188 | return (1 << size) - 1; |
paul@0 | 189 | } |
paul@0 | 190 | |
paul@0 | 191 | static uint32_t truncate_channel(uint32_t value, uint32_t size) |
paul@0 | 192 | { |
paul@0 | 193 | return (value >> (8 - size)) & bitmask(size); |
paul@0 | 194 | } |
paul@0 | 195 | |
paul@0 | 196 | static void set_pixel(uint32_t pos, uint8_t bpp, uint32_t value) |
paul@0 | 197 | { |
paul@0 | 198 | if (bpp <= 8) *(uint8_t *) pos = value; |
paul@0 | 199 | else if (bpp <= 16) *(uint16_t *) pos = value; |
paul@0 | 200 | else *(uint32_t *) pos = value; |
paul@0 | 201 | } |
paul@0 | 202 | |
paul@0 | 203 | /* Show the state of a key on the display. */ |
paul@0 | 204 | |
paul@0 | 205 | static void fill_rectangle(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t rgb) |
paul@0 | 206 | { |
paul@0 | 207 | uint8_t bpp = l4re_video_bits_per_pixel(&fbi.pixel_info); |
paul@0 | 208 | uint8_t bytes_per_pixel = fbi.pixel_info.bytes_per_pixel; |
paul@0 | 209 | uint32_t bytes_per_line = fbi.bytes_per_line; |
paul@0 | 210 | uint32_t pos; |
paul@0 | 211 | uint32_t col, row; |
paul@0 | 212 | |
paul@0 | 213 | rgb = (truncate_channel(rgb >> 16, fbi.pixel_info.r.size) << fbi.pixel_info.r.shift) | |
paul@0 | 214 | (truncate_channel(rgb >> 8, fbi.pixel_info.g.size) << fbi.pixel_info.g.shift) | |
paul@0 | 215 | (truncate_channel(rgb, fbi.pixel_info.b.size) << fbi.pixel_info.b.shift); |
paul@0 | 216 | |
paul@0 | 217 | for (row = 0; row < h; row++) |
paul@0 | 218 | { |
paul@0 | 219 | pos = (uint32_t) fb + (y + row) * bytes_per_line + x * bytes_per_pixel; |
paul@0 | 220 | |
paul@0 | 221 | for (col = 0; col < w; col++) |
paul@0 | 222 | { |
paul@0 | 223 | set_pixel(pos, bpp, rgb); |
paul@0 | 224 | pos += bytes_per_pixel; |
paul@0 | 225 | } |
paul@0 | 226 | } |
paul@0 | 227 | } |
paul@0 | 228 | |
paul@0 | 229 | /* Show the keypad status on the display. */ |
paul@0 | 230 | |
paul@0 | 231 | static void show_keypad(void) |
paul@0 | 232 | { |
paul@0 | 233 | uint32_t rowsize = fbi.height / ROWS, colsize; |
paul@0 | 234 | uint8_t column, row; |
paul@0 | 235 | uint32_t mask; |
paul@0 | 236 | const uint32_t *pos; |
paul@0 | 237 | |
paul@0 | 238 | for (column = 0; column < columns; column++) |
paul@0 | 239 | |
paul@0 | 240 | for (row = 0, mask = 1 << (rows - 1); |
paul@0 | 241 | row < rows; |
paul@0 | 242 | row++, mask >>= 1) |
paul@0 | 243 | { |
paul@0 | 244 | /* Obtain the physical position. */ |
paul@0 | 245 | |
paul@0 | 246 | pos = keypos[row][column]; |
paul@0 | 247 | |
paul@0 | 248 | /* Obtain the width of the key. */ |
paul@0 | 249 | |
paul@0 | 250 | colsize = (pos[2] * fbi.width) / WIDTH; |
paul@0 | 251 | |
paul@0 | 252 | /* Plot the rectangle for the key. */ |
paul@0 | 253 | |
paul@0 | 254 | fill_rectangle((pos[0] * fbi.width) / WIDTH, pos[1] * rowsize, colsize, rowsize, |
paul@0 | 255 | keypad[column] & mask ? 0xffffff : 0); |
paul@0 | 256 | } |
paul@0 | 257 | |
paul@0 | 258 | /* Refresh the display. */ |
paul@0 | 259 | |
paul@0 | 260 | l4re_util_video_goos_fb_refresh(&gfb, 0, 0, fbi.width, fbi.height); |
paul@0 | 261 | } |
paul@0 | 262 | |
paul@0 | 263 | |
paul@0 | 264 | |
paul@0 | 265 | int main(void) |
paul@0 | 266 | { |
paul@0 | 267 | l4_cap_idx_t keypad_server; |
paul@0 | 268 | l4re_ds_t mem; |
paul@0 | 269 | l4_msgtag_t tag; |
paul@0 | 270 | |
paul@0 | 271 | if (l4re_util_video_goos_fb_setup_name(&gfb, "fb")) |
paul@0 | 272 | return 1; |
paul@0 | 273 | |
paul@0 | 274 | if (l4re_util_video_goos_fb_view_info(&gfb, &fbi)) |
paul@0 | 275 | return 1; |
paul@0 | 276 | |
paul@0 | 277 | if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb))) |
paul@0 | 278 | return 1; |
paul@0 | 279 | |
paul@0 | 280 | /* Obtain a reference to the keypad. */ |
paul@0 | 281 | |
paul@0 | 282 | keypad_server = l4re_env_get_cap("keypad"); |
paul@0 | 283 | if (l4_is_invalid_cap(keypad_server)) return 1; |
paul@0 | 284 | |
paul@0 | 285 | /* Obtain a capability for the keypad data. */ |
paul@0 | 286 | |
paul@0 | 287 | mem = l4re_util_cap_alloc(); |
paul@0 | 288 | if (l4_is_invalid_cap(mem)) return 1; |
paul@0 | 289 | |
paul@0 | 290 | /* Obtain a reference to the keypad data. */ |
paul@0 | 291 | |
paul@0 | 292 | l4_utcb_br()->bdr = 0; |
paul@0 | 293 | l4_utcb_br()->br[0] = L4_RCV_ITEM_SINGLE_CAP | mem; |
paul@0 | 294 | |
paul@0 | 295 | tag = l4_ipc_call(keypad_server, l4_utcb(), |
paul@0 | 296 | l4_msgtag(0, 0, 0, 0), /* label zero, zero words, zero *sent* items */ |
paul@0 | 297 | L4_IPC_NEVER); |
paul@0 | 298 | |
paul@0 | 299 | if (l4_ipc_error(tag, l4_utcb())) return 1; |
paul@0 | 300 | |
paul@0 | 301 | /* Attach the keypad data to a region in this task. */ |
paul@0 | 302 | |
paul@142 | 303 | if (l4re_rm_attach(&keymem, l4re_ds_size(mem), L4RE_RM_F_SEARCH_ADDR, mem, 0, |
paul@0 | 304 | L4_PAGESHIFT)) |
paul@0 | 305 | return 1; |
paul@0 | 306 | |
paul@0 | 307 | /* Show the keypad state. */ |
paul@0 | 308 | |
paul@0 | 309 | keypad = (uint32_t *) keymem; |
paul@0 | 310 | |
paul@0 | 311 | while (1) show_keypad(); |
paul@0 | 312 | |
paul@0 | 313 | return 0; |
paul@0 | 314 | } |