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
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
102/** Transparent putchar */
103static void tran_putch(char c, int row, int col)
104{
105 nsend_call_3(fbphone, FB_TRANS_PUTCHAR, c, row, col);
106}
107
108/** Redraw the button showing state of a given console */
109static void redraw_state(int consnum)
110{
111 char data[5];
112 int i;
113 enum butstate state = console_state[consnum];
114
115 vp_switch(cstatus_vp[consnum]);
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++)
122 tran_putch(data[i], 1, 2+i);
123 }
124}
125
126/** Notification run on changing console (except kernel console) */
127void gcons_change_console(int consnum)
128{
129 int i;
130
131 if (!use_gcons)
132 return;
133
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 }
144 active_console = consnum;
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);
152
153 vp_switch(console_vp);
154}
155
156/** Notification function that gets called on new output to virtual console */
157void gcons_notify_char(int consnum)
158{
159 if (!use_gcons)
160 return;
161
162 if (consnum == active_console || console_state[consnum] == CONS_HAS_DATA)
163 return;
164
165 console_state[consnum] = CONS_HAS_DATA;
166
167 if (active_console == KERNEL_CONSOLE)
168 return;
169
170 redraw_state(consnum);
171
172 vp_switch(console_vp);
173}
174
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
192/** Notification function called on console connect */
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);
207}
208
209/** Change to kernel console */
210void gcons_in_kernel(void)
211{
212 if (console_state[active_console] == CONS_DISCONNECTED_SEL)
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 */
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 */
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 */
248 nsend_call_2(fbphone, FB_DRAW_PPM, x, y);
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;
261/** Redraws console graphics */
262static void gcons_redraw_console(void)
263{
264 int i;
265 size_t hsize = (size_t)&_binary_helenos_ppm_size;
266
267 if (!use_gcons)
268 return;
269
270 vp_switch(0);
271 set_style(MAIN_COLOR, MAIN_COLOR);
272 clear();
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);
275
276 for (i=0;i < CONSOLE_COUNT; i++)
277 redraw_state(i);
278 vp_switch(console_vp);
279}
280
281/** Creates a pixmap on framebuffer
282 *
283 * @param data PPM data
284 * @param size PPM data size
285 * @return Pixmap identification
286 */
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;
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 */
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));
350 if (console_vp < 0)
351 return;
352
353 /* Create status buttons */
354 for (i=0; i < CONSOLE_COUNT; i++) {
355 cstatus_vp[i] = vp_create(STATUS_START+CONSOLE_MARGIN+i*(STATUS_WIDTH+STATUS_SPACE),
356 STATUS_TOP, STATUS_WIDTH, STATUS_HEIGHT);
357 if (cstatus_vp[i] < 0)
358 return;
359 vp_switch(cstatus_vp[i]);
360 set_style(0x202020, 0xffffff);
361 }
362
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
376 use_gcons = 1;
377 console_state[0] = CONS_DISCONNECTED_SEL;
378 console_state[KERNEL_CONSOLE] = CONS_KERNEL;
379 gcons_redraw_console();
380}
Note: See TracBrowser for help on using the repository browser.