00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <ipc/fb.h>
00036 #include <async.h>
00037 #include <stdio.h>
00038 #include <sys/mman.h>
00039 #include <str.h>
00040 #include <align.h>
00041 #include <bool.h>
00042
00043 #include "console.h"
00044 #include "gcons.h"
00045
00046 #define CONSOLE_TOP 66
00047 #define CONSOLE_MARGIN 6
00048
00049 #define STATUS_START 110
00050 #define STATUS_TOP 8
00051 #define STATUS_SPACE 4
00052 #define STATUS_WIDTH 48
00053 #define STATUS_HEIGHT 48
00054
00055 #define COLOR_MAIN 0xffffff
00056 #define COLOR_FOREGROUND 0x202020
00057 #define COLOR_BACKGROUND 0xffffff
00058
00059 extern char _binary_gfx_helenos_ppm_start[0];
00060 extern int _binary_gfx_helenos_ppm_size;
00061 extern char _binary_gfx_nameic_ppm_start[0];
00062 extern int _binary_gfx_nameic_ppm_size;
00063
00064 extern char _binary_gfx_anim_1_ppm_start[0];
00065 extern int _binary_gfx_anim_1_ppm_size;
00066 extern char _binary_gfx_anim_2_ppm_start[0];
00067 extern int _binary_gfx_anim_2_ppm_size;
00068 extern char _binary_gfx_anim_3_ppm_start[0];
00069 extern int _binary_gfx_anim_3_ppm_size;
00070 extern char _binary_gfx_anim_4_ppm_start[0];
00071 extern int _binary_gfx_anim_4_ppm_size;
00072
00073 extern char _binary_gfx_cons_selected_ppm_start[0];
00074 extern int _binary_gfx_cons_selected_ppm_size;
00075 extern char _binary_gfx_cons_idle_ppm_start[0];
00076 extern int _binary_gfx_cons_idle_ppm_size;
00077 extern char _binary_gfx_cons_has_data_ppm_start[0];
00078 extern int _binary_gfx_cons_has_data_ppm_size;
00079 extern char _binary_gfx_cons_kernel_ppm_start[0];
00080 extern int _binary_gfx_cons_kernel_ppm_size;
00081
00082 static bool use_gcons = false;
00083 static sysarg_t xres;
00084 static sysarg_t yres;
00085
00086 enum butstate {
00087 CONS_DISCONNECTED = 0,
00088 CONS_SELECTED,
00089 CONS_IDLE,
00090 CONS_HAS_DATA,
00091 CONS_KERNEL,
00092 CONS_DISCONNECTED_SEL,
00093 CONS_LAST
00094 };
00095
00096 static int console_vp;
00097 static int cstatus_vp[CONSOLE_COUNT];
00098 static enum butstate console_state[CONSOLE_COUNT];
00099
00100 static int fbphone;
00101
00103 static int ic_pixmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
00104 static int animation = -1;
00105
00106 static size_t active_console = 0;
00107
00108 static sysarg_t mouse_x = 0;
00109 static sysarg_t mouse_y= 0;
00110
00111 static bool btn_pressed = false;
00112 static sysarg_t btn_x = 0;
00113 static sysarg_t btn_y = 0;
00114
00115 static void vp_switch(int vp)
00116 {
00117 async_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
00118 }
00119
00121 static int vp_create(sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height)
00122 {
00123 return async_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
00124 (width << 16) | height);
00125 }
00126
00127 static void clear(void)
00128 {
00129 async_msg_0(fbphone, FB_CLEAR);
00130 }
00131
00132 static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
00133 {
00134 async_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
00135 }
00136
00138 static void tran_putch(wchar_t ch, sysarg_t col, sysarg_t row)
00139 {
00140 async_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
00141 }
00142
00144 static void redraw_state(size_t index)
00145 {
00146 vp_switch(cstatus_vp[index]);
00147
00148 enum butstate state = console_state[index];
00149
00150 if (ic_pixmaps[state] != -1)
00151 async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[index],
00152 ic_pixmaps[state]);
00153
00154 if ((state != CONS_DISCONNECTED) && (state != CONS_KERNEL)
00155 && (state != CONS_DISCONNECTED_SEL)) {
00156
00157 char data[5];
00158 snprintf(data, 5, "%zu", index + 1);
00159
00160 size_t i;
00161 for (i = 0; data[i] != 0; i++)
00162 tran_putch(data[i], 2 + i, 1);
00163 }
00164 }
00165
00167 void gcons_change_console(size_t index)
00168 {
00169 if (!use_gcons)
00170 return;
00171
00172 if (active_console == KERNEL_CONSOLE) {
00173 size_t i;
00174
00175 for (i = 0; i < CONSOLE_COUNT; i++)
00176 redraw_state(i);
00177
00178 if (animation != -1)
00179 async_msg_1(fbphone, FB_ANIM_START, animation);
00180 } else {
00181 if (console_state[active_console] == CONS_DISCONNECTED_SEL)
00182 console_state[active_console] = CONS_DISCONNECTED;
00183 else
00184 console_state[active_console] = CONS_IDLE;
00185
00186 redraw_state(active_console);
00187 }
00188
00189 active_console = index;
00190
00191 if ((console_state[index] == CONS_DISCONNECTED)
00192 || (console_state[index] == CONS_DISCONNECTED_SEL))
00193 console_state[index] = CONS_DISCONNECTED_SEL;
00194 else
00195 console_state[index] = CONS_SELECTED;
00196
00197 redraw_state(index);
00198 vp_switch(console_vp);
00199 }
00200
00202 void gcons_notify_char(size_t index)
00203 {
00204 if (!use_gcons)
00205 return;
00206
00207 if ((index == active_console)
00208 || (console_state[index] == CONS_HAS_DATA))
00209 return;
00210
00211 console_state[index] = CONS_HAS_DATA;
00212
00213 if (active_console == KERNEL_CONSOLE)
00214 return;
00215
00216 redraw_state(index);
00217 vp_switch(console_vp);
00218 }
00219
00221 void gcons_notify_disconnect(size_t index)
00222 {
00223 if (!use_gcons)
00224 return;
00225
00226 if (index == active_console)
00227 console_state[index] = CONS_DISCONNECTED_SEL;
00228 else
00229 console_state[index] = CONS_DISCONNECTED;
00230
00231 if (active_console == KERNEL_CONSOLE)
00232 return;
00233
00234 redraw_state(index);
00235 vp_switch(console_vp);
00236 }
00237
00239 void gcons_notify_connect(size_t index)
00240 {
00241 if (!use_gcons)
00242 return;
00243
00244 if (index == active_console)
00245 console_state[index] = CONS_SELECTED;
00246 else
00247 console_state[index] = CONS_IDLE;
00248
00249 if (active_console == KERNEL_CONSOLE)
00250 return;
00251
00252 redraw_state(index);
00253 vp_switch(console_vp);
00254 }
00255
00257 void gcons_in_kernel(void)
00258 {
00259 if (animation != -1)
00260 async_msg_1(fbphone, FB_ANIM_STOP, animation);
00261
00262 active_console = KERNEL_CONSOLE;
00263 vp_switch(0);
00264 }
00265
00267 static inline ssize_t limit(ssize_t a, ssize_t left, ssize_t right)
00268 {
00269 if (a < left)
00270 a = left;
00271
00272 if (a >= right)
00273 a = right - 1;
00274
00275 return a;
00276 }
00277
00283 void gcons_mouse_move(ssize_t dx, ssize_t dy)
00284 {
00285 ssize_t nx = (ssize_t) mouse_x + dx;
00286 ssize_t ny = (ssize_t) mouse_y + dy;
00287
00288
00289 if (xres == 0 || yres == 0)
00290 return;
00291
00292 mouse_x = (size_t) limit(nx, 0, xres);
00293 mouse_y = (size_t) limit(ny, 0, yres);
00294
00295 if (active_console != KERNEL_CONSOLE)
00296 async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
00297 }
00298
00299 static int gcons_find_conbut(sysarg_t x, sysarg_t y)
00300 {
00301 sysarg_t status_start = STATUS_START + (xres - 800) / 2;
00302
00303 if ((y < STATUS_TOP) || (y >= STATUS_TOP + STATUS_HEIGHT))
00304 return -1;
00305
00306 if (x < status_start)
00307 return -1;
00308
00309 if (x >= status_start + (STATUS_WIDTH + STATUS_SPACE) * CONSOLE_COUNT)
00310 return -1;
00311
00312 if (((x - status_start) % (STATUS_WIDTH + STATUS_SPACE)) < STATUS_SPACE)
00313 return -1;
00314
00315 sysarg_t btn = (x - status_start) / (STATUS_WIDTH + STATUS_SPACE);
00316
00317 if (btn < CONSOLE_COUNT)
00318 return btn;
00319
00320 return -1;
00321 }
00322
00328 int gcons_mouse_btn(bool state)
00329 {
00330
00331
00332 if (xres < 800)
00333 return -1;
00334
00335 if (state) {
00336 int conbut = gcons_find_conbut(mouse_x, mouse_y);
00337 if (conbut != -1) {
00338 btn_pressed = true;
00339 btn_x = mouse_x;
00340 btn_y = mouse_y;
00341 }
00342 return -1;
00343 }
00344
00345 if ((!state) && (!btn_pressed))
00346 return -1;
00347
00348 btn_pressed = false;
00349
00350 int conbut = gcons_find_conbut(mouse_x, mouse_y);
00351 if (conbut == gcons_find_conbut(btn_x, btn_y))
00352 return conbut;
00353
00354 return -1;
00355 }
00356
00365 static void draw_pixmap(char *logo, size_t size, sysarg_t x, sysarg_t y)
00366 {
00367
00368 char *shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
00369 MAP_ANONYMOUS, 0, 0);
00370 if (shm == MAP_FAILED)
00371 return;
00372
00373 memcpy(shm, logo, size);
00374
00375
00376 int rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
00377 if (rc)
00378 goto exit;
00379
00380 rc = async_share_out_start(fbphone, shm, PROTO_READ);
00381 if (rc)
00382 goto drop;
00383
00384
00385 async_msg_2(fbphone, FB_DRAW_PPM, x, y);
00386
00387 drop:
00388
00389 async_msg_0(fbphone, FB_DROP_SHM);
00390
00391 exit:
00392
00393 munmap(shm, size);
00394 }
00395
00397 void gcons_redraw_console(void)
00398 {
00399 if (!use_gcons)
00400 return;
00401
00402 vp_switch(0);
00403 set_rgb_color(COLOR_MAIN, COLOR_MAIN);
00404 clear();
00405 draw_pixmap(_binary_gfx_helenos_ppm_start,
00406 (size_t) &_binary_gfx_helenos_ppm_size, xres - 66, 2);
00407 draw_pixmap(_binary_gfx_nameic_ppm_start,
00408 (size_t) &_binary_gfx_nameic_ppm_size, 5, 17);
00409
00410 unsigned int i;
00411 for (i = 0; i < CONSOLE_COUNT; i++)
00412 redraw_state(i);
00413
00414 vp_switch(console_vp);
00415 }
00416
00425 static int make_pixmap(char *data, size_t size)
00426 {
00427
00428 char *shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
00429 MAP_ANONYMOUS, 0, 0);
00430 if (shm == MAP_FAILED)
00431 return -1;
00432
00433 memcpy(shm, data, size);
00434
00435 int pxid = -1;
00436
00437
00438 int rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
00439 if (rc)
00440 goto exit;
00441
00442 rc = async_share_out_start(fbphone, shm, PROTO_READ);
00443 if (rc)
00444 goto drop;
00445
00446
00447 rc = async_req_0_0(fbphone, FB_SHM2PIXMAP);
00448 if (rc < 0)
00449 goto drop;
00450
00451 pxid = rc;
00452
00453 drop:
00454
00455 async_msg_0(fbphone, FB_DROP_SHM);
00456
00457 exit:
00458
00459 munmap(shm, size);
00460
00461 return pxid;
00462 }
00463
00464 static void make_anim(void)
00465 {
00466 int an = async_req_1_0(fbphone, FB_ANIM_CREATE,
00467 cstatus_vp[KERNEL_CONSOLE]);
00468 if (an < 0)
00469 return;
00470
00471 int pm = make_pixmap(_binary_gfx_anim_1_ppm_start,
00472 (size_t) &_binary_gfx_anim_1_ppm_size);
00473 async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
00474
00475 pm = make_pixmap(_binary_gfx_anim_2_ppm_start,
00476 (size_t) &_binary_gfx_anim_2_ppm_size);
00477 async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
00478
00479 pm = make_pixmap(_binary_gfx_anim_3_ppm_start,
00480 (size_t) &_binary_gfx_anim_3_ppm_size);
00481 async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
00482
00483 pm = make_pixmap(_binary_gfx_anim_4_ppm_start,
00484 (size_t) &_binary_gfx_anim_4_ppm_size);
00485 async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
00486
00487 async_msg_1(fbphone, FB_ANIM_START, an);
00488
00489 animation = an;
00490 }
00491
00493 void gcons_init(int phone)
00494 {
00495 fbphone = phone;
00496
00497 int rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
00498 if (rc)
00499 return;
00500
00501 if ((xres < 800) || (yres < 600))
00502 return;
00503
00504
00505
00506
00507 console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
00508 ALIGN_DOWN(xres - 2 * CONSOLE_MARGIN, 8),
00509 ALIGN_DOWN(yres - (CONSOLE_TOP + CONSOLE_MARGIN), 16));
00510
00511 if (console_vp < 0)
00512 return;
00513
00514
00515 sysarg_t status_start = STATUS_START + (xres - 800) / 2;
00516 size_t i;
00517 for (i = 0; i < CONSOLE_COUNT; i++) {
00518 cstatus_vp[i] = vp_create(status_start + CONSOLE_MARGIN +
00519 i * (STATUS_WIDTH + STATUS_SPACE), STATUS_TOP,
00520 STATUS_WIDTH, STATUS_HEIGHT);
00521
00522 if (cstatus_vp[i] < 0)
00523 return;
00524
00525 vp_switch(cstatus_vp[i]);
00526 set_rgb_color(COLOR_FOREGROUND, COLOR_BACKGROUND);
00527 }
00528
00529
00530 ic_pixmaps[CONS_SELECTED] =
00531 make_pixmap(_binary_gfx_cons_selected_ppm_start,
00532 (size_t) &_binary_gfx_cons_selected_ppm_size);
00533 ic_pixmaps[CONS_IDLE] =
00534 make_pixmap(_binary_gfx_cons_idle_ppm_start,
00535 (size_t) &_binary_gfx_cons_idle_ppm_size);
00536 ic_pixmaps[CONS_HAS_DATA] =
00537 make_pixmap(_binary_gfx_cons_has_data_ppm_start,
00538 (size_t) &_binary_gfx_cons_has_data_ppm_size);
00539 ic_pixmaps[CONS_DISCONNECTED] =
00540 make_pixmap(_binary_gfx_cons_idle_ppm_start,
00541 (size_t) &_binary_gfx_cons_idle_ppm_size);
00542 ic_pixmaps[CONS_KERNEL] =
00543 make_pixmap(_binary_gfx_cons_kernel_ppm_start,
00544 (size_t) &_binary_gfx_cons_kernel_ppm_size);
00545 ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
00546
00547 make_anim();
00548
00549 use_gcons = true;
00550 console_state[0] = CONS_DISCONNECTED_SEL;
00551 console_state[KERNEL_CONSOLE] = CONS_KERNEL;
00552
00553 vp_switch(console_vp);
00554 }
00555