gcons.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Ondrej Palkovsky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <ipc/fb.h>
00036 #include <ipc/ipc.h>
00037 #include <async.h>
00038 #include <stdio.h>
00039 #include <sys/mman.h>
00040 #include <string.h>
00041 #include <align.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 MAIN_COLOR      0xffffff
00056 
00057 static int use_gcons = 0;
00058 static ipcarg_t xres,yres;
00059 
00060 enum butstate {
00061         CONS_DISCONNECTED = 0,
00062         CONS_SELECTED,
00063         CONS_IDLE,
00064         CONS_HAS_DATA,
00065         CONS_KERNEL,
00066         CONS_DISCONNECTED_SEL,
00067         CONS_LAST
00068 };
00069 
00070 static int console_vp;
00071 static int cstatus_vp[CONSOLE_COUNT];
00072 static enum butstate console_state[CONSOLE_COUNT];
00073 
00074 static int fbphone;
00075 
00077 static int ic_pixmaps[CONS_LAST] = {-1,-1,-1,-1,-1,-1};
00078 static int animation = -1;
00079 
00080 static int active_console = 0;
00081 
00082 static void vp_switch(int vp)
00083 {
00084         async_msg(fbphone,FB_VIEWPORT_SWITCH, vp);
00085 }
00086 
00088 static int vp_create(unsigned int x, unsigned int y, 
00089                      unsigned int width, unsigned int height)
00090 {
00091         return async_req_2(fbphone, FB_VIEWPORT_CREATE,
00092                            (x << 16) | y, (width << 16) | height,
00093                            NULL, NULL);
00094 }
00095 
00096 static void clear(void)
00097 {
00098         async_msg(fbphone, FB_CLEAR, 0);
00099         
00100 }
00101 
00102 static void set_style(int fgcolor, int bgcolor)
00103 {
00104         async_msg_2(fbphone, FB_SET_STYLE, fgcolor, bgcolor);
00105 }
00106 
00108 static void tran_putch(char c, int row, int col)
00109 {
00110         async_msg_3(fbphone, FB_TRANS_PUTCHAR, c, row, col);
00111 }
00112 
00114 static void redraw_state(int consnum)
00115 {
00116         char data[5];
00117         int i;
00118         enum butstate state = console_state[consnum];
00119 
00120         vp_switch(cstatus_vp[consnum]);
00121         if (ic_pixmaps[state] != -1)
00122                 async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[consnum], ic_pixmaps[state]);
00123 
00124         if (state != CONS_DISCONNECTED && state != CONS_KERNEL && state != CONS_DISCONNECTED_SEL) {
00125                 snprintf(data, 5, "%d", consnum+1);
00126                 for (i=0;data[i];i++)
00127                         tran_putch(data[i], 1, 2+i);
00128         }
00129 }
00130 
00132 void gcons_change_console(int consnum)
00133 {
00134         int i;
00135 
00136         if (!use_gcons)
00137                 return;
00138 
00139         if (active_console == KERNEL_CONSOLE) {
00140                 for (i=0; i < CONSOLE_COUNT; i++)
00141                         redraw_state(i);
00142                 if (animation != -1)
00143                         async_msg(fbphone, FB_ANIM_START, animation);
00144         } else {
00145                 if (console_state[active_console] == CONS_DISCONNECTED_SEL)
00146                         console_state[active_console] = CONS_DISCONNECTED;
00147                 else
00148                         console_state[active_console] = CONS_IDLE;
00149                 redraw_state(active_console);
00150         }
00151         active_console = consnum;
00152 
00153         if (console_state[consnum] == CONS_DISCONNECTED) {
00154                 console_state[consnum] = CONS_DISCONNECTED_SEL;
00155                 redraw_state(consnum);
00156         } else
00157                 console_state[consnum] = CONS_SELECTED;
00158         redraw_state(consnum);
00159 
00160         vp_switch(console_vp);
00161 }
00162 
00164 void gcons_notify_char(int consnum)
00165 {
00166         if (!use_gcons)
00167                 return;
00168 
00169         if (consnum == active_console || console_state[consnum] == CONS_HAS_DATA)
00170                 return;
00171 
00172         console_state[consnum] = CONS_HAS_DATA;
00173 
00174         if (active_console == KERNEL_CONSOLE)
00175                 return;
00176 
00177         redraw_state(consnum);
00178         
00179         vp_switch(console_vp);
00180 }
00181 
00183 void gcons_notify_disconnect(int consnum)
00184 {
00185         if (!use_gcons)
00186                 return;
00187         if (active_console == consnum)
00188                 console_state[consnum] = CONS_DISCONNECTED_SEL;
00189         else
00190                 console_state[consnum] = CONS_DISCONNECTED;
00191 
00192         if (active_console == KERNEL_CONSOLE)
00193                 return;
00194 
00195         redraw_state(consnum);
00196         vp_switch(console_vp);
00197 }
00198 
00200 void gcons_notify_connect(int consnum)
00201 {
00202         if (!use_gcons)
00203                 return;
00204         if (active_console == consnum)
00205                 console_state[consnum] = CONS_SELECTED;
00206         else
00207                 console_state[consnum] = CONS_IDLE;
00208 
00209         if (active_console == KERNEL_CONSOLE)
00210                 return;
00211 
00212         redraw_state(consnum);
00213         vp_switch(console_vp);
00214 }
00215 
00217 void gcons_in_kernel(void)
00218 {
00219         if (console_state[active_console] == CONS_DISCONNECTED_SEL)
00220                 console_state[active_console] = CONS_DISCONNECTED;
00221         else
00222                 console_state[active_console] = CONS_IDLE;
00223         redraw_state(active_console);
00224 
00225         if (animation != -1)
00226                 async_msg(fbphone, FB_ANIM_STOP, animation);
00227 
00228         active_console = KERNEL_CONSOLE; /* Set to kernel console */
00229         vp_switch(0);
00230 }
00231 
00232 
00233 static inline int limit(int a,int left, int right)
00234 {
00235         if (a < left)
00236                 a = left;
00237         if (a >= right)
00238                 a = right - 1;
00239         return a;
00240 }
00241 
00242 int mouse_x, mouse_y;
00243 int btn_pressed, btn_x, btn_y;
00244 
00250 void gcons_mouse_move(int dx, int dy)
00251 {
00252         mouse_x = limit(mouse_x+dx, 0, xres);
00253         mouse_y = limit(mouse_y+dy, 0, yres);
00254 
00255         async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
00256 }
00257 
00258 static int gcons_find_conbut(int x, int y)
00259 {
00260         int status_start = STATUS_START + (xres-800) / 2;;
00261 
00262         if (y < STATUS_TOP || y >= STATUS_TOP+STATUS_HEIGHT)
00263                 return -1;
00264         
00265         if (x < status_start)
00266                 return -1;
00267         
00268         if (x >= status_start + (STATUS_WIDTH+STATUS_SPACE)*CONSOLE_COUNT)
00269                 return -1;
00270         if (((x - status_start) % (STATUS_WIDTH+STATUS_SPACE)) < STATUS_SPACE)
00271                 return -1;
00272         
00273         return (x-status_start) / (STATUS_WIDTH+STATUS_SPACE);
00274 }
00275 
00280 int gcons_mouse_btn(int state)
00281 {
00282         int conbut;
00283 
00284         if (state) {
00285                 conbut = gcons_find_conbut(mouse_x, mouse_y);
00286                 if (conbut != -1) {
00287                         btn_pressed = 1;
00288                         btn_x = mouse_x;
00289                         btn_y = mouse_y;
00290                 }
00291                 return -1;
00292         } 
00293         if (!state && !btn_pressed)
00294                 return -1;
00295         btn_pressed = 0;
00296 
00297         conbut = gcons_find_conbut(mouse_x, mouse_y);
00298         if (conbut == gcons_find_conbut(btn_x, btn_y))
00299                 return conbut;
00300         return -1;
00301 }
00302 
00303 
00311 static void draw_pixmap(char *logo, size_t size, int x, int y)
00312 {
00313         char *shm;
00314         int rc;
00315 
00316         /* Create area */
00317         shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
00318         if (shm == MAP_FAILED)
00319                 return;
00320 
00321         memcpy(shm, logo, size);
00322         /* Send area */
00323         rc = async_req_2(fbphone, FB_PREPARE_SHM, (ipcarg_t)shm, 0, NULL, NULL);
00324         if (rc)
00325                 goto exit;
00326         rc = async_req_3(fbphone, IPC_M_AS_AREA_SEND, (ipcarg_t)shm, 0, PROTO_READ, NULL, NULL, NULL);
00327         if (rc)
00328                 goto drop;
00329         /* Draw logo */
00330         async_msg_2(fbphone, FB_DRAW_PPM, x, y);
00331 drop:
00332         /* Drop area */
00333         async_msg(fbphone, FB_DROP_SHM, 0);
00334 exit:       
00335         /* Remove area */
00336         munmap(shm, size);
00337 }
00338 
00339 extern char _binary_helenos_ppm_start[0];
00340 extern int _binary_helenos_ppm_size;
00341 extern char _binary_nameic_ppm_start[0];
00342 extern int _binary_nameic_ppm_size;
00344 static void gcons_redraw_console(void)
00345 {
00346         int i;
00347 
00348         if (!use_gcons)
00349                 return;
00350         
00351         vp_switch(0);
00352         set_style(MAIN_COLOR, MAIN_COLOR);
00353         clear();
00354         draw_pixmap(_binary_helenos_ppm_start, (size_t)&_binary_helenos_ppm_size, xres-66, 2);
00355         draw_pixmap(_binary_nameic_ppm_start, (size_t)&_binary_nameic_ppm_size, 5, 17);
00356 
00357         for (i=0;i < CONSOLE_COUNT; i++) 
00358                 redraw_state(i);
00359         vp_switch(console_vp);
00360 }
00361 
00368 static int make_pixmap(char *data, int size)
00369 {
00370         char *shm;
00371         int rc;
00372         int pxid = -1;
00373 
00374         /* Create area */
00375         shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
00376         if (shm == MAP_FAILED)
00377                 return -1;
00378 
00379         memcpy(shm, data, size);
00380         /* Send area */
00381         rc = async_req_2(fbphone, FB_PREPARE_SHM, (ipcarg_t)shm, 0, NULL, NULL);
00382         if (rc)
00383                 goto exit;
00384         rc = async_req_3(fbphone, IPC_M_AS_AREA_SEND, (ipcarg_t)shm, 0, PROTO_READ, NULL, NULL, NULL);
00385         if (rc)
00386                 goto drop;
00387 
00388         /* Obtain pixmap */
00389         rc = async_req(fbphone, FB_SHM2PIXMAP, 0, NULL);
00390         if (rc < 0)
00391                 goto drop;
00392         pxid = rc;
00393 drop:
00394         /* Drop area */
00395         async_msg(fbphone, FB_DROP_SHM, 0);
00396 exit:       
00397         /* Remove area */
00398         munmap(shm, size);
00399 
00400         return pxid;
00401 }
00402 
00403 extern char _binary_anim_1_ppm_start[0];
00404 extern int _binary_anim_1_ppm_size;
00405 extern char _binary_anim_2_ppm_start[0];
00406 extern int _binary_anim_2_ppm_size;
00407 extern char _binary_anim_3_ppm_start[0];
00408 extern int _binary_anim_3_ppm_size;
00409 extern char _binary_anim_4_ppm_start[0];
00410 extern int _binary_anim_4_ppm_size;
00411 static void make_anim(void)
00412 {
00413         int an;
00414         int pm;
00415 
00416         an = async_req(fbphone, FB_ANIM_CREATE, cstatus_vp[KERNEL_CONSOLE], NULL);
00417         if (an < 0)
00418                 return;
00419 
00420         pm = make_pixmap(_binary_anim_1_ppm_start, (int)&_binary_anim_1_ppm_size);
00421         async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
00422 
00423         pm = make_pixmap(_binary_anim_2_ppm_start, (int)&_binary_anim_2_ppm_size);
00424         async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
00425 
00426         pm = make_pixmap(_binary_anim_3_ppm_start, (int)&_binary_anim_3_ppm_size);
00427         async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
00428 
00429         pm = make_pixmap(_binary_anim_4_ppm_start, (int)&_binary_anim_4_ppm_size);
00430         async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
00431 
00432         async_msg(fbphone, FB_ANIM_START, an);
00433 
00434         animation = an;
00435 }
00436 
00437 extern char _binary_cons_selected_ppm_start[0];
00438 extern int _binary_cons_selected_ppm_size;
00439 extern char _binary_cons_idle_ppm_start[0];
00440 extern int _binary_cons_idle_ppm_size;
00441 extern char _binary_cons_has_data_ppm_start[0];
00442 extern int _binary_cons_has_data_ppm_size;
00443 extern char _binary_cons_kernel_ppm_start[0];
00444 extern int _binary_cons_kernel_ppm_size;
00446 void gcons_init(int phone)
00447 {
00448         int rc;
00449         int i;
00450         int status_start = STATUS_START;
00451 
00452         fbphone = phone;
00453 
00454         rc = async_req_2(phone, FB_GET_RESOLUTION, 0, 0, &xres, &yres);
00455         if (rc)
00456                 return;
00457         
00458         if (xres < 800 || yres < 600)
00459                 return;
00460 
00461         /* create console viewport */
00462         /* Align width & height to character size */
00463         console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP, 
00464                                ALIGN_DOWN(xres-2*CONSOLE_MARGIN, 8),
00465                                ALIGN_DOWN(yres-(CONSOLE_TOP+CONSOLE_MARGIN),16));
00466         if (console_vp < 0)
00467                 return;
00468         
00469         /* Create status buttons */
00470         status_start += (xres-800) / 2;
00471         for (i=0; i < CONSOLE_COUNT; i++) {
00472                 cstatus_vp[i] = vp_create(status_start+CONSOLE_MARGIN+i*(STATUS_WIDTH+STATUS_SPACE),
00473                                           STATUS_TOP, STATUS_WIDTH, STATUS_HEIGHT);
00474                 if (cstatus_vp[i] < 0)
00475                         return;
00476                 vp_switch(cstatus_vp[i]);
00477                 set_style(0x202020, 0xffffff);
00478         }
00479         
00480         /* Initialize icons */
00481         ic_pixmaps[CONS_SELECTED] = make_pixmap(_binary_cons_selected_ppm_start,
00482                                               (int)&_binary_cons_selected_ppm_size);
00483         ic_pixmaps[CONS_IDLE] = make_pixmap(_binary_cons_idle_ppm_start,
00484                                               (int)&_binary_cons_idle_ppm_size);
00485         ic_pixmaps[CONS_HAS_DATA] = make_pixmap(_binary_cons_has_data_ppm_start,
00486                                                 (int)&_binary_cons_has_data_ppm_size);
00487         ic_pixmaps[CONS_DISCONNECTED] = make_pixmap(_binary_cons_idle_ppm_start,
00488                                               (int)&_binary_cons_idle_ppm_size);
00489         ic_pixmaps[CONS_KERNEL] = make_pixmap(_binary_cons_kernel_ppm_start,
00490                                               (int)&_binary_cons_kernel_ppm_size);
00491         ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
00492         
00493         make_anim();
00494 
00495         use_gcons = 1;
00496         console_state[0] = CONS_DISCONNECTED_SEL;
00497         console_state[KERNEL_CONSOLE] = CONS_KERNEL;
00498         gcons_redraw_console();
00499 }
00500  

Generated on Sun Jun 18 18:00:18 2006 for HelenOS Userspace (ia64) by  doxygen 1.4.6