source: mainline/console/gcons.c@ 51dbadf3

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

Added correct disconnect handling.

  • Property mode set to 100644
File size: 9.9 KB
RevLine 
[b1f51f0]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>
[e1c4849]31#include <async.h>
32#include <stdio.h>
[90f5d64]33#include <sys/mman.h>
34#include <string.h>
[a7d2d78]35#include <align.h>
[b1f51f0]36
37#include "console.h"
[e1c4849]38#include "gcons.h"
[b1f51f0]39
[90f5d64]40#define CONSOLE_TOP 65
[a7d2d78]41#define CONSOLE_MARGIN 6
[b1f51f0]42
[a7d2d78]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
[b1f51f0]48
[90f5d64]49#define MAIN_COLOR 0xffffff
[e1c4849]50
[b1f51f0]51static int use_gcons = 0;
52static ipcarg_t xres,yres;
53
[a7d2d78]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
[b1f51f0]64static int console_vp;
65static int cstatus_vp[CONSOLE_COUNT];
[e1c4849]66static int cstat_row, cstat_col; /* Size of cstatus buttons */
[a7d2d78]67static enum butstate console_state[CONSOLE_COUNT];
[b1f51f0]68
69static int fbphone;
70
[a7d2d78]71/** List of pixmaps identifying these icons */
72static int ic_pixmaps[CONS_LAST] = {-1,-1,-1,-1,-1,-1};
[e1c4849]73
74static int active_console = 0;
75
[b1f51f0]76static void vp_switch(int vp)
77{
[e1c4849]78 nsend_call(fbphone,FB_VIEWPORT_SWITCH, vp);
[b1f51f0]79}
80
[e1c4849]81/** Create view port */
[b1f51f0]82static int vp_create(unsigned int x, unsigned int y,
[e1c4849]83 unsigned int width, unsigned int height)
[b1f51f0]84{
[e1c4849]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);
[b1f51f0]89}
90
[e1c4849]91static void clear(void)
[b1f51f0]92{
[e1c4849]93 nsend_call(fbphone, FB_CLEAR, 0);
[b1f51f0]94
95}
96
[e1c4849]97static void set_style(int fgcolor, int bgcolor)
98{
99 nsend_call_2(fbphone, FB_SET_STYLE, fgcolor, bgcolor);
100}
101
[d530237a]102/** Transparent putchar */
103static void tran_putch(char c, int row, int col)
[e1c4849]104{
[d530237a]105 nsend_call_3(fbphone, FB_TRANS_PUTCHAR, c, row, col);
[e1c4849]106}
107
[d530237a]108/** Redraw the button showing state of a given console */
[a7d2d78]109static void redraw_state(int consnum)
[b1f51f0]110{
[e1c4849]111 char data[5];
112 int i;
[a7d2d78]113 enum butstate state = console_state[consnum];
114
[e1c4849]115 vp_switch(cstatus_vp[consnum]);
[a7d2d78]116 if (ic_pixmaps[state] != -1)
117 nsend_call_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[consnum], ic_pixmaps[state]);
118
119 if (state != CONS_DISCONNECTED && state != CONS_KERNEL && state != CONS_DISCONNECTED_SEL) {
120 snprintf(data, 5, "%d", consnum+1);
121 for (i=0;data[i];i++)
[d530237a]122 tran_putch(data[i], 1, 2+i);
[a7d2d78]123 }
[b1f51f0]124}
125
[a7d2d78]126/** Notification run on changing console (except kernel console) */
[b1f51f0]127void gcons_change_console(int consnum)
128{
[a7d2d78]129 int i;
130
[b1f51f0]131 if (!use_gcons)
132 return;
[429acb9]133
[a7d2d78]134 if (active_console == KERNEL_CONSOLE) {
135 for (i=0; i < CONSOLE_COUNT; i++)
136 redraw_state(i);
137 } else {
138 if (console_state[active_console] == CONS_DISCONNECTED_SEL)
139 console_state[active_console] = CONS_DISCONNECTED;
140 else
141 console_state[active_console] = CONS_IDLE;
142 redraw_state(active_console);
143 }
[e1c4849]144 active_console = consnum;
[a7d2d78]145
146 if (console_state[consnum] == CONS_DISCONNECTED) {
147 console_state[consnum] = CONS_DISCONNECTED_SEL;
148 redraw_state(consnum);
149 } else
150 console_state[consnum] = CONS_SELECTED;
151 redraw_state(consnum);
[d6cc453]152
[b1f51f0]153 vp_switch(console_vp);
154}
155
[429acb9]156/** Notification function that gets called on new output to virtual console */
[b1f51f0]157void gcons_notify_char(int consnum)
158{
159 if (!use_gcons)
160 return;
161
[a7d2d78]162 if (consnum == active_console || console_state[consnum] == CONS_HAS_DATA)
[d6cc453]163 return;
164
[a7d2d78]165 console_state[consnum] = CONS_HAS_DATA;
[429acb9]166
[a7d2d78]167 if (active_console == KERNEL_CONSOLE)
[429acb9]168 return;
169
[a7d2d78]170 redraw_state(consnum);
[d6cc453]171
[b1f51f0]172 vp_switch(console_vp);
[a7d2d78]173}
[429acb9]174
[e9073f2]175/** Notification function called on service disconnect from console */
176void gcons_notify_disconnect(int consnum)
177{
178 if (!use_gcons)
179 return;
180 if (active_console == consnum)
181 console_state[consnum] = CONS_DISCONNECTED_SEL;
182 else
183 console_state[consnum] = CONS_DISCONNECTED;
184
185 if (active_console == KERNEL_CONSOLE)
186 return;
187
188 redraw_state(consnum);
189 vp_switch(console_vp);
190}
191
[d530237a]192/** Notification function called on console connect */
[a7d2d78]193void gcons_notify_connect(int consnum)
194{
195 if (!use_gcons)
196 return;
197 if (active_console == consnum)
198 console_state[consnum] = CONS_SELECTED;
199 else
200 console_state[consnum] = CONS_IDLE;
201
202 if (active_console == KERNEL_CONSOLE)
203 return;
204
205 redraw_state(consnum);
206 vp_switch(console_vp);
[b1f51f0]207}
208
[429acb9]209/** Change to kernel console */
210void gcons_in_kernel(void)
211{
[a78e273]212 if (console_state[active_console] == CONS_DISCONNECTED_SEL)
[a7d2d78]213 console_state[active_console] = CONS_DISCONNECTED;
214 else
215 console_state[active_console] = CONS_IDLE;
216 redraw_state(active_console);
217
218 active_console = KERNEL_CONSOLE; /* Set to kernel console */
[429acb9]219 vp_switch(0);
220}
221
222/** Draw a PPM pixmap to framebuffer
223 *
224 * @param logo Pointer to PPM data
225 * @param size Size of PPM data
226 * @param x Coordinate of upper left corner
227 * @param y Coordinate of upper left corner
228 */
[90f5d64]229static void draw_pixmap(char *logo, size_t size, int x, int y)
230{
231 char *shm;
232 int rc;
233
234 /* Create area */
235 shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
236 if (shm == MAP_FAILED)
237 return;
238
239 memcpy(shm, logo, size);
240 /* Send area */
241 rc = sync_send_2(fbphone, FB_PREPARE_SHM, (ipcarg_t)shm, 0, NULL, NULL);
242 if (rc)
243 goto exit;
244 rc = sync_send_3(fbphone, IPC_M_AS_AREA_SEND, (ipcarg_t)shm, 0, PROTO_READ, NULL, NULL, NULL);
245 if (rc)
246 goto drop;
247 /* Draw logo */
[a7d2d78]248 nsend_call_2(fbphone, FB_DRAW_PPM, x, y);
[90f5d64]249drop:
250 /* Drop area */
251 nsend_call(fbphone, FB_DROP_SHM, 0);
252exit:
253 /* Remove area */
254 munmap(shm, size);
255}
256
257extern char _binary_helenos_ppm_start[0];
258extern int _binary_helenos_ppm_size;
259extern char _binary_nameic_ppm_start[0];
260extern int _binary_nameic_ppm_size;
[d530237a]261/** Redraws console graphics */
[a7d2d78]262static void gcons_redraw_console(void)
[b1f51f0]263{
[e1c4849]264 int i;
[90f5d64]265 size_t hsize = (size_t)&_binary_helenos_ppm_size;
[e1c4849]266
[b1f51f0]267 if (!use_gcons)
268 return;
269
270 vp_switch(0);
[e1c4849]271 set_style(MAIN_COLOR, MAIN_COLOR);
272 clear();
[a7d2d78]273 draw_pixmap(_binary_helenos_ppm_start, (size_t)&_binary_helenos_ppm_size, xres-66, 2);
274 draw_pixmap(_binary_nameic_ppm_start, (size_t)&_binary_nameic_ppm_size, 5, 17);
[90f5d64]275
[e1c4849]276 for (i=0;i < CONSOLE_COUNT; i++)
[a7d2d78]277 redraw_state(i);
[b1f51f0]278 vp_switch(console_vp);
279}
280
[d530237a]281/** Creates a pixmap on framebuffer
282 *
283 * @param data PPM data
284 * @param size PPM data size
285 * @return Pixmap identification
286 */
[a7d2d78]287static int make_pixmap(char *data, int size)
288{
289 char *shm;
290 int rc;
291 int pxid = -1;
292
293 /* Create area */
294 shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
295 if (shm == MAP_FAILED)
296 return -1;
297
298 memcpy(shm, data, size);
299 /* Send area */
300 rc = sync_send_2(fbphone, FB_PREPARE_SHM, (ipcarg_t)shm, 0, NULL, NULL);
301 if (rc)
302 goto exit;
303 rc = sync_send_3(fbphone, IPC_M_AS_AREA_SEND, (ipcarg_t)shm, 0, PROTO_READ, NULL, NULL, NULL);
304 if (rc)
305 goto drop;
306
307 /* Obtain pixmap */
308 rc = sync_send(fbphone, FB_SHM2PIXMAP, 0, NULL);
309 if (rc < 0)
310 goto drop;
311 pxid = rc;
312drop:
313 /* Drop area */
314 nsend_call(fbphone, FB_DROP_SHM, 0);
315exit:
316 /* Remove area */
317 munmap(shm, size);
318
319 return pxid;
320}
321
322extern char _binary_cons_selected_ppm_start[0];
323extern int _binary_cons_selected_ppm_size;
324extern char _binary_cons_idle_ppm_start[0];
325extern int _binary_cons_idle_ppm_size;
326extern char _binary_cons_has_data_ppm_start[0];
327extern int _binary_cons_has_data_ppm_size;
328extern char _binary_cons_kernel_ppm_start[0];
329extern int _binary_cons_kernel_ppm_size;
[b1f51f0]330/** Initialize nice graphical console environment */
331void gcons_init(int phone)
332{
333 int rc;
334 int i;
335
336 fbphone = phone;
337
338 rc = ipc_call_sync_2(phone, FB_GET_RESOLUTION, 0, 0, &xres, &yres);
339 if (rc)
340 return;
341
342 if (xres < 800 || yres < 600)
343 return;
344
345 /* create console viewport */
[a7d2d78]346 /* Align width & height to character size */
347 console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
348 ALIGN_DOWN(xres-2*CONSOLE_MARGIN, 8),
349 ALIGN_DOWN(yres-(CONSOLE_TOP+CONSOLE_MARGIN),16));
[b1f51f0]350 if (console_vp < 0)
351 return;
352
353 /* Create status buttons */
354 for (i=0; i < CONSOLE_COUNT; i++) {
[90f5d64]355 cstatus_vp[i] = vp_create(STATUS_START+CONSOLE_MARGIN+i*(STATUS_WIDTH+STATUS_SPACE),
[a7d2d78]356 STATUS_TOP, STATUS_WIDTH, STATUS_HEIGHT);
[b1f51f0]357 if (cstatus_vp[i] < 0)
358 return;
[a7d2d78]359 vp_switch(cstatus_vp[i]);
360 set_style(0x202020, 0xffffff);
[b1f51f0]361 }
362
[a7d2d78]363 /* Initialize icons */
364 ic_pixmaps[CONS_SELECTED] = make_pixmap(_binary_cons_selected_ppm_start,
365 (int)&_binary_cons_selected_ppm_size);
366 ic_pixmaps[CONS_IDLE] = make_pixmap(_binary_cons_idle_ppm_start,
367 (int)&_binary_cons_idle_ppm_size);
368 ic_pixmaps[CONS_HAS_DATA] = make_pixmap(_binary_cons_has_data_ppm_start,
369 (int)&_binary_cons_has_data_ppm_size);
370 ic_pixmaps[CONS_DISCONNECTED] = make_pixmap(_binary_cons_idle_ppm_start,
371 (int)&_binary_cons_idle_ppm_size);
372 ic_pixmaps[CONS_KERNEL] = make_pixmap(_binary_cons_kernel_ppm_start,
373 (int)&_binary_cons_kernel_ppm_size);
374 ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
375
[b1f51f0]376 use_gcons = 1;
[a7d2d78]377 console_state[0] = CONS_DISCONNECTED_SEL;
378 console_state[KERNEL_CONSOLE] = CONS_KERNEL;
[e1c4849]379 gcons_redraw_console();
[b1f51f0]380}
Note: See TracBrowser for help on using the repository browser.