source: mainline/uspace/srv/hid/console/gcons.c@ 9247c02c

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

eradicate PPMs and pixmaps completely
make TGA and image map code more robust

  • Property mode set to 100644
File size: 13.0 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/** @addtogroup console
30 * @{
31 */
32/** @file
33 */
34
35#include <ipc/fb.h>
36#include <async.h>
37#include <async_obsolete.h>
38#include <stdio.h>
39#include <sys/mman.h>
40#include <str.h>
41#include <align.h>
42#include <bool.h>
43#include <imgmap.h>
44
45#include "console.h"
46#include "gcons.h"
47#include "images.h"
48
49#define CONSOLE_TOP 66
50#define CONSOLE_MARGIN 6
51
52#define STATUS_START 110
53#define STATUS_TOP 8
54#define STATUS_SPACE 4
55#define STATUS_WIDTH 48
56#define STATUS_HEIGHT 48
57
58#define COLOR_MAIN 0xffffff
59#define COLOR_FOREGROUND 0x202020
60#define COLOR_BACKGROUND 0xffffff
61
62static bool use_gcons = false;
63static sysarg_t xres;
64static sysarg_t yres;
65
66static imgmap_t *helenos_img;
67static imgmap_t *nameic_img;
68
69static imgmap_t *anim_1_img;
70static imgmap_t *anim_2_img;
71static imgmap_t *anim_3_img;
72static imgmap_t *anim_4_img;
73
74static imgmap_t *cons_has_data_img;
75static imgmap_t *cons_idle_img;
76static imgmap_t *cons_kernel_img;
77static imgmap_t *cons_selected_img;
78
79enum butstate {
80 CONS_DISCONNECTED = 0,
81 CONS_SELECTED,
82 CONS_IDLE,
83 CONS_HAS_DATA,
84 CONS_KERNEL,
85 CONS_DISCONNECTED_SEL,
86 CONS_LAST
87};
88
89static int console_vp;
90static int cstatus_vp[CONSOLE_COUNT];
91static enum butstate console_state[CONSOLE_COUNT];
92
93static int fbphone;
94
95/** List of image maps identifying these icons */
96static int ic_imgmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
97static int animation = -1;
98
99static size_t active_console = 0;
100
101static sysarg_t mouse_x = 0;
102static sysarg_t mouse_y= 0;
103
104static bool btn_pressed = false;
105static sysarg_t btn_x = 0;
106static sysarg_t btn_y = 0;
107
108static void vp_switch(int vp)
109{
110 async_obsolete_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
111}
112
113/** Create view port */
114static int vp_create(sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height)
115{
116 return async_obsolete_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
117 (width << 16) | height);
118}
119
120static void clear(void)
121{
122 async_obsolete_msg_0(fbphone, FB_CLEAR);
123}
124
125static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
126{
127 async_obsolete_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
128}
129
130/** Transparent putchar */
131static void tran_putch(wchar_t ch, sysarg_t col, sysarg_t row)
132{
133 async_obsolete_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
134}
135
136/** Redraw the button showing state of a given console */
137static void redraw_state(size_t index)
138{
139 vp_switch(cstatus_vp[index]);
140
141 enum butstate state = console_state[index];
142
143 if (ic_imgmaps[state] != -1)
144 async_obsolete_msg_2(fbphone, FB_VP_DRAW_IMGMAP, cstatus_vp[index],
145 ic_imgmaps[state]);
146
147 if ((state != CONS_DISCONNECTED) && (state != CONS_KERNEL)
148 && (state != CONS_DISCONNECTED_SEL)) {
149
150 char data[5];
151 snprintf(data, 5, "%zu", index + 1);
152
153 size_t i;
154 for (i = 0; data[i] != 0; i++)
155 tran_putch(data[i], 2 + i, 1);
156 }
157}
158
159/** Notification run on changing console (except kernel console) */
160void gcons_change_console(size_t index)
161{
162 if (!use_gcons) {
163 active_console = index;
164 return;
165 }
166
167 if (active_console == KERNEL_CONSOLE) {
168 size_t i;
169
170 for (i = 0; i < CONSOLE_COUNT; i++)
171 redraw_state(i);
172
173 if (animation != -1)
174 async_obsolete_msg_1(fbphone, FB_ANIM_START, animation);
175 } else {
176 if (console_state[active_console] == CONS_DISCONNECTED_SEL)
177 console_state[active_console] = CONS_DISCONNECTED;
178 else
179 console_state[active_console] = CONS_IDLE;
180
181 redraw_state(active_console);
182 }
183
184 active_console = index;
185
186 if ((console_state[index] == CONS_DISCONNECTED)
187 || (console_state[index] == CONS_DISCONNECTED_SEL))
188 console_state[index] = CONS_DISCONNECTED_SEL;
189 else
190 console_state[index] = CONS_SELECTED;
191
192 redraw_state(index);
193 vp_switch(console_vp);
194}
195
196/** Notification function that gets called on new output to virtual console */
197void gcons_notify_char(size_t index)
198{
199 if (!use_gcons)
200 return;
201
202 if ((index == active_console)
203 || (console_state[index] == CONS_HAS_DATA))
204 return;
205
206 console_state[index] = CONS_HAS_DATA;
207
208 if (active_console == KERNEL_CONSOLE)
209 return;
210
211 redraw_state(index);
212 vp_switch(console_vp);
213}
214
215/** Notification function called on service disconnect from console */
216void gcons_notify_disconnect(size_t index)
217{
218 if (!use_gcons)
219 return;
220
221 if (index == active_console)
222 console_state[index] = CONS_DISCONNECTED_SEL;
223 else
224 console_state[index] = CONS_DISCONNECTED;
225
226 if (active_console == KERNEL_CONSOLE)
227 return;
228
229 redraw_state(index);
230 vp_switch(console_vp);
231}
232
233/** Notification function called on console connect */
234void gcons_notify_connect(size_t index)
235{
236 if (!use_gcons)
237 return;
238
239 if (index == active_console)
240 console_state[index] = CONS_SELECTED;
241 else
242 console_state[index] = CONS_IDLE;
243
244 if (active_console == KERNEL_CONSOLE)
245 return;
246
247 redraw_state(index);
248 vp_switch(console_vp);
249}
250
251/** Change to kernel console */
252void gcons_in_kernel(void)
253{
254 if (animation != -1)
255 async_obsolete_msg_1(fbphone, FB_ANIM_STOP, animation);
256
257 active_console = KERNEL_CONSOLE;
258 vp_switch(0);
259}
260
261/** Return x, where left <= x <= right && |a-x| == min(|a-x|) is smallest */
262static inline ssize_t limit(ssize_t a, ssize_t left, ssize_t right)
263{
264 if (a < left)
265 a = left;
266
267 if (a >= right)
268 a = right - 1;
269
270 return a;
271}
272
273/** Handle mouse move
274 *
275 * @param dx Delta X of mouse move
276 * @param dy Delta Y of mouse move
277 */
278void gcons_mouse_move(ssize_t dx, ssize_t dy)
279{
280 ssize_t nx = (ssize_t) mouse_x + dx;
281 ssize_t ny = (ssize_t) mouse_y + dy;
282
283 /* Until gcons is initalized we don't have the screen resolution */
284 if (xres == 0 || yres == 0)
285 return;
286
287 mouse_x = (size_t) limit(nx, 0, xres);
288 mouse_y = (size_t) limit(ny, 0, yres);
289
290 if (active_console != KERNEL_CONSOLE)
291 async_obsolete_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
292}
293
294static int gcons_find_conbut(sysarg_t x, sysarg_t y)
295{
296 sysarg_t status_start = STATUS_START + (xres - 800) / 2;
297
298 if ((y < STATUS_TOP) || (y >= STATUS_TOP + STATUS_HEIGHT))
299 return -1;
300
301 if (x < status_start)
302 return -1;
303
304 if (x >= status_start + (STATUS_WIDTH + STATUS_SPACE) * CONSOLE_COUNT)
305 return -1;
306
307 if (((x - status_start) % (STATUS_WIDTH + STATUS_SPACE)) < STATUS_SPACE)
308 return -1;
309
310 sysarg_t btn = (x - status_start) / (STATUS_WIDTH + STATUS_SPACE);
311
312 if (btn < CONSOLE_COUNT)
313 return btn;
314
315 return -1;
316}
317
318/** Handle mouse click
319 *
320 * @param state New state (true - pressed, false - depressed)
321 *
322 */
323int gcons_mouse_btn(bool state)
324{
325 /* Ignore mouse clicks if no buttons
326 are drawn at all */
327 if (xres < 800)
328 return -1;
329
330 if (state) {
331 int conbut = gcons_find_conbut(mouse_x, mouse_y);
332 if (conbut != -1) {
333 btn_pressed = true;
334 btn_x = mouse_x;
335 btn_y = mouse_y;
336 }
337 return -1;
338 }
339
340 if ((!state) && (!btn_pressed))
341 return -1;
342
343 btn_pressed = false;
344
345 int conbut = gcons_find_conbut(mouse_x, mouse_y);
346 if (conbut == gcons_find_conbut(btn_x, btn_y))
347 return conbut;
348
349 return -1;
350}
351
352/** Draw an image map to framebuffer
353 *
354 * @param img Image map
355 * @param x Coordinate of upper left corner
356 * @param y Coordinate of upper left corner
357 *
358 */
359static void draw_imgmap(imgmap_t *img, sysarg_t x, sysarg_t y)
360{
361 if (img == NULL)
362 return;
363
364 /* Create area */
365 char *shm = mmap(NULL, img->size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
366 MAP_ANONYMOUS, 0, 0);
367 if (shm == MAP_FAILED)
368 return;
369
370 memcpy(shm, img, img->size);
371
372 /* Send area */
373 int rc = async_obsolete_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
374 if (rc)
375 goto exit;
376
377 rc = async_obsolete_share_out_start(fbphone, shm, PROTO_READ);
378 if (rc)
379 goto drop;
380
381 /* Draw logo */
382 async_obsolete_msg_2(fbphone, FB_DRAW_IMGMAP, x, y);
383
384drop:
385 /* Drop area */
386 async_obsolete_msg_0(fbphone, FB_DROP_SHM);
387
388exit:
389 /* Remove area */
390 munmap(shm, img->size);
391}
392
393/** Redraws console graphics */
394void gcons_redraw_console(void)
395{
396 if (!use_gcons)
397 return;
398
399 vp_switch(0);
400 set_rgb_color(COLOR_MAIN, COLOR_MAIN);
401 clear();
402 draw_imgmap(helenos_img, xres - 66, 2);
403 draw_imgmap(nameic_img, 5, 17);
404
405 unsigned int i;
406 for (i = 0; i < CONSOLE_COUNT; i++)
407 redraw_state(i);
408
409 vp_switch(console_vp);
410}
411
412/** Create an image map on framebuffer
413 *
414 * @param img Image map.
415 *
416 * @return Image map identification
417 *
418 */
419static int make_imgmap(imgmap_t *img)
420{
421 if (img == NULL)
422 return -1;
423
424 /* Create area */
425 char *shm = mmap(NULL, img->size, PROTO_READ | PROTO_WRITE,
426 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
427 if (shm == MAP_FAILED)
428 return -1;
429
430 memcpy(shm, img, img->size);
431
432 int id = -1;
433
434 /* Send area */
435 int rc = async_obsolete_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
436 if (rc)
437 goto exit;
438
439 rc = async_obsolete_share_out_start(fbphone, shm, PROTO_READ);
440 if (rc)
441 goto drop;
442
443 /* Obtain image map identifier */
444 rc = async_obsolete_req_0_0(fbphone, FB_SHM2IMGMAP);
445 if (rc < 0)
446 goto drop;
447
448 id = rc;
449
450drop:
451 /* Drop area */
452 async_obsolete_msg_0(fbphone, FB_DROP_SHM);
453
454exit:
455 /* Remove area */
456 munmap(shm, img->size);
457
458 return id;
459}
460
461static void make_anim(void)
462{
463 int an = async_obsolete_req_1_0(fbphone, FB_ANIM_CREATE,
464 cstatus_vp[KERNEL_CONSOLE]);
465 if (an < 0)
466 return;
467
468 int pm = make_imgmap(anim_1_img);
469 async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
470
471 pm = make_imgmap(anim_2_img);
472 async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
473
474 pm = make_imgmap(anim_3_img);
475 async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
476
477 pm = make_imgmap(anim_4_img);
478 async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
479
480 async_obsolete_msg_1(fbphone, FB_ANIM_START, an);
481
482 animation = an;
483}
484
485/** Initialize nice graphical console environment */
486void gcons_init(int phone)
487{
488 fbphone = phone;
489
490 int rc = async_obsolete_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
491 if (rc)
492 return;
493
494 if ((xres < 800) || (yres < 600))
495 return;
496
497 /* Create image maps */
498 helenos_img = imgmap_decode_tga((void *) helenos_tga,
499 helenos_tga_size);
500 nameic_img = imgmap_decode_tga((void *) nameic_tga,
501 nameic_tga_size);
502
503 anim_1_img = imgmap_decode_tga((void *) anim_1_tga,
504 anim_1_tga_size);
505 anim_2_img = imgmap_decode_tga((void *) anim_2_tga,
506 anim_2_tga_size);
507 anim_3_img = imgmap_decode_tga((void *) anim_3_tga,
508 anim_3_tga_size);
509 anim_4_img = imgmap_decode_tga((void *) anim_4_tga,
510 anim_4_tga_size);
511
512 cons_has_data_img = imgmap_decode_tga((void *) cons_has_data_tga,
513 cons_has_data_tga_size);
514 cons_idle_img = imgmap_decode_tga((void *) cons_idle_tga,
515 cons_idle_tga_size);
516 cons_kernel_img = imgmap_decode_tga((void *) cons_kernel_tga,
517 cons_kernel_tga_size);
518 cons_selected_img = imgmap_decode_tga((void *) cons_selected_tga,
519 cons_selected_tga_size);
520
521 /* Create console viewport */
522
523 /* Align width & height to character size */
524 console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
525 ALIGN_DOWN(xres - 2 * CONSOLE_MARGIN, 8),
526 ALIGN_DOWN(yres - (CONSOLE_TOP + CONSOLE_MARGIN), 16));
527
528 if (console_vp < 0)
529 return;
530
531 /* Create status buttons */
532 sysarg_t status_start = STATUS_START + (xres - 800) / 2;
533 size_t i;
534 for (i = 0; i < CONSOLE_COUNT; i++) {
535 cstatus_vp[i] = vp_create(status_start + CONSOLE_MARGIN +
536 i * (STATUS_WIDTH + STATUS_SPACE), STATUS_TOP,
537 STATUS_WIDTH, STATUS_HEIGHT);
538
539 if (cstatus_vp[i] < 0)
540 return;
541
542 vp_switch(cstatus_vp[i]);
543 set_rgb_color(COLOR_FOREGROUND, COLOR_BACKGROUND);
544 }
545
546 /* Initialize icons */
547 ic_imgmaps[CONS_SELECTED] = make_imgmap(cons_selected_img);
548 ic_imgmaps[CONS_IDLE] = make_imgmap(cons_idle_img);
549 ic_imgmaps[CONS_HAS_DATA] = make_imgmap(cons_has_data_img);
550 ic_imgmaps[CONS_DISCONNECTED] = make_imgmap(cons_idle_img);
551 ic_imgmaps[CONS_KERNEL] = make_imgmap(cons_kernel_img);
552 ic_imgmaps[CONS_DISCONNECTED_SEL] = ic_imgmaps[CONS_SELECTED];
553
554 make_anim();
555
556 use_gcons = true;
557 console_state[0] = CONS_DISCONNECTED_SEL;
558 console_state[KERNEL_CONSOLE] = CONS_KERNEL;
559
560 vp_switch(console_vp);
561}
562
563/** @}
564 */
Note: See TracBrowser for help on using the repository browser.