Changes in uspace/srv/hid/console/console.c [f302586:b366a6f4] in mainline
- File:
-
- 1 edited
-
uspace/srv/hid/console/console.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/console/console.c
rf302586 rb366a6f4 1 1 /* 2 * Copyright (c) 2011 Martin Decky 2 * Copyright (c) 2006 Josef Cejka 3 * Copyright (c) 2011 Jiri Svoboda 3 4 * All rights reserved. 4 5 * … … 33 34 */ 34 35 35 #include <async.h> 36 #include <stdio.h> 37 #include <adt/prodcons.h> 36 #include <libc.h> 38 37 #include <ipc/input.h> 39 #include <ipc/console.h> 40 #include <ipc/vfs.h> 38 #include <io/keycode.h> 39 #include <ipc/fb.h> 40 #include <ipc/services.h> 41 #include <ns.h> 42 #include <ns_obsolete.h> 41 43 #include <errno.h> 42 44 #include <str_error.h> 43 #include <loc.h> 45 #include <ipc/console.h> 46 #include <unistd.h> 47 #include <async.h> 48 #include <async_obsolete.h> 49 #include <adt/fifo.h> 50 #include <sys/mman.h> 51 #include <stdio.h> 52 #include <str.h> 53 #include <sysinfo.h> 44 54 #include <event.h> 45 #include <io/keycode.h> 46 #include <screenbuffer.h> 47 #include <fb.h> 48 #include <imgmap.h> 49 #include <align.h> 50 #include <malloc.h> 51 #include <as.h> 55 #include <devmap.h> 56 #include <fcntl.h> 57 #include <vfs/vfs.h> 52 58 #include <fibril_synch.h> 53 #include "images.h" 59 #include <io/style.h> 60 #include <io/screenbuffer.h> 61 54 62 #include "console.h" 63 #include "gcons.h" 64 #include "keybuffer.h" 55 65 56 66 #define NAME "console" 57 67 #define NAMESPACE "term" 58 68 59 #define CONSOLE_TOP 66 60 #define CONSOLE_MARGIN 12 61 62 #define STATE_START 100 63 #define STATE_TOP 8 64 #define STATE_SPACE 4 65 #define STATE_WIDTH 48 66 #define STATE_HEIGHT 48 67 68 typedef enum { 69 CONS_DISCONNECTED = 0, 70 CONS_DISCONNECTED_SELECTED, 71 CONS_SELECTED, 72 CONS_IDLE, 73 CONS_DATA, 74 CONS_KERNEL, 75 CONS_LAST 76 } console_state_t; 69 /** Session with the input server. */ 70 static async_sess_t *input_sess; 71 72 /** Information about framebuffer */ 73 struct { 74 int phone; /**< Framebuffer phone */ 75 sysarg_t cols; /**< Framebuffer columns */ 76 sysarg_t rows; /**< Framebuffer rows */ 77 sysarg_t color_cap; /**< Color capabilities (FB_CCAP_xxx) */ 78 } fb_info; 77 79 78 80 typedef struct { 79 atomic_t refcnt; /**< Connection reference count */ 80 prodcons_t input_pc; /**< Incoming keyboard events */ 81 82 fibril_mutex_t mtx; /**< Lock protecting mutable fields */ 83 84 size_t index; /**< Console index */ 85 console_state_t state; /**< Console state */ 86 service_id_t dsid; /**< Service handle */ 87 88 vp_handle_t state_vp; /**< State icon viewport */ 89 sysarg_t cols; /**< Number of columns */ 90 sysarg_t rows; /**< Number of rows */ 91 console_caps_t ccaps; /**< Console capabilities */ 92 93 screenbuffer_t *frontbuf; /**< Front buffer */ 94 frontbuf_handle_t fbid; /**< Front buffer handle */ 81 size_t index; /**< Console index */ 82 size_t refcount; /**< Connection reference count */ 83 devmap_handle_t devmap_handle; /**< Device handle */ 84 keybuffer_t keybuffer; /**< Buffer for incoming keys. */ 85 screenbuffer_t scr; /**< Screenbuffer for saving screen 86 contents and related settings. */ 95 87 } console_t; 96 97 typedef enum {98 GRAPHICS_NONE = 0,99 GRAPHICS_BASIC = 1,100 GRAPHICS_FULL = 2101 } graphics_state_t;102 103 /** Current console state */104 static graphics_state_t graphics_state = GRAPHICS_NONE;105 106 /** State icons */107 static imagemap_handle_t state_icons[CONS_LAST];108 109 /** Session to the input server */110 static async_sess_t *input_sess;111 112 /** Session to the framebuffer server */113 static async_sess_t *fb_sess;114 115 /** Framebuffer resolution */116 static sysarg_t xres;117 static sysarg_t yres;118 88 119 89 /** Array of data for virtual consoles */ 120 90 static console_t consoles[CONSOLE_COUNT]; 121 91 122 /** Mutex for console switching */ 123 static FIBRIL_MUTEX_INITIALIZE(switch_mtx); 124 92 static console_t *active_console = &consoles[0]; 125 93 static console_t *prev_console = &consoles[0]; 126 static console_t *active_console = &consoles[0];127 94 static console_t *kernel_console = &consoles[KERNEL_CONSOLE]; 128 95 129 static imgmap_t *logo_img; 130 static imgmap_t *nameic_img; 131 132 static imgmap_t *anim_1_img; 133 static imgmap_t *anim_2_img; 134 static imgmap_t *anim_3_img; 135 static imgmap_t *anim_4_img; 136 137 static imagemap_handle_t anim_1; 138 static imagemap_handle_t anim_2; 139 static imagemap_handle_t anim_3; 140 static imagemap_handle_t anim_4; 141 142 static sequence_handle_t anim_seq; 143 144 static imgmap_t *cons_data_img; 145 static imgmap_t *cons_dis_img; 146 static imgmap_t *cons_dis_sel_img; 147 static imgmap_t *cons_idle_img; 148 static imgmap_t *cons_kernel_img; 149 static imgmap_t *cons_sel_img; 150 151 static vp_handle_t logo_vp; 152 static imagemap_handle_t logo_handle; 153 154 static vp_handle_t nameic_vp; 155 static imagemap_handle_t nameic_handle; 156 157 static vp_handle_t screen_vp; 158 static vp_handle_t console_vp; 159 96 /** Pointer to memory shared with framebufer used for 97 faster virtual console switching */ 98 static keyfield_t *interbuffer = NULL; 99 100 /** Information on row-span yet unsent to FB driver. */ 160 101 struct { 161 sysarg_t x; 162 sysarg_t y; 163 164 sysarg_t btn_x; 165 sysarg_t btn_y; 166 167 bool pressed; 168 } mouse; 169 170 static void cons_redraw_state(console_t *cons) 171 { 172 if (graphics_state == GRAPHICS_FULL) { 173 fibril_mutex_lock(&cons->mtx); 174 175 fb_vp_imagemap_damage(fb_sess, cons->state_vp, 176 state_icons[cons->state], 0, 0, STATE_WIDTH, STATE_HEIGHT); 177 178 if ((cons->state != CONS_DISCONNECTED) && 179 (cons->state != CONS_KERNEL) && 180 (cons->state != CONS_DISCONNECTED_SELECTED)) { 181 char data[5]; 182 snprintf(data, 5, "%zu", cons->index + 1); 183 184 for (size_t i = 0; data[i] != 0; i++) 185 fb_vp_putchar(fb_sess, cons->state_vp, i + 2, 1, data[i]); 186 } 187 188 fibril_mutex_unlock(&cons->mtx); 189 } 190 } 191 192 static void cons_kernel_sequence_start(console_t *cons) 193 { 194 if (graphics_state == GRAPHICS_FULL) { 195 fibril_mutex_lock(&cons->mtx); 196 197 fb_vp_sequence_start(fb_sess, cons->state_vp, anim_seq); 198 fb_vp_imagemap_damage(fb_sess, cons->state_vp, 199 state_icons[cons->state], 0, 0, STATE_WIDTH, STATE_HEIGHT); 200 201 fibril_mutex_unlock(&cons->mtx); 202 } 203 } 204 205 static void cons_update_state(console_t *cons, console_state_t state) 206 { 207 bool update = false; 208 209 fibril_mutex_lock(&cons->mtx); 210 211 if (cons->state != state) { 212 cons->state = state; 213 update = true; 214 } 215 216 fibril_mutex_unlock(&cons->mtx); 217 218 if (update) 219 cons_redraw_state(cons); 220 } 221 222 static void cons_notify_data(console_t *cons) 223 { 224 fibril_mutex_lock(&switch_mtx); 225 226 if (cons != active_console) 227 cons_update_state(cons, CONS_DATA); 228 229 fibril_mutex_unlock(&switch_mtx); 230 } 231 232 static void cons_notify_connect(console_t *cons) 233 { 234 fibril_mutex_lock(&switch_mtx); 235 236 if (cons == active_console) 237 cons_update_state(cons, CONS_SELECTED); 238 else 239 cons_update_state(cons, CONS_IDLE); 240 241 fibril_mutex_unlock(&switch_mtx); 242 } 243 244 static void cons_notify_disconnect(console_t *cons) 245 { 246 fibril_mutex_lock(&switch_mtx); 247 248 if (cons == active_console) 249 cons_update_state(cons, CONS_DISCONNECTED_SELECTED); 250 else 251 cons_update_state(cons, CONS_DISCONNECTED); 252 253 fibril_mutex_unlock(&switch_mtx); 254 } 255 256 static void cons_update(console_t *cons) 257 { 258 fibril_mutex_lock(&switch_mtx); 259 fibril_mutex_lock(&cons->mtx); 260 261 if ((cons == active_console) && (active_console != kernel_console)) { 262 fb_vp_update(fb_sess, console_vp, cons->fbid); 263 fb_vp_cursor_update(fb_sess, console_vp, cons->fbid); 264 } 265 266 fibril_mutex_unlock(&cons->mtx); 267 fibril_mutex_unlock(&switch_mtx); 268 } 269 270 static void cons_update_cursor(console_t *cons) 271 { 272 fibril_mutex_lock(&switch_mtx); 273 fibril_mutex_lock(&cons->mtx); 274 275 if ((cons == active_console) && (active_console != kernel_console)) 276 fb_vp_cursor_update(fb_sess, console_vp, cons->fbid); 277 278 fibril_mutex_unlock(&cons->mtx); 279 fibril_mutex_unlock(&switch_mtx); 280 } 281 282 static void cons_clear(console_t *cons) 283 { 284 fibril_mutex_lock(&cons->mtx); 285 screenbuffer_clear(cons->frontbuf); 286 fibril_mutex_unlock(&cons->mtx); 287 288 cons_update(cons); 289 } 290 291 static void cons_damage_all(console_t *cons) 292 { 293 fibril_mutex_lock(&switch_mtx); 294 fibril_mutex_lock(&cons->mtx); 295 296 if ((cons == active_console) && (active_console != kernel_console)) { 297 fb_vp_damage(fb_sess, console_vp, cons->fbid, 0, 0, cons->cols, 298 cons->rows); 299 fb_vp_cursor_update(fb_sess, console_vp, cons->fbid); 300 } 301 302 fibril_mutex_unlock(&cons->mtx); 303 fibril_mutex_unlock(&switch_mtx); 304 } 305 306 static void cons_switch(console_t *cons) 307 { 308 fibril_mutex_lock(&switch_mtx); 309 310 if (cons == active_console) { 311 fibril_mutex_unlock(&switch_mtx); 102 sysarg_t col; /**< Leftmost column of the span. */ 103 sysarg_t row; /**< Row where the span lies. */ 104 sysarg_t cnt; /**< Width of the span. */ 105 } fb_pending; 106 107 static FIBRIL_MUTEX_INITIALIZE(input_mutex); 108 static FIBRIL_CONDVAR_INITIALIZE(input_cv); 109 110 static FIBRIL_MUTEX_INITIALIZE(big_console_lock); 111 112 static void console_serialize_start(void) 113 { 114 fibril_mutex_lock(&big_console_lock); 115 } 116 117 static void console_serialize_end(void) 118 { 119 fibril_mutex_unlock(&big_console_lock); 120 } 121 122 static void curs_visibility(bool visible) 123 { 124 async_obsolete_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); 125 } 126 127 static void curs_hide_sync(void) 128 { 129 async_obsolete_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 130 } 131 132 static void curs_goto(sysarg_t x, sysarg_t y) 133 { 134 async_obsolete_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y); 135 } 136 137 static void screen_clear(void) 138 { 139 async_obsolete_msg_0(fb_info.phone, FB_CLEAR); 140 } 141 142 static void screen_yield(void) 143 { 144 async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_YIELD); 145 } 146 147 static void screen_reclaim(void) 148 { 149 async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM); 150 } 151 152 static void input_yield(void) 153 { 154 async_exch_t *exch = async_exchange_begin(input_sess); 155 if (exch == NULL) { 156 printf("%s: Failed starting exchange with input device.\n", 157 NAME); 312 158 return; 313 159 } 314 160 315 if (cons == kernel_console) { 316 fb_yield(fb_sess); 317 if (!console_kcon()) { 318 fb_claim(fb_sess); 319 fibril_mutex_unlock(&switch_mtx); 320 return; 321 } 322 } 323 324 if (active_console == kernel_console) 325 fb_claim(fb_sess); 326 327 prev_console = active_console; 328 active_console = cons; 329 330 if (prev_console->state == CONS_DISCONNECTED_SELECTED) 331 cons_update_state(prev_console, CONS_DISCONNECTED); 332 else 333 cons_update_state(prev_console, CONS_IDLE); 334 335 if ((cons->state == CONS_DISCONNECTED) || 336 (cons->state == CONS_DISCONNECTED_SELECTED)) 337 cons_update_state(cons, CONS_DISCONNECTED_SELECTED); 338 else 339 cons_update_state(cons, CONS_SELECTED); 340 341 fibril_mutex_unlock(&switch_mtx); 342 343 cons_damage_all(cons); 344 } 345 346 static console_t *cons_get_active_uspace(void) 347 { 348 fibril_mutex_lock(&switch_mtx); 349 350 console_t *active_uspace = active_console; 351 if (active_uspace == kernel_console) { 352 active_uspace = prev_console; 353 } 354 assert(active_uspace != kernel_console); 355 356 fibril_mutex_unlock(&switch_mtx); 357 358 return active_uspace; 359 } 360 361 static ssize_t limit(ssize_t val, ssize_t lo, ssize_t hi) 362 { 363 if (val > hi) 364 return hi; 365 366 if (val < lo) 367 return lo; 368 369 return val; 370 } 371 372 static void cons_mouse_move(sysarg_t dx, sysarg_t dy) 373 { 374 ssize_t sx = (ssize_t) dx; 375 ssize_t sy = (ssize_t) dy; 376 377 mouse.x = limit(mouse.x + sx, 0, xres); 378 mouse.y = limit(mouse.y + sy, 0, yres); 379 380 fb_pointer_update(fb_sess, mouse.x, mouse.y, true); 381 } 382 383 static console_t *cons_find_icon(sysarg_t x, sysarg_t y) 384 { 385 sysarg_t status_start = 386 STATE_START + (xres - 800) / 2 + CONSOLE_MARGIN; 387 388 if ((y < STATE_TOP) || (y >= STATE_TOP + STATE_HEIGHT)) 389 return NULL; 390 391 if (x < status_start) 392 return NULL; 393 394 if (x >= status_start + (STATE_WIDTH + STATE_SPACE) * CONSOLE_COUNT) 395 return NULL; 396 397 if (((x - status_start) % (STATE_WIDTH + STATE_SPACE)) >= STATE_WIDTH) 398 return NULL; 399 400 sysarg_t btn = (x - status_start) / (STATE_WIDTH + STATE_SPACE); 401 402 if (btn < CONSOLE_COUNT) 403 return consoles + btn; 404 405 return NULL; 406 } 407 408 /** Handle mouse click 161 async_req_0_0(exch, INPUT_YIELD); 162 async_exchange_end(exch); 163 } 164 165 static void input_reclaim(void) 166 { 167 async_exch_t *exch = async_exchange_begin(input_sess); 168 if (exch == NULL) { 169 printf("%s: Failed starting exchange with input device.\n", 170 NAME); 171 return; 172 } 173 174 async_req_0_0(exch, INPUT_RECLAIM); 175 async_exchange_end(exch); 176 } 177 178 static void set_style(uint8_t style) 179 { 180 async_obsolete_msg_1(fb_info.phone, FB_SET_STYLE, style); 181 } 182 183 static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags) 184 { 185 async_obsolete_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags); 186 } 187 188 static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor) 189 { 190 async_obsolete_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 191 } 192 193 static void set_attrs(attrs_t *attrs) 194 { 195 switch (attrs->t) { 196 case at_style: 197 set_style(attrs->a.s.style); 198 break; 199 case at_idx: 200 set_color(attrs->a.i.fg_color, attrs->a.i.bg_color, 201 attrs->a.i.flags); 202 break; 203 case at_rgb: 204 set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color); 205 break; 206 } 207 } 208 209 static int ccap_fb_to_con(sysarg_t ccap_fb, sysarg_t *ccap_con) 210 { 211 switch (ccap_fb) { 212 case FB_CCAP_NONE: 213 *ccap_con = CONSOLE_CCAP_NONE; 214 break; 215 case FB_CCAP_STYLE: 216 *ccap_con = CONSOLE_CCAP_STYLE; 217 break; 218 case FB_CCAP_INDEXED: 219 *ccap_con = CONSOLE_CCAP_INDEXED; 220 break; 221 case FB_CCAP_RGB: 222 *ccap_con = CONSOLE_CCAP_RGB; 223 break; 224 default: 225 return EINVAL; 226 } 227 228 return EOK; 229 } 230 231 /** Send an area of screenbuffer to the FB driver. */ 232 static void fb_update_area(console_t *cons, sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height) 233 { 234 if (interbuffer) { 235 sysarg_t x; 236 sysarg_t y; 237 238 for (y = 0; y < height; y++) { 239 for (x = 0; x < width; x++) { 240 interbuffer[y * width + x] = 241 *get_field_at(&cons->scr, x0 + x, y0 + y); 242 } 243 } 244 245 async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, 246 x0, y0, width, height); 247 } 248 } 249 250 /** Flush pending cells to FB. */ 251 static void fb_pending_flush(void) 252 { 253 if (fb_pending.cnt > 0) { 254 fb_update_area(active_console, fb_pending.col, 255 fb_pending.row, fb_pending.cnt, 1); 256 fb_pending.cnt = 0; 257 } 258 } 259 260 /** Mark a character cell as changed. 409 261 * 410 * @param state Button state (true - pressed, false - depressed) 262 * This adds the cell to the pending rowspan if possible. Otherwise 263 * the old span is flushed first. 411 264 * 412 265 */ 413 static console_t *cons_mouse_button(bool state) 414 { 415 if (graphics_state != GRAPHICS_FULL) 416 return NULL; 417 418 if (state) { 419 console_t *cons = cons_find_icon(mouse.x, mouse.y); 420 if (cons != NULL) { 421 mouse.btn_x = mouse.x; 422 mouse.btn_y = mouse.y; 423 mouse.pressed = true; 424 } 425 426 return NULL; 427 } 428 429 if ((!state) && (!mouse.pressed)) 430 return NULL; 431 432 console_t *cons = cons_find_icon(mouse.x, mouse.y); 433 if (cons == cons_find_icon(mouse.btn_x, mouse.btn_y)) 434 return cons; 435 436 mouse.pressed = false; 437 return NULL; 438 } 439 266 static void cell_mark_changed(sysarg_t col, sysarg_t row) 267 { 268 if (fb_pending.cnt != 0) { 269 if ((col != fb_pending.col + fb_pending.cnt) 270 || (row != fb_pending.row)) { 271 fb_pending_flush(); 272 } 273 } 274 275 if (fb_pending.cnt == 0) { 276 fb_pending.col = col; 277 fb_pending.row = row; 278 } 279 280 fb_pending.cnt++; 281 } 282 283 /** Print a character to the active VC with buffering. */ 284 static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row) 285 { 286 async_obsolete_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row); 287 } 288 289 /** Process a character from the client (TTY emulation). */ 290 static void write_char(console_t *cons, wchar_t ch) 291 { 292 bool flush_cursor = false; 293 294 switch (ch) { 295 case '\n': 296 fb_pending_flush(); 297 flush_cursor = true; 298 cons->scr.position_y++; 299 cons->scr.position_x = 0; 300 break; 301 case '\r': 302 break; 303 case '\t': 304 cons->scr.position_x += 8; 305 cons->scr.position_x -= cons->scr.position_x % 8; 306 break; 307 case '\b': 308 if (cons->scr.position_x == 0) 309 break; 310 cons->scr.position_x--; 311 if (cons == active_console) 312 cell_mark_changed(cons->scr.position_x, cons->scr.position_y); 313 screenbuffer_putchar(&cons->scr, ' '); 314 break; 315 default: 316 if (cons == active_console) 317 cell_mark_changed(cons->scr.position_x, cons->scr.position_y); 318 319 screenbuffer_putchar(&cons->scr, ch); 320 cons->scr.position_x++; 321 } 322 323 if (cons->scr.position_x >= cons->scr.size_x) { 324 flush_cursor = true; 325 cons->scr.position_y++; 326 } 327 328 if (cons->scr.position_y >= cons->scr.size_y) { 329 fb_pending_flush(); 330 cons->scr.position_y = cons->scr.size_y - 1; 331 screenbuffer_clear_line(&cons->scr, cons->scr.top_line); 332 cons->scr.top_line = (cons->scr.top_line + 1) % cons->scr.size_y; 333 334 if (cons == active_console) 335 async_obsolete_msg_1(fb_info.phone, FB_SCROLL, 1); 336 } 337 338 if (cons == active_console && flush_cursor) 339 curs_goto(cons->scr.position_x, cons->scr.position_y); 340 cons->scr.position_x = cons->scr.position_x % cons->scr.size_x; 341 } 342 343 /** Switch to new console */ 344 static void change_console(console_t *cons) 345 { 346 if (cons == active_console) 347 return; 348 349 fb_pending_flush(); 350 351 if (cons == kernel_console) { 352 console_serialize_start(); 353 curs_hide_sync(); 354 gcons_in_kernel(); 355 screen_yield(); 356 input_yield(); 357 console_serialize_end(); 358 359 if (console_kcon()) { 360 prev_console = active_console; 361 active_console = kernel_console; 362 } else 363 cons = active_console; 364 } 365 366 if (cons != kernel_console) { 367 console_serialize_start(); 368 369 if (active_console == kernel_console) { 370 screen_reclaim(); 371 input_reclaim(); 372 gcons_redraw_console(); 373 } 374 375 active_console = cons; 376 gcons_change_console(cons->index); 377 378 set_attrs(&cons->scr.attrs); 379 curs_visibility(false); 380 381 sysarg_t x; 382 sysarg_t y; 383 int rc = 0; 384 385 if (interbuffer) { 386 for (y = 0; y < cons->scr.size_y; y++) { 387 for (x = 0; x < cons->scr.size_x; x++) { 388 interbuffer[y * cons->scr.size_x + x] = 389 *get_field_at(&cons->scr, x, y); 390 } 391 } 392 393 /* This call can preempt, but we are already at the end */ 394 rc = async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, 395 0, 0, cons->scr.size_x, 396 cons->scr.size_y); 397 } 398 399 if ((!interbuffer) || (rc != 0)) { 400 set_attrs(&cons->scr.attrs); 401 screen_clear(); 402 403 for (y = 0; y < cons->scr.size_y; y++) 404 for (x = 0; x < cons->scr.size_x; x++) { 405 keyfield_t *field = get_field_at(&cons->scr, x, y); 406 407 if (!attrs_same(cons->scr.attrs, field->attrs)) 408 set_attrs(&field->attrs); 409 410 cons->scr.attrs = field->attrs; 411 if ((field->character == ' ') && 412 (attrs_same(field->attrs, cons->scr.attrs))) 413 continue; 414 415 fb_putchar(field->character, x, y); 416 } 417 } 418 419 curs_goto(cons->scr.position_x, cons->scr.position_y); 420 curs_visibility(cons->scr.is_cursor_visible); 421 422 console_serialize_end(); 423 } 424 } 425 426 /** Handler for input events */ 440 427 static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg) 441 428 { … … 445 432 ipc_callid_t callid = async_get_call(&call); 446 433 434 int retval; 435 kbd_event_t ev; 436 447 437 if (!IPC_GET_IMETHOD(call)) { 448 438 /* TODO: Handle hangup */ … … 451 441 } 452 442 453 kbd_event_type_t type;454 keycode_t key;455 keymod_t mods;456 wchar_t c;457 458 443 switch (IPC_GET_IMETHOD(call)) { 459 444 case INPUT_EVENT_KEY: 460 type = IPC_GET_ARG1(call); 461 key = IPC_GET_ARG2(call); 462 mods = IPC_GET_ARG3(call); 463 c = IPC_GET_ARG4(call); 445 /* Got key press/release event */ 446 retval = 0; 447 ev.type = IPC_GET_ARG1(call); 448 ev.key = IPC_GET_ARG2(call); 449 ev.mods = IPC_GET_ARG3(call); 450 ev.c = IPC_GET_ARG4(call); 464 451 465 if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) && 466 ((mods & KM_CTRL) == 0)) 467 cons_switch(&consoles[key - KC_F1]); 468 else { 469 /* Got key press/release event */ 470 kbd_event_t *event = 471 (kbd_event_t *) malloc(sizeof(kbd_event_t)); 472 if (event == NULL) { 473 async_answer_0(callid, ENOMEM); 474 break; 475 } 476 477 link_initialize(&event->link); 478 event->type = type; 479 event->key = key; 480 event->mods = mods; 481 event->c = c; 482 483 /* 484 * Kernel console does not read events 485 * from us, so we will redirect them 486 * to the (last) active userspace console 487 * if necessary. 488 */ 489 console_t *target_console = cons_get_active_uspace(); 490 491 prodcons_produce(&target_console->input_pc, 492 &event->link); 452 if ((ev.key >= KC_F1) && (ev.key < KC_F1 + 453 CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) { 454 if (ev.key == KC_F1 + KERNEL_CONSOLE) 455 change_console(kernel_console); 456 else 457 change_console(&consoles[ev.key - KC_F1]); 458 break; 493 459 } 494 460 495 async_answer_0(callid, EOK); 461 fibril_mutex_lock(&input_mutex); 462 keybuffer_push(&active_console->keybuffer, &ev); 463 fibril_condvar_broadcast(&input_cv); 464 fibril_mutex_unlock(&input_mutex); 496 465 break; 497 466 case INPUT_EVENT_MOVE: 498 cons_mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 499 async_answer_0(callid, EOK); 467 /* Got pointer move event */ 468 gcons_mouse_move((int) IPC_GET_ARG1(call), 469 (int) IPC_GET_ARG2(call)); 470 retval = 0; 500 471 break; 501 472 case INPUT_EVENT_BUTTON: 502 473 /* Got pointer button press/release event */ 503 474 if (IPC_GET_ARG1(call) == 1) { 504 console_t *cons = 505 cons_mouse_button((bool) IPC_GET_ARG2(call)); 506 if (cons != NULL) 507 cons_switch(cons); 475 int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call)); 476 if (newcon != -1) 477 change_console(&consoles[newcon]); 508 478 } 509 async_answer_0(callid, EOK);479 retval = 0; 510 480 break; 511 481 default: 512 async_answer_0(callid, EINVAL); 513 } 514 } 515 } 516 517 /** Process a character from the client (TTY emulation). */ 518 static void cons_write_char(console_t *cons, wchar_t ch) 519 { 520 sysarg_t updated = 0; 521 522 fibril_mutex_lock(&cons->mtx); 523 524 switch (ch) { 525 case '\n': 526 updated = screenbuffer_newline(cons->frontbuf); 527 break; 528 case '\r': 529 break; 530 case '\t': 531 updated = screenbuffer_tabstop(cons->frontbuf, 8); 532 break; 533 case '\b': 534 updated = screenbuffer_backspace(cons->frontbuf); 535 break; 536 default: 537 updated = screenbuffer_putchar(cons->frontbuf, ch, true); 538 } 539 540 fibril_mutex_unlock(&cons->mtx); 541 542 if (updated > 1) 543 cons_update(cons); 544 } 545 546 static void cons_set_cursor(console_t *cons, sysarg_t col, sysarg_t row) 547 { 548 fibril_mutex_lock(&cons->mtx); 549 screenbuffer_set_cursor(cons->frontbuf, col, row); 550 fibril_mutex_unlock(&cons->mtx); 551 552 cons_update_cursor(cons); 553 } 554 555 static void cons_set_cursor_visibility(console_t *cons, bool visible) 556 { 557 fibril_mutex_lock(&cons->mtx); 558 screenbuffer_set_cursor_visibility(cons->frontbuf, visible); 559 fibril_mutex_unlock(&cons->mtx); 560 561 cons_update_cursor(cons); 562 } 563 564 static void cons_get_cursor(console_t *cons, ipc_callid_t iid, ipc_call_t *icall) 565 { 566 sysarg_t col; 567 sysarg_t row; 568 569 fibril_mutex_lock(&cons->mtx); 570 screenbuffer_get_cursor(cons->frontbuf, &col, &row); 571 fibril_mutex_unlock(&cons->mtx); 572 573 async_answer_2(iid, EOK, col, row); 574 } 575 576 static void cons_write(console_t *cons, ipc_callid_t iid, ipc_call_t *icall) 482 retval = ENOENT; 483 } 484 485 async_answer_0(callid, retval); 486 } 487 } 488 489 static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request) 577 490 { 578 491 void *buf; … … 581 494 582 495 if (rc != EOK) { 583 async_answer_0( iid, rc);496 async_answer_0(rid, rc); 584 497 return; 585 498 } 586 499 500 console_serialize_start(); 501 587 502 size_t off = 0; 588 while (off < size) 589 cons_write_char(cons, str_decode(buf, &off, size)); 590 591 async_answer_1(iid, EOK, size); 503 while (off < size) { 504 wchar_t ch = str_decode(buf, &off, size); 505 write_char(cons, ch); 506 } 507 508 console_serialize_end(); 509 510 gcons_notify_char(cons->index); 511 async_answer_1(rid, EOK, size); 512 592 513 free(buf); 593 594 cons_notify_data(cons); 595 } 596 597 static void cons_read(console_t *cons, ipc_callid_t iid, ipc_call_t *icall) 514 } 515 516 static void cons_read(console_t *cons, ipc_callid_t rid, ipc_call_t *request) 598 517 { 599 518 ipc_callid_t callid; … … 601 520 if (!async_data_read_receive(&callid, &size)) { 602 521 async_answer_0(callid, EINVAL); 603 async_answer_0( iid, EINVAL);522 async_answer_0(rid, EINVAL); 604 523 return; 605 524 } … … 608 527 if (buf == NULL) { 609 528 async_answer_0(callid, ENOMEM); 610 async_answer_0( iid, ENOMEM);529 async_answer_0(rid, ENOMEM); 611 530 return; 612 531 } 613 532 614 533 size_t pos = 0; 615 while (pos < size) { 616 link_t *link = prodcons_consume(&cons->input_pc); 617 kbd_event_t *event = list_get_instance(link, kbd_event_t, link); 618 619 if (event->type == KEY_PRESS) { 620 buf[pos] = event->c; 534 kbd_event_t ev; 535 fibril_mutex_lock(&input_mutex); 536 537 recheck: 538 while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) { 539 if (ev.type == KEY_PRESS) { 540 buf[pos] = ev.c; 621 541 pos++; 622 542 } 623 624 free(event); 625 } 626 627 (void) async_data_read_finalize(callid, buf, size); 628 async_answer_1(iid, EOK, size); 629 free(buf); 630 } 631 632 static void cons_set_style(console_t *cons, console_style_t style) 633 { 634 fibril_mutex_lock(&cons->mtx); 635 screenbuffer_set_style(cons->frontbuf, style); 636 fibril_mutex_unlock(&cons->mtx); 637 } 638 639 static void cons_set_color(console_t *cons, console_color_t bgcolor, 640 console_color_t fgcolor, console_color_attr_t attr) 641 { 642 fibril_mutex_lock(&cons->mtx); 643 screenbuffer_set_color(cons->frontbuf, bgcolor, fgcolor, attr); 644 fibril_mutex_unlock(&cons->mtx); 645 } 646 647 static void cons_set_rgb_color(console_t *cons, pixel_t bgcolor, 648 pixel_t fgcolor) 649 { 650 fibril_mutex_lock(&cons->mtx); 651 screenbuffer_set_rgb_color(cons->frontbuf, bgcolor, fgcolor); 652 fibril_mutex_unlock(&cons->mtx); 653 } 654 655 static void cons_get_event(console_t *cons, ipc_callid_t iid, ipc_call_t *icall) 656 { 657 link_t *link = prodcons_consume(&cons->input_pc); 658 kbd_event_t *event = list_get_instance(link, kbd_event_t, link); 659 660 async_answer_4(iid, EOK, event->type, event->key, event->mods, event->c); 661 free(event); 662 } 663 543 } 544 545 if (pos == size) { 546 (void) async_data_read_finalize(callid, buf, size); 547 async_answer_1(rid, EOK, size); 548 free(buf); 549 } else { 550 fibril_condvar_wait(&input_cv, &input_mutex); 551 goto recheck; 552 } 553 554 fibril_mutex_unlock(&input_mutex); 555 } 556 557 static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request) 558 { 559 kbd_event_t ev; 560 561 fibril_mutex_lock(&input_mutex); 562 563 recheck: 564 if (keybuffer_pop(&cons->keybuffer, &ev)) { 565 async_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c); 566 } else { 567 fibril_condvar_wait(&input_cv, &input_mutex); 568 goto recheck; 569 } 570 571 fibril_mutex_unlock(&input_mutex); 572 } 573 574 /** Default thread for new connections */ 664 575 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 665 576 { 666 577 console_t *cons = NULL; 667 578 668 for (size_t i = 0; i < CONSOLE_COUNT; i++) { 579 size_t i; 580 for (i = 0; i < CONSOLE_COUNT; i++) { 669 581 if (i == KERNEL_CONSOLE) 670 582 continue; 671 583 672 if (consoles[i].d sid == (service_id_t) IPC_GET_ARG1(*icall)) {584 if (consoles[i].devmap_handle == (devmap_handle_t) IPC_GET_ARG1(*icall)) { 673 585 cons = &consoles[i]; 674 586 break; … … 681 593 } 682 594 683 if (atomic_postinc(&cons->refcnt) == 0) { 684 cons_set_cursor_visibility(cons, true); 685 cons_notify_connect(cons); 686 } 595 ipc_callid_t callid; 596 ipc_call_t call; 597 sysarg_t arg1; 598 sysarg_t arg2; 599 sysarg_t arg3; 600 601 int rc; 602 603 console_serialize_start(); 604 if (cons->refcount == 0) 605 gcons_notify_connect(cons->index); 606 607 cons->refcount++; 687 608 688 609 /* Accept the connection */ … … 690 611 691 612 while (true) { 692 ipc_call_t call; 693 ipc_callid_t callid = async_get_call(&call); 613 console_serialize_end(); 614 callid = async_get_call(&call); 615 console_serialize_start(); 616 617 arg1 = 0; 618 arg2 = 0; 619 arg3 = 0; 694 620 695 621 if (!IPC_GET_IMETHOD(call)) { 696 if (atomic_postdec(&cons->refcnt) == 1) 697 cons_notify_disconnect(cons); 698 622 cons->refcount--; 623 if (cons->refcount == 0) 624 gcons_notify_disconnect(cons->index); 625 console_serialize_end(); 699 626 return; 700 627 } … … 702 629 switch (IPC_GET_IMETHOD(call)) { 703 630 case VFS_OUT_READ: 631 console_serialize_end(); 704 632 cons_read(cons, callid, &call); 705 break; 633 console_serialize_start(); 634 continue; 706 635 case VFS_OUT_WRITE: 636 console_serialize_end(); 707 637 cons_write(cons, callid, &call); 708 break; 638 console_serialize_start(); 639 continue; 709 640 case VFS_OUT_SYNC: 710 cons_update(cons); 711 async_answer_0(callid, EOK); 641 fb_pending_flush(); 642 if (cons == active_console) { 643 async_obsolete_req_0_0(fb_info.phone, FB_FLUSH); 644 curs_goto(cons->scr.position_x, cons->scr.position_y); 645 } 712 646 break; 713 647 case CONSOLE_CLEAR: 714 cons_clear(cons); 715 async_answer_0(callid, EOK); 648 /* Send message to fb */ 649 if (cons == active_console) 650 async_obsolete_msg_0(fb_info.phone, FB_CLEAR); 651 652 screenbuffer_clear(&cons->scr); 653 716 654 break; 717 655 case CONSOLE_GOTO: 718 cons_set_cursor(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 719 async_answer_0(callid, EOK); 656 screenbuffer_goto(&cons->scr, 657 IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 658 if (cons == active_console) 659 curs_goto(IPC_GET_ARG1(call), 660 IPC_GET_ARG2(call)); 720 661 break; 721 662 case CONSOLE_GET_POS: 722 cons_get_cursor(cons, callid, &call); 663 arg1 = cons->scr.position_x; 664 arg2 = cons->scr.position_y; 723 665 break; 724 666 case CONSOLE_GET_SIZE: 725 async_answer_2(callid, EOK, cons->cols, cons->rows); 667 arg1 = fb_info.cols; 668 arg2 = fb_info.rows; 726 669 break; 727 670 case CONSOLE_GET_COLOR_CAP: 728 async_answer_1(callid, EOK, cons->ccaps); 671 rc = ccap_fb_to_con(fb_info.color_cap, &arg1); 672 if (rc != EOK) { 673 async_answer_0(callid, rc); 674 continue; 675 } 729 676 break; 730 677 case CONSOLE_SET_STYLE: 731 cons_set_style(cons, IPC_GET_ARG1(call)); 732 async_answer_0(callid, EOK); 678 fb_pending_flush(); 679 arg1 = IPC_GET_ARG1(call); 680 screenbuffer_set_style(&cons->scr, arg1); 681 if (cons == active_console) 682 set_style(arg1); 733 683 break; 734 684 case CONSOLE_SET_COLOR: 735 cons_set_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call), 736 IPC_GET_ARG3(call)); 737 async_answer_0(callid, EOK); 685 fb_pending_flush(); 686 arg1 = IPC_GET_ARG1(call); 687 arg2 = IPC_GET_ARG2(call); 688 arg3 = IPC_GET_ARG3(call); 689 screenbuffer_set_color(&cons->scr, arg1, arg2, arg3); 690 if (cons == active_console) 691 set_color(arg1, arg2, arg3); 738 692 break; 739 693 case CONSOLE_SET_RGB_COLOR: 740 cons_set_rgb_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 741 async_answer_0(callid, EOK); 694 fb_pending_flush(); 695 arg1 = IPC_GET_ARG1(call); 696 arg2 = IPC_GET_ARG2(call); 697 screenbuffer_set_rgb_color(&cons->scr, arg1, arg2); 698 if (cons == active_console) 699 set_rgb_color(arg1, arg2); 742 700 break; 743 701 case CONSOLE_CURSOR_VISIBILITY: 744 cons_set_cursor_visibility(cons, IPC_GET_ARG1(call)); 745 async_answer_0(callid, EOK); 702 fb_pending_flush(); 703 arg1 = IPC_GET_ARG1(call); 704 cons->scr.is_cursor_visible = arg1; 705 if (cons == active_console) 706 curs_visibility(arg1); 746 707 break; 747 708 case CONSOLE_GET_EVENT: 709 console_serialize_end(); 748 710 cons_get_event(cons, callid, &call); 749 break; 750 default: 751 async_answer_0(callid, EINVAL); 752 } 753 } 754 } 755 756 static async_sess_t *input_connect(const char *svc) 711 console_serialize_start(); 712 continue; 713 } 714 async_answer_3(callid, EOK, arg1, arg2, arg3); 715 } 716 } 717 718 static void interrupt_received(ipc_callid_t callid, ipc_call_t *call) 719 { 720 change_console(prev_console); 721 } 722 723 static async_sess_t *connect_input(const char *dev_path) 757 724 { 758 725 async_sess_t *sess; 759 service_id_t dsid; 760 761 int rc = loc_service_get_id(svc, &dsid, 0); 726 async_exch_t *exch; 727 devmap_handle_t handle; 728 729 int rc = devmap_device_get_handle(dev_path, &handle, 0); 762 730 if (rc == EOK) { 763 sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);731 sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0); 764 732 if (sess == NULL) { 765 printf("%s: Unable to connect to input service %s\n", NAME, 766 svc); 733 printf("%s: Failed to connect to input server\n", NAME); 767 734 return NULL; 768 735 } 769 } else 736 } else { 770 737 return NULL; 771 772 async_exch_t *exch = async_exchange_begin(sess); 738 } 739 740 exch = async_exchange_begin(sess); 741 if (exch == NULL) { 742 printf("%s: Failed to create callback from input server.\n", NAME); 743 return NULL; 744 } 745 746 /* NB: The callback connection is slotted for removal */ 773 747 rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL); 748 774 749 async_exchange_end(exch); 775 750 776 751 if (rc != EOK) { 777 752 async_hangup(sess); 778 printf("%s: Unable to create callback connection to service %s (%s)\n",779 NAME, s vc, str_error(rc));753 printf("%s: Failed to create callback from input server (%s).\n", 754 NAME, str_error(rc)); 780 755 return NULL; 781 756 } … … 784 759 } 785 760 786 static void interrupt_received(ipc_callid_t callid, ipc_call_t *call) 787 { 788 cons_switch(prev_console); 789 } 790 791 static async_sess_t *fb_connect(const char *svc) 792 { 793 async_sess_t *sess; 794 service_id_t dsid; 795 796 int rc = loc_service_get_id(svc, &dsid, 0); 797 if (rc == EOK) { 798 sess = loc_service_connect(EXCHANGE_SERIALIZE, dsid, 0); 799 if (sess == NULL) { 800 printf("%s: Unable to connect to framebuffer service %s\n", 801 NAME, svc); 802 return NULL; 803 } 804 } else 805 return NULL; 806 807 return sess; 808 } 809 810 static bool console_srv_init(char *input_svc, char *fb_svc) 811 { 812 /* Avoid double initialization */ 813 if (graphics_state != GRAPHICS_NONE) 814 return false; 815 816 /* Connect to input service */ 817 input_sess = input_connect(input_svc); 761 static bool console_srv_init(char *input_dev) 762 { 763 /* Connect to input server */ 764 input_sess = connect_input(input_dev); 818 765 if (input_sess == NULL) 819 766 return false; 820 767 821 /* Connect to framebuffer service */ 822 fb_sess = fb_connect(fb_svc); 823 if (fb_sess == NULL) 768 /* Connect to framebuffer driver */ 769 fb_info.phone = service_obsolete_connect_blocking(SERVICE_VIDEO, 0, 0); 770 if (fb_info.phone < 0) { 771 printf("%s: Failed to connect to video service\n", NAME); 824 772 return false; 825 826 /* Register server */827 async_set_client_connection(client_connection);828 int rc = loc_server_register(NAME);773 } 774 775 /* Register driver */ 776 int rc = devmap_driver_register(NAME, client_connection); 829 777 if (rc < 0) { 830 printf("%s: Unable to register server (%s)\n", NAME, 831 str_error(rc)); 778 printf("%s: Unable to register driver (%d)\n", NAME, rc); 832 779 return false; 833 780 } 834 781 835 fb_get_resolution(fb_sess, &xres, &yres); 782 /* Initialize gcons */ 783 gcons_init(fb_info.phone); 784 785 /* Synchronize, the gcons could put something in queue */ 786 async_obsolete_req_0_0(fb_info.phone, FB_FLUSH); 787 async_obsolete_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows); 788 async_obsolete_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap); 789 790 /* Set up shared memory buffer. */ 791 size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows; 792 interbuffer = as_get_mappable_page(ib_size); 793 794 if (as_area_create(interbuffer, ib_size, AS_AREA_READ | 795 AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) 796 interbuffer = NULL; 797 798 if (interbuffer) { 799 if (async_obsolete_share_out_start(fb_info.phone, interbuffer, 800 AS_AREA_READ) != EOK) { 801 as_area_destroy(interbuffer); 802 interbuffer = NULL; 803 } 804 } 805 806 fb_pending.cnt = 0; 807 808 /* Inititalize consoles */ 809 size_t i; 810 for (i = 0; i < CONSOLE_COUNT; i++) { 811 if (i != KERNEL_CONSOLE) { 812 if (screenbuffer_init(&consoles[i].scr, 813 fb_info.cols, fb_info.rows) == NULL) { 814 printf("%s: Unable to allocate screen buffer %zu\n", NAME, i); 815 return false; 816 } 817 screenbuffer_clear(&consoles[i].scr); 818 keybuffer_init(&consoles[i].keybuffer); 819 consoles[i].index = i; 820 consoles[i].refcount = 0; 821 822 char vc[DEVMAP_NAME_MAXLEN + 1]; 823 snprintf(vc, DEVMAP_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i); 824 825 if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) { 826 printf("%s: Unable to register device %s\n", NAME, vc); 827 return false; 828 } 829 } 830 } 836 831 837 832 /* Initialize the screen */ 838 screen_vp = fb_vp_create(fb_sess, 0, 0, xres, yres); 839 840 if ((xres >= 800) && (yres >= 600)) { 841 logo_vp = fb_vp_create(fb_sess, xres - 66, 2, 64, 60); 842 logo_img = imgmap_decode_tga((void *) helenos_tga, 843 helenos_tga_size, IMGMAP_FLAG_SHARED); 844 logo_handle = fb_imagemap_create(fb_sess, logo_img); 845 846 nameic_vp = fb_vp_create(fb_sess, 5, 17, 100, 26); 847 nameic_img = imgmap_decode_tga((void *) nameic_tga, 848 nameic_tga_size, IMGMAP_FLAG_SHARED); 849 nameic_handle = fb_imagemap_create(fb_sess, nameic_img); 850 851 cons_data_img = imgmap_decode_tga((void *) cons_data_tga, 852 cons_data_tga_size, IMGMAP_FLAG_SHARED); 853 cons_dis_img = imgmap_decode_tga((void *) cons_dis_tga, 854 cons_dis_tga_size, IMGMAP_FLAG_SHARED); 855 cons_dis_sel_img = imgmap_decode_tga((void *) cons_dis_sel_tga, 856 cons_dis_sel_tga_size, IMGMAP_FLAG_SHARED); 857 cons_idle_img = imgmap_decode_tga((void *) cons_idle_tga, 858 cons_idle_tga_size, IMGMAP_FLAG_SHARED); 859 cons_kernel_img = imgmap_decode_tga((void *) cons_kernel_tga, 860 cons_kernel_tga_size, IMGMAP_FLAG_SHARED); 861 cons_sel_img = imgmap_decode_tga((void *) cons_sel_tga, 862 cons_sel_tga_size, IMGMAP_FLAG_SHARED); 863 864 state_icons[CONS_DISCONNECTED] = 865 fb_imagemap_create(fb_sess, cons_dis_img); 866 state_icons[CONS_DISCONNECTED_SELECTED] = 867 fb_imagemap_create(fb_sess, cons_dis_sel_img); 868 state_icons[CONS_SELECTED] = 869 fb_imagemap_create(fb_sess, cons_sel_img); 870 state_icons[CONS_IDLE] = 871 fb_imagemap_create(fb_sess, cons_idle_img); 872 state_icons[CONS_DATA] = 873 fb_imagemap_create(fb_sess, cons_data_img); 874 state_icons[CONS_KERNEL] = 875 fb_imagemap_create(fb_sess, cons_kernel_img); 876 877 anim_1_img = imgmap_decode_tga((void *) anim_1_tga, 878 anim_1_tga_size, IMGMAP_FLAG_SHARED); 879 anim_2_img = imgmap_decode_tga((void *) anim_2_tga, 880 anim_2_tga_size, IMGMAP_FLAG_SHARED); 881 anim_3_img = imgmap_decode_tga((void *) anim_3_tga, 882 anim_3_tga_size, IMGMAP_FLAG_SHARED); 883 anim_4_img = imgmap_decode_tga((void *) anim_4_tga, 884 anim_4_tga_size, IMGMAP_FLAG_SHARED); 885 886 anim_1 = fb_imagemap_create(fb_sess, anim_1_img); 887 anim_2 = fb_imagemap_create(fb_sess, anim_2_img); 888 anim_3 = fb_imagemap_create(fb_sess, anim_3_img); 889 anim_4 = fb_imagemap_create(fb_sess, anim_4_img); 890 891 anim_seq = fb_sequence_create(fb_sess); 892 fb_sequence_add_imagemap(fb_sess, anim_seq, anim_1); 893 fb_sequence_add_imagemap(fb_sess, anim_seq, anim_2); 894 fb_sequence_add_imagemap(fb_sess, anim_seq, anim_3); 895 fb_sequence_add_imagemap(fb_sess, anim_seq, anim_4); 896 897 console_vp = fb_vp_create(fb_sess, CONSOLE_MARGIN, CONSOLE_TOP, 898 xres - 2 * CONSOLE_MARGIN, yres - (CONSOLE_TOP + CONSOLE_MARGIN)); 899 900 fb_vp_clear(fb_sess, screen_vp); 901 fb_vp_imagemap_damage(fb_sess, logo_vp, logo_handle, 902 0, 0, 64, 60); 903 fb_vp_imagemap_damage(fb_sess, nameic_vp, nameic_handle, 904 0, 0, 100, 26); 905 906 graphics_state = GRAPHICS_FULL; 907 } else { 908 console_vp = screen_vp; 909 graphics_state = GRAPHICS_BASIC; 910 } 911 912 fb_vp_set_style(fb_sess, console_vp, STYLE_NORMAL); 913 fb_vp_clear(fb_sess, console_vp); 914 915 sysarg_t cols; 916 sysarg_t rows; 917 fb_vp_get_dimensions(fb_sess, console_vp, &cols, &rows); 918 919 console_caps_t ccaps; 920 fb_vp_get_caps(fb_sess, console_vp, &ccaps); 921 922 mouse.x = xres / 2; 923 mouse.y = yres / 2; 924 mouse.pressed = false; 925 926 /* Inititalize consoles */ 927 for (size_t i = 0; i < CONSOLE_COUNT; i++) { 928 consoles[i].index = i; 929 atomic_set(&consoles[i].refcnt, 0); 930 fibril_mutex_initialize(&consoles[i].mtx); 931 prodcons_initialize(&consoles[i].input_pc); 932 933 if (graphics_state == GRAPHICS_FULL) { 934 /* Create state buttons */ 935 consoles[i].state_vp = 936 fb_vp_create(fb_sess, STATE_START + (xres - 800) / 2 + 937 CONSOLE_MARGIN + i * (STATE_WIDTH + STATE_SPACE), 938 STATE_TOP, STATE_WIDTH, STATE_HEIGHT); 939 } 940 941 if (i == KERNEL_CONSOLE) { 942 consoles[i].state = CONS_KERNEL; 943 cons_redraw_state(&consoles[i]); 944 cons_kernel_sequence_start(&consoles[i]); 945 continue; 946 } 947 948 if (i == 0) 949 consoles[i].state = CONS_DISCONNECTED_SELECTED; 950 else 951 consoles[i].state = CONS_DISCONNECTED; 952 953 consoles[i].cols = cols; 954 consoles[i].rows = rows; 955 consoles[i].ccaps = ccaps; 956 consoles[i].frontbuf = 957 screenbuffer_create(cols, rows, SCREENBUFFER_FLAG_SHARED); 958 959 if (consoles[i].frontbuf == NULL) { 960 printf("%s: Unable to allocate frontbuffer %zu\n", NAME, i); 961 return false; 962 } 963 964 consoles[i].fbid = fb_frontbuf_create(fb_sess, consoles[i].frontbuf); 965 if (consoles[i].fbid == 0) { 966 printf("%s: Unable to create frontbuffer %zu\n", NAME, i); 967 return false; 968 } 969 970 cons_redraw_state(&consoles[i]); 971 972 char vc[LOC_NAME_MAXLEN + 1]; 973 snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i); 974 975 if (loc_service_register(vc, &consoles[i].dsid) != EOK) { 976 printf("%s: Unable to register device %s\n", NAME, vc); 977 return false; 978 } 979 } 833 console_serialize_start(); 834 gcons_redraw_console(); 835 set_style(STYLE_NORMAL); 836 screen_clear(); 837 curs_goto(0, 0); 838 curs_visibility(active_console->scr.is_cursor_visible); 839 console_serialize_end(); 980 840 981 841 /* Receive kernel notifications */ 982 842 async_set_interrupt_received(interrupt_received); 983 rc = event_subscribe(EVENT_KCONSOLE, 0); 984 if (rc != EOK) 985 printf("%s: Failed to register kconsole notifications (%s)\n", 986 NAME, str_error(rc)); 843 if (event_subscribe(EVENT_KCONSOLE, 0) != EOK) 844 printf("%s: Error registering kconsole notifications\n", NAME); 987 845 988 846 return true; … … 991 849 static void usage(void) 992 850 { 993 printf("Usage: console <input_dev> <framebuffer_dev>\n");851 printf("Usage: console <input_dev>\n"); 994 852 } 995 853 996 854 int main(int argc, char *argv[]) 997 855 { 998 if (argc < 3) {856 if (argc < 2) { 999 857 usage(); 1000 858 return -1; 1001 859 } 1002 860 1003 printf( "%s: HelenOS Console service\n", NAME);1004 1005 if (!console_srv_init(argv[1] , argv[2]))861 printf(NAME ": HelenOS Console service\n"); 862 863 if (!console_srv_init(argv[1])) 1006 864 return -1; 1007 865 1008 printf("%s: Accepting connections\n", NAME); 1009 task_retval(0); 866 printf(NAME ": Accepting connections\n"); 1010 867 async_manager(); 1011 868
Note:
See TracChangeset
for help on using the changeset viewer.
