source: mainline/console/gcons.c@ 2400469

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2400469 was a7d2d78, checked in by Ondrej Palkovsky <ondrap@…>, 19 years ago

Completed graphical console.

  • Property mode set to 100644
File size: 9.2 KB
Line 
1/*
2 * Copyright (C) 2006 Ondrej Palkovsky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <ipc/fb.h>
30#include <ipc/ipc.h>
31#include <async.h>
32#include <stdio.h>
33#include <sys/mman.h>
34#include <string.h>
35#include <align.h>
36
37#include "console.h"
38#include "gcons.h"
39
40#define CONSOLE_TOP 65
41#define CONSOLE_MARGIN 6
42
43#define STATUS_START 110
44#define STATUS_TOP 8
45#define STATUS_SPACE 3
46#define STATUS_WIDTH 48
47#define STATUS_HEIGHT 48
48
49#define MAIN_COLOR 0xffffff
50
51static int use_gcons = 0;
52static ipcarg_t xres,yres;
53
54enum butstate {
55 CONS_DISCONNECTED = 0,
56 CONS_SELECTED,
57 CONS_IDLE,
58 CONS_HAS_DATA,
59 CONS_KERNEL,
60 CONS_DISCONNECTED_SEL,
61 CONS_LAST
62};
63
64static int console_vp;
65static int cstatus_vp[CONSOLE_COUNT];
66static int cstat_row, cstat_col; /* Size of cstatus buttons */
67static enum butstate console_state[CONSOLE_COUNT];
68
69static int fbphone;
70
71/** List of pixmaps identifying these icons */
72static int ic_pixmaps[CONS_LAST] = {-1,-1,-1,-1,-1,-1};
73
74static int active_console = 0;
75
76static void vp_switch(int vp)
77{
78 nsend_call(fbphone,FB_VIEWPORT_SWITCH, vp);
79}
80
81/** Create view port */
82static int vp_create(unsigned int x, unsigned int y,
83 unsigned int width, unsigned int height)
84{
85 /* Init function, use ipc_call_sync */
86 return ipc_call_sync_2(fbphone, FB_VIEWPORT_CREATE,
87 (x << 16) | y, (width << 16) | height,
88 NULL, NULL);
89}
90
91static void clear(void)
92{
93 nsend_call(fbphone, FB_CLEAR, 0);
94
95}
96
97static void set_style(int fgcolor, int bgcolor)
98{
99 nsend_call_2(fbphone, FB_SET_STYLE, fgcolor, bgcolor);
100}
101
102static void putch(char c, int row, int col)
103{
104 nsend_call_3(fbphone, FB_PUTCHAR, c, row, col);
105}
106
107static void redraw_state(int consnum)
108{
109 char data[5];
110 int i;
111 enum butstate state = console_state[consnum];
112
113 vp_switch(cstatus_vp[consnum]);
114 if (ic_pixmaps[state] != -1)
115 nsend_call_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[consnum], ic_pixmaps[state]);
116
117 if (state != CONS_DISCONNECTED && state != CONS_KERNEL && state != CONS_DISCONNECTED_SEL) {
118 snprintf(data, 5, "%d", consnum+1);
119 for (i=0;data[i];i++)
120 putch(data[i], 1, 2+i);
121 }
122}
123
124/** Notification run on changing console (except kernel console) */
125void gcons_change_console(int consnum)
126{
127 int i;
128
129 if (!use_gcons)
130 return;
131
132 if (active_console == KERNEL_CONSOLE) {
133 for (i=0; i < CONSOLE_COUNT; i++)
134 redraw_state(i);
135 } else {
136 if (console_state[active_console] == CONS_DISCONNECTED_SEL)
137 console_state[active_console] = CONS_DISCONNECTED;
138 else
139 console_state[active_console] = CONS_IDLE;
140 redraw_state(active_console);
141 }
142 active_console = consnum;
143
144 if (console_state[consnum] == CONS_DISCONNECTED) {
145 console_state[consnum] = CONS_DISCONNECTED_SEL;
146 redraw_state(consnum);
147 } else
148 console_state[consnum] = CONS_SELECTED;
149 redraw_state(consnum);
150
151 vp_switch(console_vp);
152}
153
154/** Notification function that gets called on new output to virtual console */
155void gcons_notify_char(int consnum)
156{
157 if (!use_gcons)
158 return;
159
160 if (consnum == active_console || console_state[consnum] == CONS_HAS_DATA)
161 return;
162
163 console_state[consnum] = CONS_HAS_DATA;
164
165 if (active_console == KERNEL_CONSOLE)
166 return;
167
168 redraw_state(consnum);
169
170 vp_switch(console_vp);
171}
172
173void gcons_notify_connect(int consnum)
174{
175 if (!use_gcons)
176 return;
177 if (active_console == consnum)
178 console_state[consnum] = CONS_SELECTED;
179 else
180 console_state[consnum] = CONS_IDLE;
181
182 if (active_console == KERNEL_CONSOLE)
183 return;
184
185 redraw_state(consnum);
186 vp_switch(console_vp);
187}
188
189/** Change to kernel console */
190void gcons_in_kernel(void)
191{
192 if (console_state[active_console] = CONS_DISCONNECTED_SEL)
193 console_state[active_console] = CONS_DISCONNECTED;
194 else
195 console_state[active_console] = CONS_IDLE;
196 redraw_state(active_console);
197
198 active_console = KERNEL_CONSOLE; /* Set to kernel console */
199 vp_switch(0);
200}
201
202/** Draw a PPM pixmap to framebuffer
203 *
204 * @param logo Pointer to PPM data
205 * @param size Size of PPM data
206 * @param x Coordinate of upper left corner
207 * @param y Coordinate of upper left corner
208 */
209static void draw_pixmap(char *logo, size_t size, int x, int y)
210{
211 char *shm;
212 int rc;
213
214 /* Create area */
215 shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
216 if (shm == MAP_FAILED)
217 return;
218
219 memcpy(shm, logo, size);
220 /* Send area */
221 rc = sync_send_2(fbphone, FB_PREPARE_SHM, (ipcarg_t)shm, 0, NULL, NULL);
222 if (rc)
223 goto exit;
224 rc = sync_send_3(fbphone, IPC_M_AS_AREA_SEND, (ipcarg_t)shm, 0, PROTO_READ, NULL, NULL, NULL);
225 if (rc)
226 goto drop;
227 /* Draw logo */
228 nsend_call_2(fbphone, FB_DRAW_PPM, x, y);
229drop:
230 /* Drop area */
231 nsend_call(fbphone, FB_DROP_SHM, 0);
232exit:
233 /* Remove area */
234 munmap(shm, size);
235}
236
237extern char _binary_helenos_ppm_start[0];
238extern int _binary_helenos_ppm_size;
239extern char _binary_nameic_ppm_start[0];
240extern int _binary_nameic_ppm_size;
241static void gcons_redraw_console(void)
242{
243 int i;
244 size_t hsize = (size_t)&_binary_helenos_ppm_size;
245
246 if (!use_gcons)
247 return;
248
249 vp_switch(0);
250 set_style(MAIN_COLOR, MAIN_COLOR);
251 clear();
252 draw_pixmap(_binary_helenos_ppm_start, (size_t)&_binary_helenos_ppm_size, xres-66, 2);
253 draw_pixmap(_binary_nameic_ppm_start, (size_t)&_binary_nameic_ppm_size, 5, 17);
254
255
256 for (i=0;i < CONSOLE_COUNT; i++)
257 redraw_state(i);
258 vp_switch(console_vp);
259}
260
261static int make_pixmap(char *data, int size)
262{
263 char *shm;
264 int rc;
265 int pxid = -1;
266
267 /* Create area */
268 shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
269 if (shm == MAP_FAILED)
270 return -1;
271
272 memcpy(shm, data, size);
273 /* Send area */
274 rc = sync_send_2(fbphone, FB_PREPARE_SHM, (ipcarg_t)shm, 0, NULL, NULL);
275 if (rc)
276 goto exit;
277 rc = sync_send_3(fbphone, IPC_M_AS_AREA_SEND, (ipcarg_t)shm, 0, PROTO_READ, NULL, NULL, NULL);
278 if (rc)
279 goto drop;
280
281 /* Obtain pixmap */
282 rc = sync_send(fbphone, FB_SHM2PIXMAP, 0, NULL);
283 if (rc < 0)
284 goto drop;
285 pxid = rc;
286drop:
287 /* Drop area */
288 nsend_call(fbphone, FB_DROP_SHM, 0);
289exit:
290 /* Remove area */
291 munmap(shm, size);
292
293 return pxid;
294}
295
296extern char _binary_cons_selected_ppm_start[0];
297extern int _binary_cons_selected_ppm_size;
298extern char _binary_cons_idle_ppm_start[0];
299extern int _binary_cons_idle_ppm_size;
300extern char _binary_cons_has_data_ppm_start[0];
301extern int _binary_cons_has_data_ppm_size;
302extern char _binary_cons_kernel_ppm_start[0];
303extern int _binary_cons_kernel_ppm_size;
304/** Initialize nice graphical console environment */
305void gcons_init(int phone)
306{
307 int rc;
308 int i;
309
310 fbphone = phone;
311
312 rc = ipc_call_sync_2(phone, FB_GET_RESOLUTION, 0, 0, &xres, &yres);
313 if (rc)
314 return;
315
316 if (xres < 800 || yres < 600)
317 return;
318
319 /* create console viewport */
320 /* Align width & height to character size */
321 console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
322 ALIGN_DOWN(xres-2*CONSOLE_MARGIN, 8),
323 ALIGN_DOWN(yres-(CONSOLE_TOP+CONSOLE_MARGIN),16));
324 if (console_vp < 0)
325 return;
326
327 /* Create status buttons */
328 for (i=0; i < CONSOLE_COUNT; i++) {
329 cstatus_vp[i] = vp_create(STATUS_START+CONSOLE_MARGIN+i*(STATUS_WIDTH+STATUS_SPACE),
330 STATUS_TOP, STATUS_WIDTH, STATUS_HEIGHT);
331 if (cstatus_vp[i] < 0)
332 return;
333 vp_switch(cstatus_vp[i]);
334 set_style(0x202020, 0xffffff);
335 }
336
337 /* Initialize icons */
338 ic_pixmaps[CONS_SELECTED] = make_pixmap(_binary_cons_selected_ppm_start,
339 (int)&_binary_cons_selected_ppm_size);
340 ic_pixmaps[CONS_IDLE] = make_pixmap(_binary_cons_idle_ppm_start,
341 (int)&_binary_cons_idle_ppm_size);
342 ic_pixmaps[CONS_HAS_DATA] = make_pixmap(_binary_cons_has_data_ppm_start,
343 (int)&_binary_cons_has_data_ppm_size);
344 ic_pixmaps[CONS_DISCONNECTED] = make_pixmap(_binary_cons_idle_ppm_start,
345 (int)&_binary_cons_idle_ppm_size);
346 ic_pixmaps[CONS_KERNEL] = make_pixmap(_binary_cons_kernel_ppm_start,
347 (int)&_binary_cons_kernel_ppm_size);
348 ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
349
350 use_gcons = 1;
351 console_state[0] = CONS_DISCONNECTED_SEL;
352 console_state[KERNEL_CONSOLE] = CONS_KERNEL;
353 gcons_redraw_console();
354}
Note: See TracBrowser for help on using the repository browser.