source: mainline/uspace/srv/console/gcons.c@ 1601f3c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1601f3c was 1601f3c, checked in by Martin Decky <martin@…>, 16 years ago

console cleanup (no functional changes)

  • Property mode set to 100644
File size: 12.4 KB
RevLine 
[b1f51f0]1/*
[df4ed85]2 * Copyright (c) 2006 Ondrej Palkovsky
[b1f51f0]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
[ce5bcb4]29/** @addtogroup console
[1601f3c]30 * @{
[ce5bcb4]31 */
32/** @file
33 */
34
[b1f51f0]35#include <ipc/fb.h>
36#include <ipc/ipc.h>
[e1c4849]37#include <async.h>
38#include <stdio.h>
[2def788]39#include <sys/mman.h>
[90f5d64]40#include <string.h>
[a7d2d78]41#include <align.h>
[b1f51f0]42
43#include "console.h"
[e1c4849]44#include "gcons.h"
[b1f51f0]45
[1601f3c]46#define CONSOLE_TOP 66
47#define CONSOLE_MARGIN 6
[b1f51f0]48
[1601f3c]49#define STATUS_START 110
50#define STATUS_TOP 8
51#define STATUS_SPACE 4
52#define STATUS_WIDTH 48
53#define STATUS_HEIGHT 48
[b1f51f0]54
[1601f3c]55#define MAIN_COLOR 0xffffff
[e1c4849]56
[b1f51f0]57static int use_gcons = 0;
58static ipcarg_t xres,yres;
59
[a7d2d78]60enum butstate {
61 CONS_DISCONNECTED = 0,
62 CONS_SELECTED,
63 CONS_IDLE,
64 CONS_HAS_DATA,
65 CONS_KERNEL,
66 CONS_DISCONNECTED_SEL,
67 CONS_LAST
68};
69
[b1f51f0]70static int console_vp;
71static int cstatus_vp[CONSOLE_COUNT];
[a7d2d78]72static enum butstate console_state[CONSOLE_COUNT];
[b1f51f0]73
74static int fbphone;
75
[a7d2d78]76/** List of pixmaps identifying these icons */
[00bb6965]77static int ic_pixmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
[1fd7700]78static int animation = -1;
[e1c4849]79
80static int active_console = 0;
81
[b1f51f0]82static void vp_switch(int vp)
83{
[76fca31]84 async_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
[b1f51f0]85}
86
[e1c4849]87/** Create view port */
[0cc4313]88static int vp_create(unsigned int x, unsigned int y, unsigned int width,
89 unsigned int height)
[b1f51f0]90{
[0cc4313]91 return async_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
92 (width << 16) | height);
[b1f51f0]93}
94
[e1c4849]95static void clear(void)
[b1f51f0]96{
[0cc4313]97 async_msg_0(fbphone, FB_CLEAR);
[b1f51f0]98}
99
[9805cde]100static void set_rgb_color(int fgcolor, int bgcolor)
[e1c4849]101{
[9805cde]102 async_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
[e1c4849]103}
104
[d530237a]105/** Transparent putchar */
106static void tran_putch(char c, int row, int col)
[e1c4849]107{
[76fca31]108 async_msg_3(fbphone, FB_PUTCHAR, c, row, col);
[e1c4849]109}
110
[d530237a]111/** Redraw the button showing state of a given console */
[a7d2d78]112static void redraw_state(int consnum)
[b1f51f0]113{
[e1c4849]114 char data[5];
115 int i;
[a7d2d78]116 enum butstate state = console_state[consnum];
[1601f3c]117
[e1c4849]118 vp_switch(cstatus_vp[consnum]);
[a7d2d78]119 if (ic_pixmaps[state] != -1)
[00bb6965]120 async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[consnum],
[0cc4313]121 ic_pixmaps[state]);
[1601f3c]122
123 if (state != CONS_DISCONNECTED && state != CONS_KERNEL &&
124 state != CONS_DISCONNECTED_SEL) {
125 snprintf(data, 5, "%d", consnum + 1);
126 for (i = 0; data[i]; i++)
127 tran_putch(data[i], 1, 2 + i);
128 }
[b1f51f0]129}
130
[a7d2d78]131/** Notification run on changing console (except kernel console) */
[b1f51f0]132void gcons_change_console(int consnum)
133{
[a7d2d78]134 int i;
[1601f3c]135
[b1f51f0]136 if (!use_gcons)
137 return;
[1601f3c]138
[a7d2d78]139 if (active_console == KERNEL_CONSOLE) {
[00bb6965]140 for (i = 0; i < CONSOLE_COUNT; i++)
[a7d2d78]141 redraw_state(i);
[70178b74]142 if (animation != -1)
[0cc4313]143 async_msg_1(fbphone, FB_ANIM_START, animation);
[a7d2d78]144 } else {
145 if (console_state[active_console] == CONS_DISCONNECTED_SEL)
146 console_state[active_console] = CONS_DISCONNECTED;
147 else
148 console_state[active_console] = CONS_IDLE;
149 redraw_state(active_console);
150 }
[e1c4849]151 active_console = consnum;
[1601f3c]152
[a7d2d78]153 if (console_state[consnum] == CONS_DISCONNECTED) {
154 console_state[consnum] = CONS_DISCONNECTED_SEL;
155 redraw_state(consnum);
156 } else
157 console_state[consnum] = CONS_SELECTED;
158 redraw_state(consnum);
[1601f3c]159
[b1f51f0]160 vp_switch(console_vp);
161}
162
[429acb9]163/** Notification function that gets called on new output to virtual console */
[b1f51f0]164void gcons_notify_char(int consnum)
165{
166 if (!use_gcons)
167 return;
[1601f3c]168
169 if ((consnum == active_console) ||
170 (console_state[consnum] == CONS_HAS_DATA))
[d6cc453]171 return;
[1601f3c]172
[a7d2d78]173 console_state[consnum] = CONS_HAS_DATA;
[1601f3c]174
[a7d2d78]175 if (active_console == KERNEL_CONSOLE)
[429acb9]176 return;
[1601f3c]177
[a7d2d78]178 redraw_state(consnum);
[d6cc453]179
[b1f51f0]180 vp_switch(console_vp);
[a7d2d78]181}
[429acb9]182
[e9073f2]183/** Notification function called on service disconnect from console */
184void gcons_notify_disconnect(int consnum)
185{
186 if (!use_gcons)
187 return;
[1601f3c]188
[e9073f2]189 if (active_console == consnum)
190 console_state[consnum] = CONS_DISCONNECTED_SEL;
191 else
192 console_state[consnum] = CONS_DISCONNECTED;
[76fca31]193
[e9073f2]194 if (active_console == KERNEL_CONSOLE)
195 return;
[76fca31]196
[e9073f2]197 redraw_state(consnum);
198 vp_switch(console_vp);
199}
200
[d530237a]201/** Notification function called on console connect */
[a7d2d78]202void gcons_notify_connect(int consnum)
203{
204 if (!use_gcons)
205 return;
[1601f3c]206
[a7d2d78]207 if (active_console == consnum)
208 console_state[consnum] = CONS_SELECTED;
209 else
210 console_state[consnum] = CONS_IDLE;
[1601f3c]211
[a7d2d78]212 if (active_console == KERNEL_CONSOLE)
213 return;
[1601f3c]214
[a7d2d78]215 redraw_state(consnum);
216 vp_switch(console_vp);
[b1f51f0]217}
218
[429acb9]219/** Change to kernel console */
220void gcons_in_kernel(void)
221{
[70178b74]222 if (animation != -1)
[0cc4313]223 async_msg_1(fbphone, FB_ANIM_STOP, animation);
[76fca31]224
225 active_console = KERNEL_CONSOLE;
[429acb9]226 vp_switch(0);
227}
228
[d8b42fb2]229/** Return x, where left <= x <= right && |a-x|==min(|a-x|) is smallest */
[1601f3c]230static inline int limit(int a, int left, int right)
[830ac99]231{
232 if (a < left)
233 a = left;
234 if (a >= right)
235 a = right - 1;
236 return a;
237}
238
[1f83244]239int mouse_x, mouse_y;
240int btn_pressed, btn_x, btn_y;
241
242/** Handle mouse move
243 *
244 * @param dx Delta X of mouse move
245 * @param dy Delta Y of mouse move
246 */
[830ac99]247void gcons_mouse_move(int dx, int dy)
248{
[f15cb3c4]249 mouse_x = limit(mouse_x + dx, 0, xres);
250 mouse_y = limit(mouse_y + dy, 0, yres);
[1601f3c]251
[1f83244]252 async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
253}
254
255static int gcons_find_conbut(int x, int y)
256{
[f15cb3c4]257 int status_start = STATUS_START + (xres - 800) / 2;
[1601f3c]258
259 if ((y < STATUS_TOP) || (y >= STATUS_TOP + STATUS_HEIGHT))
[1f83244]260 return -1;
261
262 if (x < status_start)
263 return -1;
264
[00bb6965]265 if (x >= status_start + (STATUS_WIDTH + STATUS_SPACE) * CONSOLE_COUNT)
[1f83244]266 return -1;
[f15cb3c4]267 if (((x - status_start) % (STATUS_WIDTH + STATUS_SPACE)) < STATUS_SPACE)
[1f83244]268 return -1;
269
[f15cb3c4]270 return (x - status_start) / (STATUS_WIDTH + STATUS_SPACE);
[1f83244]271}
[830ac99]272
[1f83244]273/** Handle mouse click
274 *
275 * @param state New state (1-pressed, 0-depressed)
276 */
277int gcons_mouse_btn(int state)
278{
279 int conbut;
[1601f3c]280
[1f83244]281 if (state) {
282 conbut = gcons_find_conbut(mouse_x, mouse_y);
283 if (conbut != -1) {
284 btn_pressed = 1;
285 btn_x = mouse_x;
286 btn_y = mouse_y;
287 }
288 return -1;
[1601f3c]289 }
290
291 if ((!state) && (!btn_pressed))
[1f83244]292 return -1;
[1601f3c]293
[1f83244]294 btn_pressed = 0;
[1601f3c]295
[1f83244]296 conbut = gcons_find_conbut(mouse_x, mouse_y);
297 if (conbut == gcons_find_conbut(btn_x, btn_y))
298 return conbut;
[1601f3c]299
[1f83244]300 return -1;
[830ac99]301}
302
303
[429acb9]304/** Draw a PPM pixmap to framebuffer
305 *
306 * @param logo Pointer to PPM data
307 * @param size Size of PPM data
308 * @param x Coordinate of upper left corner
309 * @param y Coordinate of upper left corner
310 */
[90f5d64]311static void draw_pixmap(char *logo, size_t size, int x, int y)
312{
313 char *shm;
314 int rc;
[1601f3c]315
[90f5d64]316 /* Create area */
[00bb6965]317 shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
[0cc4313]318 MAP_ANONYMOUS, 0, 0);
[90f5d64]319 if (shm == MAP_FAILED)
320 return;
[1601f3c]321
[90f5d64]322 memcpy(shm, logo, size);
[1601f3c]323
[90f5d64]324 /* Send area */
[0cc4313]325 rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm);
[90f5d64]326 if (rc)
327 goto exit;
[1601f3c]328
[215e375]329 rc = ipc_share_out_start(fbphone, shm, PROTO_READ);
[90f5d64]330 if (rc)
331 goto drop;
[1601f3c]332
[90f5d64]333 /* Draw logo */
[085bd54]334 async_msg_2(fbphone, FB_DRAW_PPM, x, y);
[1601f3c]335
[90f5d64]336drop:
337 /* Drop area */
[0cc4313]338 async_msg_0(fbphone, FB_DROP_SHM);
[1601f3c]339
340exit:
[90f5d64]341 /* Remove area */
342 munmap(shm, size);
343}
344
[1601f3c]345extern char _binary_gfx_helenos_ppm_start[0];
346extern int _binary_gfx_helenos_ppm_size;
347extern char _binary_gfx_nameic_ppm_start[0];
348extern int _binary_gfx_nameic_ppm_size;
[76fca31]349
350/** Redraws console graphics */
351void gcons_redraw_console(void)
[b1f51f0]352{
[e1c4849]353 int i;
[76fca31]354
[b1f51f0]355 if (!use_gcons)
356 return;
357
358 vp_switch(0);
[9805cde]359 set_rgb_color(MAIN_COLOR, MAIN_COLOR);
[e1c4849]360 clear();
[1601f3c]361 draw_pixmap(_binary_gfx_helenos_ppm_start,
362 (size_t) &_binary_gfx_helenos_ppm_size, xres - 66, 2);
363 draw_pixmap(_binary_gfx_nameic_ppm_start,
364 (size_t) &_binary_gfx_nameic_ppm_size, 5, 17);
[76fca31]365
[0cc4313]366 for (i = 0; i < CONSOLE_COUNT; i++)
[a7d2d78]367 redraw_state(i);
[1601f3c]368
[b1f51f0]369 vp_switch(console_vp);
370}
371
[d530237a]372/** Creates a pixmap on framebuffer
373 *
374 * @param data PPM data
375 * @param size PPM data size
376 * @return Pixmap identification
377 */
[a7d2d78]378static int make_pixmap(char *data, int size)
379{
380 char *shm;
381 int rc;
382 int pxid = -1;
[1601f3c]383
[a7d2d78]384 /* Create area */
[00bb6965]385 shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
[0cc4313]386 MAP_ANONYMOUS, 0, 0);
[a7d2d78]387 if (shm == MAP_FAILED)
388 return -1;
[1601f3c]389
[a7d2d78]390 memcpy(shm, data, size);
[1601f3c]391
[a7d2d78]392 /* Send area */
[0cc4313]393 rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm);
[a7d2d78]394 if (rc)
395 goto exit;
[1601f3c]396
[215e375]397 rc = ipc_share_out_start(fbphone, shm, PROTO_READ);
[a7d2d78]398 if (rc)
399 goto drop;
[1601f3c]400
[a7d2d78]401 /* Obtain pixmap */
[0cc4313]402 rc = async_req_0_0(fbphone, FB_SHM2PIXMAP);
[a7d2d78]403 if (rc < 0)
404 goto drop;
[1601f3c]405
[a7d2d78]406 pxid = rc;
[1601f3c]407
[a7d2d78]408drop:
409 /* Drop area */
[0cc4313]410 async_msg_0(fbphone, FB_DROP_SHM);
[1601f3c]411
412exit:
[a7d2d78]413 /* Remove area */
414 munmap(shm, size);
[1601f3c]415
[a7d2d78]416 return pxid;
417}
418
[1601f3c]419extern char _binary_gfx_anim_1_ppm_start[0];
420extern int _binary_gfx_anim_1_ppm_size;
421extern char _binary_gfx_anim_2_ppm_start[0];
422extern int _binary_gfx_anim_2_ppm_size;
423extern char _binary_gfx_anim_3_ppm_start[0];
424extern int _binary_gfx_anim_3_ppm_size;
425extern char _binary_gfx_anim_4_ppm_start[0];
426extern int _binary_gfx_anim_4_ppm_size;
[00bb6965]427
[1fd7700]428static void make_anim(void)
429{
[1601f3c]430 int an = async_req_1_0(fbphone, FB_ANIM_CREATE, cstatus_vp[KERNEL_CONSOLE]);
[1fd7700]431 if (an < 0)
432 return;
[1601f3c]433
434 int pm = make_pixmap(_binary_gfx_anim_1_ppm_start,
435 (int) &_binary_gfx_anim_1_ppm_size);
[1fd7700]436 async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
[1601f3c]437
438 pm = make_pixmap(_binary_gfx_anim_2_ppm_start,
439 (int) &_binary_gfx_anim_2_ppm_size);
[1fd7700]440 async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
[1601f3c]441
442 pm = make_pixmap(_binary_gfx_anim_3_ppm_start,
443 (int) &_binary_gfx_anim_3_ppm_size);
[1fd7700]444 async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
[1601f3c]445
446 pm = make_pixmap(_binary_gfx_anim_4_ppm_start,
447 (int) &_binary_gfx_anim_4_ppm_size);
[1fd7700]448 async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
[1601f3c]449
[0cc4313]450 async_msg_1(fbphone, FB_ANIM_START, an);
[1601f3c]451
[1fd7700]452 animation = an;
453}
454
[1601f3c]455extern char _binary_gfx_cons_selected_ppm_start[0];
456extern int _binary_gfx_cons_selected_ppm_size;
457extern char _binary_gfx_cons_idle_ppm_start[0];
458extern int _binary_gfx_cons_idle_ppm_size;
459extern char _binary_gfx_cons_has_data_ppm_start[0];
460extern int _binary_gfx_cons_has_data_ppm_size;
461extern char _binary_gfx_cons_kernel_ppm_start[0];
462extern int _binary_gfx_cons_kernel_ppm_size;
[00bb6965]463
[b1f51f0]464/** Initialize nice graphical console environment */
465void gcons_init(int phone)
466{
467 int rc;
468 int i;
[1fd7700]469 int status_start = STATUS_START;
[76fca31]470
[b1f51f0]471 fbphone = phone;
[76fca31]472
[0cc4313]473 rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
[b1f51f0]474 if (rc)
475 return;
476
[76fca31]477 if ((xres < 800) || (yres < 600))
[b1f51f0]478 return;
[76fca31]479
[1601f3c]480 /* Create console viewport */
481
[a7d2d78]482 /* Align width & height to character size */
[d7baee6]483 console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
[0cc4313]484 ALIGN_DOWN(xres - 2 * CONSOLE_MARGIN, 8),
485 ALIGN_DOWN(yres - (CONSOLE_TOP + CONSOLE_MARGIN), 16));
[b1f51f0]486 if (console_vp < 0)
487 return;
488
489 /* Create status buttons */
[00bb6965]490 status_start += (xres - 800) / 2;
491 for (i = 0; i < CONSOLE_COUNT; i++) {
[d7baee6]492 cstatus_vp[i] = vp_create(status_start + CONSOLE_MARGIN +
[0cc4313]493 i * (STATUS_WIDTH + STATUS_SPACE), STATUS_TOP,
494 STATUS_WIDTH, STATUS_HEIGHT);
[b1f51f0]495 if (cstatus_vp[i] < 0)
496 return;
[a7d2d78]497 vp_switch(cstatus_vp[i]);
[9805cde]498 set_rgb_color(0x202020, 0xffffff);
[b1f51f0]499 }
500
[a7d2d78]501 /* Initialize icons */
[00bb6965]502 ic_pixmaps[CONS_SELECTED] =
[1601f3c]503 make_pixmap(_binary_gfx_cons_selected_ppm_start,
504 (int) &_binary_gfx_cons_selected_ppm_size);
505 ic_pixmaps[CONS_IDLE] =
506 make_pixmap(_binary_gfx_cons_idle_ppm_start,
507 (int) &_binary_gfx_cons_idle_ppm_size);
[00bb6965]508 ic_pixmaps[CONS_HAS_DATA] =
[1601f3c]509 make_pixmap(_binary_gfx_cons_has_data_ppm_start,
510 (int) &_binary_gfx_cons_has_data_ppm_size);
[00bb6965]511 ic_pixmaps[CONS_DISCONNECTED] =
[1601f3c]512 make_pixmap(_binary_gfx_cons_idle_ppm_start,
513 (int) &_binary_gfx_cons_idle_ppm_size);
514 ic_pixmaps[CONS_KERNEL] =
515 make_pixmap(_binary_gfx_cons_kernel_ppm_start,
516 (int) &_binary_gfx_cons_kernel_ppm_size);
[a7d2d78]517 ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
[1fd7700]518
519 make_anim();
[76fca31]520
[b1f51f0]521 use_gcons = 1;
[a7d2d78]522 console_state[0] = CONS_DISCONNECTED_SEL;
523 console_state[KERNEL_CONSOLE] = CONS_KERNEL;
[e1c4849]524 gcons_redraw_console();
[b1f51f0]525}
[76fca31]526
[ce5bcb4]527/** @}
528 */
Note: See TracBrowser for help on using the repository browser.