source: mainline/uspace/srv/hid/console/gcons.c@ 86018c1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 86018c1 was 2ae1e6e, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Do not redraw mouse pointer when kernel console is active.

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