Changes in uspace/srv/hid/console/console.c [5d94b16c:2f90b46] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/console/console.c
r5d94b16c r2f90b46 36 36 #include <stdio.h> 37 37 #include <adt/prodcons.h> 38 #include <io/input.h> 38 #include <ipc/input.h> 39 #include <ipc/console.h> 39 40 #include <ipc/vfs.h> 40 41 #include <errno.h> … … 42 43 #include <loc.h> 43 44 #include <event.h> 44 #include <io/con_srv.h>45 #include <io/kbd_event.h>46 45 #include <io/keycode.h> 47 #include <io/chargrid.h> 48 #include <io/output.h> 46 #include <screenbuffer.h> 47 #include <fb.h> 48 #include <imgmap.h> 49 49 #include <align.h> 50 50 #include <malloc.h> 51 51 #include <as.h> 52 52 #include <fibril_synch.h> 53 #include "images.h" 53 54 #include "console.h" 54 55 … … 56 57 #define NAMESPACE "term" 57 58 58 #define UTF8_CHAR_BUFFER_SIZE (STR_BOUNDS(1) + 1) 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; 59 77 60 78 typedef struct { 61 atomic_t refcnt; /**< Connection reference count */ 62 prodcons_t input_pc; /**< Incoming keyboard events */ 63 64 /** 65 * Not yet sent bytes of last char event. 66 */ 67 char char_remains[UTF8_CHAR_BUFFER_SIZE]; 68 size_t char_remains_len; /**< Number of not yet sent bytes. */ 69 70 fibril_mutex_t mtx; /**< Lock protecting mutable fields */ 71 72 size_t index; /**< Console index */ 73 service_id_t dsid; /**< Service handle */ 74 75 sysarg_t cols; /**< Number of columns */ 76 sysarg_t rows; /**< Number of rows */ 77 console_caps_t ccaps; /**< Console capabilities */ 78 79 chargrid_t *frontbuf; /**< Front buffer */ 80 frontbuf_handle_t fbid; /**< Front buffer handle */ 81 con_srvs_t srvs; /**< Console service setup */ 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 */ 82 95 } console_t; 83 96 84 /** Input server proxy */ 85 static input_t *input; 86 87 /** Session to the output server */ 88 static async_sess_t *output_sess; 89 90 /** Output dimensions */ 91 static sysarg_t cols; 92 static sysarg_t rows; 97 typedef enum { 98 GRAPHICS_NONE = 0, 99 GRAPHICS_BASIC = 1, 100 GRAPHICS_FULL = 2 101 } 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; 93 118 94 119 /** Array of data for virtual consoles */ … … 102 127 static console_t *kernel_console = &consoles[KERNEL_CONSOLE]; 103 128 104 static int input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t); 105 static int input_ev_move(input_t *, int, int); 106 static int input_ev_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned); 107 static int input_ev_button(input_t *, int, int); 108 109 static input_ev_ops_t input_ev_ops = { 110 .key = input_ev_key, 111 .move = input_ev_move, 112 .abs_move = input_ev_abs_move, 113 .button = input_ev_button 114 }; 115 116 static int cons_open(con_srvs_t *, con_srv_t *); 117 static int cons_close(con_srv_t *); 118 static int cons_read(con_srv_t *, void *, size_t); 119 static int cons_write(con_srv_t *, void *, size_t); 120 static void cons_sync(con_srv_t *); 121 static void cons_clear(con_srv_t *); 122 static void cons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row); 123 static int cons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *); 124 static int cons_get_size(con_srv_t *, sysarg_t *, sysarg_t *); 125 static int cons_get_color_cap(con_srv_t *, console_caps_t *); 126 static void cons_set_style(con_srv_t *, console_style_t); 127 static void cons_set_color(con_srv_t *, console_color_t, console_color_t, 128 console_color_attr_t); 129 static void cons_set_rgb_color(con_srv_t *, pixel_t, pixel_t); 130 static void cons_set_cursor_visibility(con_srv_t *, bool); 131 static int cons_get_event(con_srv_t *, kbd_event_t *); 132 133 static con_ops_t con_ops = { 134 .open = cons_open, 135 .close = cons_close, 136 .read = cons_read, 137 .write = cons_write, 138 .sync = cons_sync, 139 .clear = cons_clear, 140 .set_pos = cons_set_pos, 141 .get_pos = cons_get_pos, 142 .get_size = cons_get_size, 143 .get_color_cap = cons_get_color_cap, 144 .set_style = cons_set_style, 145 .set_color = cons_set_color, 146 .set_rgb_color = cons_set_rgb_color, 147 .set_cursor_visibility = cons_set_cursor_visibility, 148 .get_event = cons_get_event 149 }; 150 151 static console_t *srv_to_console(con_srv_t *srv) 152 { 153 return srv->srvs->sarg; 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 160 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); 154 254 } 155 255 … … 160 260 161 261 if ((cons == active_console) && (active_console != kernel_console)) { 162 output_update(output_sess, cons->fbid);163 output_cursor_update(output_sess, cons->fbid);262 fb_vp_update(fb_sess, console_vp, cons->fbid); 263 fb_vp_cursor_update(fb_sess, console_vp, cons->fbid); 164 264 } 165 265 … … 174 274 175 275 if ((cons == active_console) && (active_console != kernel_console)) 176 output_cursor_update(output_sess, cons->fbid);276 fb_vp_cursor_update(fb_sess, console_vp, cons->fbid); 177 277 178 278 fibril_mutex_unlock(&cons->mtx); … … 180 280 } 181 281 182 static void cons_damage(console_t *cons) 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) 183 292 { 184 293 fibril_mutex_lock(&switch_mtx); … … 186 295 187 296 if ((cons == active_console) && (active_console != kernel_console)) { 188 output_damage(output_sess, cons->fbid, 0, 0, cons->cols,297 fb_vp_damage(fb_sess, console_vp, cons->fbid, 0, 0, cons->cols, 189 298 cons->rows); 190 output_cursor_update(output_sess, cons->fbid);299 fb_vp_cursor_update(fb_sess, console_vp, cons->fbid); 191 300 } 192 301 … … 205 314 206 315 if (cons == kernel_console) { 207 output_yield(output_sess);316 fb_yield(fb_sess); 208 317 if (!console_kcon()) { 209 output_claim(output_sess);318 fb_claim(fb_sess); 210 319 fibril_mutex_unlock(&switch_mtx); 211 320 return; … … 214 323 215 324 if (active_console == kernel_console) 216 output_claim(output_sess);325 fb_claim(fb_sess); 217 326 218 327 prev_console = active_console; 219 328 active_console = cons; 220 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 221 341 fibril_mutex_unlock(&switch_mtx); 222 342 223 cons_damage (cons);343 cons_damage_all(cons); 224 344 } 225 345 … … 227 347 { 228 348 fibril_mutex_lock(&switch_mtx); 229 349 230 350 console_t *active_uspace = active_console; 231 if (active_uspace == kernel_console) 351 if (active_uspace == kernel_console) { 232 352 active_uspace = prev_console; 233 353 } 234 354 assert(active_uspace != kernel_console); 235 355 236 356 fibril_mutex_unlock(&switch_mtx); 237 357 238 358 return active_uspace; 239 359 } 240 360 241 static int input_ev_key(input_t *input, kbd_event_type_t type, keycode_t key, 242 keymod_t mods, wchar_t c) 243 { 244 if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) && 245 ((mods & KM_CTRL) == 0)) { 246 cons_switch(&consoles[key - KC_F1]); 247 } else { 248 /* Got key press/release event */ 249 kbd_event_t *event = 250 (kbd_event_t *) malloc(sizeof(kbd_event_t)); 251 if (event == NULL) { 252 return ENOMEM; 253 } 254 255 link_initialize(&event->link); 256 event->type = type; 257 event->key = key; 258 event->mods = mods; 259 event->c = c; 260 261 /* 262 * Kernel console does not read events 263 * from us, so we will redirect them 264 * to the (last) active userspace console 265 * if necessary. 266 */ 267 console_t *target_console = cons_get_active_uspace(); 268 269 prodcons_produce(&target_console->input_pc, 270 &event->link); 271 } 272 273 return EOK; 274 } 275 276 static int input_ev_move(input_t *input, int dx, int dy) 277 { 278 return EOK; 279 } 280 281 static int input_ev_abs_move(input_t *input, unsigned x , unsigned y, 282 unsigned max_x, unsigned max_y) 283 { 284 return EOK; 285 } 286 287 static int input_ev_button(input_t *input, int bnum, int bpress) 288 { 289 return EOK; 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 409 * 410 * @param state Button state (true - pressed, false - depressed) 411 * 412 */ 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 440 static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg) 441 { 442 /* Ignore parameters, the connection is already opened */ 443 while (true) { 444 ipc_call_t call; 445 ipc_callid_t callid = async_get_call(&call); 446 447 if (!IPC_GET_IMETHOD(call)) { 448 /* TODO: Handle hangup */ 449 async_hangup(input_sess); 450 return; 451 } 452 453 kbd_event_type_t type; 454 keycode_t key; 455 keymod_t mods; 456 wchar_t c; 457 458 switch (IPC_GET_IMETHOD(call)) { 459 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); 464 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); 493 } 494 495 async_answer_0(callid, EOK); 496 break; 497 case INPUT_EVENT_MOVE: 498 cons_mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 499 async_answer_0(callid, EOK); 500 break; 501 case INPUT_EVENT_BUTTON: 502 /* Got pointer button press/release event */ 503 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); 508 } 509 async_answer_0(callid, EOK); 510 break; 511 default: 512 async_answer_0(callid, EINVAL); 513 } 514 } 290 515 } 291 516 … … 299 524 switch (ch) { 300 525 case '\n': 301 updated = chargrid_newline(cons->frontbuf);526 updated = screenbuffer_newline(cons->frontbuf); 302 527 break; 303 528 case '\r': 304 529 break; 305 530 case '\t': 306 updated = chargrid_tabstop(cons->frontbuf, 8);531 updated = screenbuffer_tabstop(cons->frontbuf, 8); 307 532 break; 308 533 case '\b': 309 updated = chargrid_backspace(cons->frontbuf);534 updated = screenbuffer_backspace(cons->frontbuf); 310 535 break; 311 536 default: 312 updated = chargrid_putchar(cons->frontbuf, ch, true);537 updated = screenbuffer_putchar(cons->frontbuf, ch, true); 313 538 } 314 539 … … 319 544 } 320 545 321 static void cons_set_cursor _vis(console_t *cons, bool visible)322 { 323 fibril_mutex_lock(&cons->mtx); 324 chargrid_set_cursor_visibility(cons->frontbuf, visible);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); 325 550 fibril_mutex_unlock(&cons->mtx); 326 551 … … 328 553 } 329 554 330 static int cons_open(con_srvs_t *srvs, con_srv_t *srv) 331 { 332 return EOK; 333 } 334 335 static int cons_close(con_srv_t *srv) 336 { 337 return EOK; 338 } 339 340 static int cons_read(con_srv_t *srv, void *buf, size_t size) 341 { 342 uint8_t *bbuf = buf; 343 console_t *cons = srv_to_console(srv); 344 size_t pos = 0; 345 346 /* 347 * Read input from keyboard and copy it to the buffer. 348 * We need to handle situation when wchar is split by 2 following 349 * reads. 350 */ 351 while (pos < size) { 352 /* Copy to the buffer remaining characters. */ 353 while ((pos < size) && (cons->char_remains_len > 0)) { 354 bbuf[pos] = cons->char_remains[0]; 355 pos++; 356 357 /* Unshift the array. */ 358 for (size_t i = 1; i < cons->char_remains_len; i++) 359 cons->char_remains[i - 1] = cons->char_remains[i]; 360 361 cons->char_remains_len--; 362 } 363 364 /* Still not enough? Then get another key from the queue. */ 365 if (pos < size) { 366 link_t *link = prodcons_consume(&cons->input_pc); 367 kbd_event_t *event = list_get_instance(link, kbd_event_t, link); 368 369 /* Accept key presses of printable chars only. */ 370 if ((event->type == KEY_PRESS) && (event->c != 0)) { 371 wchar_t tmp[2] = { event->c, 0 }; 372 wstr_to_str(cons->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp); 373 cons->char_remains_len = str_size(cons->char_remains); 374 } 375 376 free(event); 377 } 378 } 379 380 return size; 381 } 382 383 static int cons_write(con_srv_t *srv, void *data, size_t size) 384 { 385 console_t *cons = srv_to_console(srv); 386 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) 577 { 578 void *buf; 579 size_t size; 580 int rc = async_data_write_accept(&buf, false, 0, 0, 0, &size); 581 582 if (rc != EOK) { 583 async_answer_0(iid, rc); 584 return; 585 } 586 387 587 size_t off = 0; 388 588 while (off < size) 389 cons_write_char(cons, str_decode(data, &off, size)); 390 return size; 391 } 392 393 static void cons_sync(con_srv_t *srv) 394 { 395 console_t *cons = srv_to_console(srv); 396 397 cons_update(cons); 398 } 399 400 static void cons_clear(con_srv_t *srv) 401 { 402 console_t *cons = srv_to_console(srv); 403 404 fibril_mutex_lock(&cons->mtx); 405 chargrid_clear(cons->frontbuf); 406 fibril_mutex_unlock(&cons->mtx); 407 408 cons_update(cons); 409 } 410 411 static void cons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row) 412 { 413 console_t *cons = srv_to_console(srv); 414 415 fibril_mutex_lock(&cons->mtx); 416 chargrid_set_cursor(cons->frontbuf, col, row); 417 fibril_mutex_unlock(&cons->mtx); 418 419 cons_update_cursor(cons); 420 } 421 422 static int cons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row) 423 { 424 console_t *cons = srv_to_console(srv); 425 426 fibril_mutex_lock(&cons->mtx); 427 chargrid_get_cursor(cons->frontbuf, col, row); 428 fibril_mutex_unlock(&cons->mtx); 429 430 return EOK; 431 } 432 433 static int cons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows) 434 { 435 console_t *cons = srv_to_console(srv); 436 437 fibril_mutex_lock(&cons->mtx); 438 *cols = cons->cols; 439 *rows = cons->rows; 440 fibril_mutex_unlock(&cons->mtx); 441 442 return EOK; 443 } 444 445 static int cons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps) 446 { 447 console_t *cons = srv_to_console(srv); 448 449 fibril_mutex_lock(&cons->mtx); 450 *ccaps = cons->ccaps; 451 fibril_mutex_unlock(&cons->mtx); 452 453 return EOK; 454 } 455 456 static void cons_set_style(con_srv_t *srv, console_style_t style) 457 { 458 console_t *cons = srv_to_console(srv); 459 460 fibril_mutex_lock(&cons->mtx); 461 chargrid_set_style(cons->frontbuf, style); 462 fibril_mutex_unlock(&cons->mtx); 463 } 464 465 static void cons_set_color(con_srv_t *srv, console_color_t bgcolor, 589 cons_write_char(cons, str_decode(buf, &off, size)); 590 591 async_answer_1(iid, EOK, size); 592 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) 598 { 599 ipc_callid_t callid; 600 size_t size; 601 if (!async_data_read_receive(&callid, &size)) { 602 async_answer_0(callid, EINVAL); 603 async_answer_0(iid, EINVAL); 604 return; 605 } 606 607 char *buf = (char *) malloc(size); 608 if (buf == NULL) { 609 async_answer_0(callid, ENOMEM); 610 async_answer_0(iid, ENOMEM); 611 return; 612 } 613 614 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; 621 pos++; 622 } 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, 466 640 console_color_t fgcolor, console_color_attr_t attr) 467 641 { 468 console_t *cons = srv_to_console(srv); 469 470 fibril_mutex_lock(&cons->mtx); 471 chargrid_set_color(cons->frontbuf, bgcolor, fgcolor, attr); 472 fibril_mutex_unlock(&cons->mtx); 473 } 474 475 static void cons_set_rgb_color(con_srv_t *srv, pixel_t bgcolor, 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, 476 648 pixel_t fgcolor) 477 649 { 478 console_t *cons = srv_to_console(srv); 479 480 fibril_mutex_lock(&cons->mtx); 481 chargrid_set_rgb_color(cons->frontbuf, bgcolor, fgcolor); 482 fibril_mutex_unlock(&cons->mtx); 483 } 484 485 static void cons_set_cursor_visibility(con_srv_t *srv, bool visible) 486 { 487 console_t *cons = srv_to_console(srv); 488 489 cons_set_cursor_vis(cons, visible); 490 } 491 492 static int cons_get_event(con_srv_t *srv, kbd_event_t *event) 493 { 494 console_t *cons = srv_to_console(srv); 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 { 495 657 link_t *link = prodcons_consume(&cons->input_pc); 496 kbd_event_t *kevent = list_get_instance(link, kbd_event_t, link); 497 498 *event = *kevent; 499 free(kevent); 500 return EOK; 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); 501 662 } 502 663 … … 520 681 } 521 682 522 if (atomic_postinc(&cons->refcnt) == 0) 523 cons_set_cursor_vis(cons, true); 524 525 con_conn(iid, icall, &cons->srvs); 526 } 527 528 529 static int input_connect(const char *svc) 683 if (atomic_postinc(&cons->refcnt) == 0) { 684 cons_set_cursor_visibility(cons, true); 685 cons_notify_connect(cons); 686 } 687 688 /* Accept the connection */ 689 async_answer_0(iid, EOK); 690 691 while (true) { 692 ipc_call_t call; 693 ipc_callid_t callid = async_get_call(&call); 694 695 if (!IPC_GET_IMETHOD(call)) { 696 if (atomic_postdec(&cons->refcnt) == 1) 697 cons_notify_disconnect(cons); 698 699 return; 700 } 701 702 switch (IPC_GET_IMETHOD(call)) { 703 case VFS_OUT_READ: 704 cons_read(cons, callid, &call); 705 break; 706 case VFS_OUT_WRITE: 707 cons_write(cons, callid, &call); 708 break; 709 case VFS_OUT_SYNC: 710 cons_update(cons); 711 async_answer_0(callid, EOK); 712 break; 713 case CONSOLE_CLEAR: 714 cons_clear(cons); 715 async_answer_0(callid, EOK); 716 break; 717 case CONSOLE_GOTO: 718 cons_set_cursor(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 719 async_answer_0(callid, EOK); 720 break; 721 case CONSOLE_GET_POS: 722 cons_get_cursor(cons, callid, &call); 723 break; 724 case CONSOLE_GET_SIZE: 725 async_answer_2(callid, EOK, cons->cols, cons->rows); 726 break; 727 case CONSOLE_GET_COLOR_CAP: 728 async_answer_1(callid, EOK, cons->ccaps); 729 break; 730 case CONSOLE_SET_STYLE: 731 cons_set_style(cons, IPC_GET_ARG1(call)); 732 async_answer_0(callid, EOK); 733 break; 734 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); 738 break; 739 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); 742 break; 743 case CONSOLE_CURSOR_VISIBILITY: 744 cons_set_cursor_visibility(cons, IPC_GET_ARG1(call)); 745 async_answer_0(callid, EOK); 746 break; 747 case CONSOLE_GET_EVENT: 748 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) 530 757 { 531 758 async_sess_t *sess; … … 533 760 534 761 int rc = loc_service_get_id(svc, &dsid, 0); 535 if (rc != EOK) { 536 printf("%s: Input service %s not found\n", NAME, svc); 537 return rc; 538 } 539 540 sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0); 541 if (sess == NULL) { 542 printf("%s: Unable to connect to input service %s\n", NAME, 543 svc); 544 return EIO; 545 } 546 547 rc = input_open(sess, &input_ev_ops, NULL, &input); 762 if (rc == EOK) { 763 sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0); 764 if (sess == NULL) { 765 printf("%s: Unable to connect to input service %s\n", NAME, 766 svc); 767 return NULL; 768 } 769 } else 770 return NULL; 771 772 async_exch_t *exch = async_exchange_begin(sess); 773 rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL); 774 async_exchange_end(exch); 775 548 776 if (rc != EOK) { 549 777 async_hangup(sess); 550 printf("%s: Unable to c ommunicate withservice %s (%s)\n",778 printf("%s: Unable to create callback connection to service %s (%s)\n", 551 779 NAME, svc, str_error(rc)); 552 return rc;553 } 554 555 return EOK;780 return NULL; 781 } 782 783 return sess; 556 784 } 557 785 … … 561 789 } 562 790 563 static async_sess_t * output_connect(const char *svc)791 static async_sess_t *fb_connect(const char *svc) 564 792 { 565 793 async_sess_t *sess; … … 570 798 sess = loc_service_connect(EXCHANGE_SERIALIZE, dsid, 0); 571 799 if (sess == NULL) { 572 printf("%s: Unable to connect to outputservice %s\n",800 printf("%s: Unable to connect to framebuffer service %s\n", 573 801 NAME, svc); 574 802 return NULL; … … 580 808 } 581 809 582 static bool console_srv_init(char *input_svc, char *output_svc) 583 { 584 int rc; 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; 585 815 586 816 /* Connect to input service */ 587 rc= input_connect(input_svc);588 if ( rc != EOK)817 input_sess = input_connect(input_svc); 818 if (input_sess == NULL) 589 819 return false; 590 820 591 /* Connect to outputservice */592 output_sess = output_connect(output_svc);593 if ( output_sess == NULL)821 /* Connect to framebuffer service */ 822 fb_sess = fb_connect(fb_svc); 823 if (fb_sess == NULL) 594 824 return false; 595 825 596 826 /* Register server */ 597 827 async_set_client_connection(client_connection); 598 rc = loc_server_register(NAME);828 int rc = loc_server_register(NAME); 599 829 if (rc != EOK) { 600 830 printf("%s: Unable to register server (%s)\n", NAME, … … 603 833 } 604 834 605 output_get_dimensions(output_sess, &cols, &rows); 606 output_set_style(output_sess, STYLE_NORMAL); 835 fb_get_resolution(fb_sess, &xres, &yres); 836 837 /* 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); 607 918 608 919 console_caps_t ccaps; 609 output_get_caps(output_sess, &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; 610 925 611 926 /* Inititalize consoles */ … … 615 930 fibril_mutex_initialize(&consoles[i].mtx); 616 931 prodcons_initialize(&consoles[i].input_pc); 617 consoles[i].char_remains_len = 0; 618 619 if (i == KERNEL_CONSOLE) 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]); 620 945 continue; 946 } 947 948 if (i == 0) 949 consoles[i].state = CONS_DISCONNECTED_SELECTED; 950 else 951 consoles[i].state = CONS_DISCONNECTED; 621 952 622 953 consoles[i].cols = cols; … … 624 955 consoles[i].ccaps = ccaps; 625 956 consoles[i].frontbuf = 626 chargrid_create(cols, rows, CHARGRID_FLAG_SHARED);957 screenbuffer_create(cols, rows, SCREENBUFFER_FLAG_SHARED); 627 958 628 959 if (consoles[i].frontbuf == NULL) { … … 631 962 } 632 963 633 consoles[i].fbid = output_frontbuf_create(output_sess, 634 consoles[i].frontbuf); 964 consoles[i].fbid = fb_frontbuf_create(fb_sess, consoles[i].frontbuf); 635 965 if (consoles[i].fbid == 0) { 636 966 printf("%s: Unable to create frontbuffer %zu\n", NAME, i); … … 638 968 } 639 969 640 con_srvs_init(&consoles[i].srvs); 641 consoles[i].srvs.ops = &con_ops; 642 consoles[i].srvs.sarg = &consoles[i]; 970 cons_redraw_state(&consoles[i]); 643 971 644 972 char vc[LOC_NAME_MAXLEN + 1]; … … 650 978 } 651 979 } 652 653 cons_damage(active_console);654 980 655 981 /* Receive kernel notifications */ … … 663 989 } 664 990 665 static void usage( char *name)666 { 667 printf("Usage: %s <input_dev> <output_dev>\n", name);991 static void usage(void) 992 { 993 printf("Usage: console <input_dev> <framebuffer_dev>\n"); 668 994 } 669 995 … … 671 997 { 672 998 if (argc < 3) { 673 usage( argv[0]);999 usage(); 674 1000 return -1; 675 1001 } … … 684 1010 async_manager(); 685 1011 686 /* Never reached */687 1012 return 0; 688 1013 }
Note:
See TracChangeset
for help on using the changeset viewer.