Changes in uspace/srv/hid/console/console.c [854eddd6:8c74d15] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/console/console.c
r854eddd6 r8c74d15 1 1 /* 2 2 * Copyright (c) 2006 Josef Cejka 3 * Copyright (c) 2011 Jiri Svoboda4 3 * All rights reserved. 5 4 * … … 35 34 36 35 #include <libc.h> 37 #include <ipc/ input.h>36 #include <ipc/kbd.h> 38 37 #include <io/keycode.h> 38 #include <ipc/mouse.h> 39 39 #include <ipc/fb.h> 40 40 #include <ipc/services.h> 41 #include <ns.h> 42 #include <ns_obsolete.h> 41 #include <ipc/ns.h> 43 42 #include <errno.h> 44 43 #include <str_error.h> … … 46 45 #include <unistd.h> 47 46 #include <async.h> 48 #include <async_obsolete.h>49 47 #include <adt/fifo.h> 50 48 #include <sys/mman.h> … … 54 52 #include <event.h> 55 53 #include <devmap.h> 56 #include <devmap_obsolete.h>57 54 #include <fcntl.h> 58 55 #include <vfs/vfs.h> … … 60 57 #include <io/style.h> 61 58 #include <io/screenbuffer.h> 59 #include <inttypes.h> 62 60 63 61 #include "console.h" … … 65 63 #include "keybuffer.h" 66 64 65 67 66 #define NAME "console" 68 67 #define NAMESPACE "term" 69 70 /** Phone to the input server. */ 71 static int input_phone; 68 /** Interval for checking for new keyboard (1/4s). */ 69 #define HOTPLUG_WATCH_INTERVAL (1000 * 250) 70 71 /* Kernel defines 32 but does not export it. */ 72 #define MAX_IPC_OUTGOING_PHONES 128 73 /** To allow proper phone closing. */ 74 static ipc_callid_t driver_phones[MAX_IPC_OUTGOING_PHONES] = { 0 }; 75 76 /** Phone to the keyboard driver. */ 77 static int kbd_phone; 78 79 /** Phone to the mouse driver. */ 80 static int mouse_phone; 72 81 73 82 /** Information about framebuffer */ … … 88 97 } console_t; 89 98 99 100 90 101 /** Array of data for virtual consoles */ 91 102 static console_t consoles[CONSOLE_COUNT]; … … 111 122 static void curs_visibility(bool visible) 112 123 { 113 async_ obsolete_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);124 async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); 114 125 } 115 126 116 127 static void curs_hide_sync(void) 117 128 { 118 async_ obsolete_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);129 async_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 119 130 } 120 131 121 132 static void curs_goto(sysarg_t x, sysarg_t y) 122 133 { 123 async_ obsolete_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);134 async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y); 124 135 } 125 136 126 137 static void screen_clear(void) 127 138 { 128 async_ obsolete_msg_0(fb_info.phone, FB_CLEAR);139 async_msg_0(fb_info.phone, FB_CLEAR); 129 140 } 130 141 131 142 static void screen_yield(void) 132 143 { 133 async_ obsolete_req_0_0(fb_info.phone, FB_SCREEN_YIELD);144 async_req_0_0(fb_info.phone, FB_SCREEN_YIELD); 134 145 } 135 146 136 147 static void screen_reclaim(void) 137 148 { 138 async_ obsolete_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);139 } 140 141 static void input_yield(void)142 { 143 async_ obsolete_req_0_0(input_phone, INPUT_YIELD);144 } 145 146 static void input_reclaim(void)147 { 148 async_ obsolete_req_0_0(input_phone, INPUT_RECLAIM);149 async_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM); 150 } 151 152 static void kbd_yield(void) 153 { 154 async_req_0_0(kbd_phone, KBD_YIELD); 155 } 156 157 static void kbd_reclaim(void) 158 { 159 async_req_0_0(kbd_phone, KBD_RECLAIM); 149 160 } 150 161 151 162 static void set_style(uint8_t style) 152 163 { 153 async_ obsolete_msg_1(fb_info.phone, FB_SET_STYLE, style);164 async_msg_1(fb_info.phone, FB_SET_STYLE, style); 154 165 } 155 166 156 167 static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags) 157 168 { 158 async_ obsolete_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);169 async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags); 159 170 } 160 171 161 172 static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor) 162 173 { 163 async_ obsolete_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);174 async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 164 175 } 165 176 … … 216 227 } 217 228 218 async_ obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,229 async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, 219 230 x0, y0, width, height); 220 231 } … … 257 268 static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row) 258 269 { 259 async_ obsolete_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);270 async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row); 260 271 } 261 272 … … 306 317 307 318 if (cons == active_console) 308 async_ obsolete_msg_1(fb_info.phone, FB_SCROLL, 1);319 async_msg_1(fb_info.phone, FB_SCROLL, 1); 309 320 } 310 321 … … 317 328 static void change_console(console_t *cons) 318 329 { 319 if (cons == active_console) 330 if (cons == active_console) { 320 331 return; 332 } 321 333 322 334 fb_pending_flush(); 323 335 324 336 if (cons == kernel_console) { 325 async_ obsolete_serialize_start();337 async_serialize_start(); 326 338 curs_hide_sync(); 327 339 gcons_in_kernel(); 328 340 screen_yield(); 329 input_yield();330 async_ obsolete_serialize_end();341 kbd_yield(); 342 async_serialize_end(); 331 343 332 344 if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) { … … 338 350 339 351 if (cons != kernel_console) { 340 async_ obsolete_serialize_start();352 async_serialize_start(); 341 353 342 354 if (active_console == kernel_console) { 343 355 screen_reclaim(); 344 input_reclaim();356 kbd_reclaim(); 345 357 gcons_redraw_console(); 346 358 } … … 365 377 366 378 /* This call can preempt, but we are already at the end */ 367 rc = async_ obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,379 rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, 368 380 0, 0, cons->scr.size_x, 369 381 cons->scr.size_y); … … 393 405 curs_visibility(cons->scr.is_cursor_visible); 394 406 395 async_obsolete_serialize_end(); 396 } 397 } 398 399 /** Handler for input events */ 400 static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg) 407 async_serialize_end(); 408 } 409 } 410 411 static void close_driver_phone(ipc_callid_t hash) 412 { 413 int i; 414 for (i = 0; i < MAX_IPC_OUTGOING_PHONES; i++) { 415 if (driver_phones[i] == hash) { 416 printf("Device %" PRIxn " gone.\n", hash); 417 driver_phones[i] = 0; 418 async_hangup(i); 419 return; 420 } 421 } 422 } 423 424 /** Handler for keyboard */ 425 static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall) 401 426 { 402 427 /* Ignore parameters, the connection is already opened */ … … 406 431 407 432 int retval; 408 kbd_event_t ev; 409 410 if (!IPC_GET_IMETHOD(call)) { 433 console_event_t ev; 434 435 switch (IPC_GET_IMETHOD(call)) { 436 case IPC_M_PHONE_HUNGUP: 411 437 /* TODO: Handle hangup */ 412 async_obsolete_hangup(input_phone);438 close_driver_phone(iid); 413 439 return; 414 } 415 416 switch (IPC_GET_IMETHOD(call)) { 417 case INPUT_EVENT_KEY: 418 /* Got key press/release event */ 440 case KBD_EVENT: 441 /* Got event from keyboard driver. */ 419 442 retval = 0; 420 443 ev.type = IPC_GET_ARG1(call); … … 437 460 fibril_mutex_unlock(&input_mutex); 438 461 break; 439 case INPUT_EVENT_MOVE: 440 /* Got pointer move event */ 462 default: 463 retval = ENOENT; 464 } 465 async_answer_0(callid, retval); 466 } 467 } 468 469 /** Handler for mouse events */ 470 static void mouse_events(ipc_callid_t iid, ipc_call_t *icall) 471 { 472 /* Ignore parameters, the connection is already opened */ 473 while (true) { 474 ipc_call_t call; 475 ipc_callid_t callid = async_get_call(&call); 476 477 int retval; 478 479 switch (IPC_GET_IMETHOD(call)) { 480 case IPC_M_PHONE_HUNGUP: 481 /* TODO: Handle hangup */ 482 close_driver_phone(iid); 483 return; 484 case MEVENT_BUTTON: 485 if (IPC_GET_ARG1(call) == 1) { 486 int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call)); 487 if (newcon != -1) { 488 change_console(&consoles[newcon]); 489 } 490 } 491 retval = 0; 492 break; 493 case MEVENT_MOVE: 441 494 gcons_mouse_move((int) IPC_GET_ARG1(call), 442 495 (int) IPC_GET_ARG2(call)); 443 496 retval = 0; 444 497 break; 445 case INPUT_EVENT_BUTTON:446 /* Got pointer button press/release event */447 if (IPC_GET_ARG1(call) == 1) {448 int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));449 if (newcon != -1)450 change_console(&consoles[newcon]);451 }452 retval = 0;453 break;454 498 default: 455 499 retval = ENOENT; 456 500 } 501 457 502 async_answer_0(callid, retval); 458 503 } … … 470 515 } 471 516 472 async_ obsolete_serialize_start();517 async_serialize_start(); 473 518 474 519 size_t off = 0; … … 478 523 } 479 524 480 async_ obsolete_serialize_end();525 async_serialize_end(); 481 526 482 527 gcons_notify_char(cons->index); … … 504 549 505 550 size_t pos = 0; 506 kbd_event_t ev;551 console_event_t ev; 507 552 fibril_mutex_lock(&input_mutex); 508 553 … … 529 574 static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request) 530 575 { 531 kbd_event_t ev;576 console_event_t ev; 532 577 533 578 fibril_mutex_lock(&input_mutex); … … 545 590 546 591 /** Default thread for new connections */ 547 static void client_connection(ipc_callid_t iid, ipc_call_t *icall , void *arg)592 static void client_connection(ipc_callid_t iid, ipc_call_t *icall) 548 593 { 549 594 console_t *cons = NULL; … … 573 618 int rc; 574 619 575 async_ obsolete_serialize_start();620 async_serialize_start(); 576 621 if (cons->refcount == 0) 577 622 gcons_notify_connect(cons->index); … … 583 628 584 629 while (true) { 585 async_ obsolete_serialize_end();630 async_serialize_end(); 586 631 callid = async_get_call(&call); 587 async_ obsolete_serialize_start();632 async_serialize_start(); 588 633 589 634 arg1 = 0; … … 591 636 arg3 = 0; 592 637 593 if (!IPC_GET_IMETHOD(call)) { 638 switch (IPC_GET_IMETHOD(call)) { 639 case IPC_M_PHONE_HUNGUP: 594 640 cons->refcount--; 595 641 if (cons->refcount == 0) 596 642 gcons_notify_disconnect(cons->index); 597 643 return; 598 }599 600 switch (IPC_GET_IMETHOD(call)) {601 644 case VFS_OUT_READ: 602 async_ obsolete_serialize_end();645 async_serialize_end(); 603 646 cons_read(cons, callid, &call); 604 async_ obsolete_serialize_start();647 async_serialize_start(); 605 648 continue; 606 649 case VFS_OUT_WRITE: 607 async_ obsolete_serialize_end();650 async_serialize_end(); 608 651 cons_write(cons, callid, &call); 609 async_ obsolete_serialize_start();652 async_serialize_start(); 610 653 continue; 611 654 case VFS_OUT_SYNC: 612 655 fb_pending_flush(); 613 656 if (cons == active_console) { 614 async_ obsolete_req_0_0(fb_info.phone, FB_FLUSH);657 async_req_0_0(fb_info.phone, FB_FLUSH); 615 658 curs_goto(cons->scr.position_x, cons->scr.position_y); 616 659 } … … 619 662 /* Send message to fb */ 620 663 if (cons == active_console) 621 async_ obsolete_msg_0(fb_info.phone, FB_CLEAR);664 async_msg_0(fb_info.phone, FB_CLEAR); 622 665 623 666 screenbuffer_clear(&cons->scr); … … 678 721 break; 679 722 case CONSOLE_GET_EVENT: 680 async_ obsolete_serialize_end();723 async_serialize_end(); 681 724 cons_get_event(cons, callid, &call); 682 async_ obsolete_serialize_start();725 async_serialize_start(); 683 726 continue; 684 727 case CONSOLE_KCON_ENABLE: … … 695 738 } 696 739 697 static int connect_input(const char *dev_path) 698 { 699 int phone; 700 devmap_handle_t handle; 701 702 int rc = devmap_device_get_handle(dev_path, &handle, 0); 703 if (rc == EOK) { 704 phone = devmap_obsolete_device_connect(handle, 0); 705 if (phone < 0) { 706 printf("%s: Failed to connect to input device\n", NAME); 707 return phone; 708 } 709 } else { 740 static int async_connect_to_me_hack(int phone, sysarg_t arg1, sysarg_t arg2, 741 sysarg_t arg3, async_client_conn_t client_receiver, ipc_callid_t *hash) 742 { 743 sysarg_t task_hash; 744 sysarg_t phone_hash; 745 int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 746 NULL, NULL, NULL, &task_hash, &phone_hash); 747 if (rc != EOK) 710 748 return rc; 711 } 712 713 /* NB: The callback connection is slotted for removal */ 714 rc = async_obsolete_connect_to_me(phone, SERVICE_CONSOLE, 0, 0, 715 input_events, NULL); 716 749 750 if (client_receiver != NULL) 751 async_new_connection(task_hash, phone_hash, phone_hash, NULL, 752 client_receiver); 753 754 if (hash != NULL) { 755 *hash = phone_hash; 756 } 757 758 return EOK; 759 } 760 761 static int connect_keyboard_or_mouse(const char *devname, 762 async_client_conn_t handler, const char *path) 763 { 764 int fd = open(path, O_RDONLY); 765 if (fd < 0) { 766 return fd; 767 } 768 769 int phone = fd_phone(fd); 770 close(fd); 771 if (phone < 0) { 772 printf(NAME ": Failed to connect to input device\n"); 773 return phone; 774 } 775 776 ipc_callid_t hash; 777 int rc = async_connect_to_me_hack(phone, SERVICE_CONSOLE, 0, phone, 778 handler, &hash); 717 779 if (rc != EOK) { 718 async_obsolete_hangup(phone); 719 printf("%s: Failed to create callback from input device (%s).\n", 720 NAME, str_error(rc)); 780 async_hangup(phone); 781 printf(NAME ": " \ 782 "Failed to create callback from input device: %s.\n", 783 str_error(rc)); 721 784 return rc; 722 785 } 723 786 787 driver_phones[phone] = hash; 788 789 printf(NAME ": found %s \"%s\" (%" PRIxn ").\n", devname, path, hash); 790 724 791 return phone; 725 792 } 726 793 727 static bool console_srv_init(char *input_dev) 728 { 729 /* Connect to input server */ 730 input_phone = connect_input(input_dev); 731 if (input_phone < 0) 794 static int connect_keyboard(const char *path) 795 { 796 return connect_keyboard_or_mouse("keyboard", keyboard_events, path); 797 } 798 799 static int connect_mouse(const char *path) 800 { 801 return connect_keyboard_or_mouse("mouse", mouse_events, path); 802 } 803 804 struct hid_class_info { 805 char *classname; 806 int (*connection_func)(const char *); 807 }; 808 809 /** Periodically check for new keyboards in /dev/class/. 810 * 811 * @param arg Class name. 812 * @return This function should never exit. 813 */ 814 static int check_new_device_fibril(void *arg) 815 { 816 struct hid_class_info *dev_info = arg; 817 818 size_t index = 1; 819 820 while (true) { 821 async_usleep(HOTPLUG_WATCH_INTERVAL); 822 char *path; 823 int rc = asprintf(&path, "/dev/class/%s\\%zu", 824 dev_info->classname, index); 825 if (rc < 0) { 826 continue; 827 } 828 rc = 0; 829 rc = dev_info->connection_func(path); 830 if (rc > 0) { 831 /* We do not allow unplug. */ 832 index++; 833 } 834 835 free(path); 836 } 837 838 return EOK; 839 } 840 841 842 /** Start a fibril monitoring hot-plugged keyboards. 843 */ 844 static void check_new_devices_in_background(int (*connection_func)(const char *), 845 const char *classname) 846 { 847 struct hid_class_info *dev_info = malloc(sizeof(struct hid_class_info)); 848 if (dev_info == NULL) { 849 printf(NAME ": " \ 850 "out of memory, will not start hot-plug-watch fibril.\n"); 851 return; 852 } 853 int rc; 854 855 rc = asprintf(&dev_info->classname, "%s", classname); 856 if (rc < 0) { 857 printf(NAME ": failed to format classname: %s.\n", 858 str_error(rc)); 859 return; 860 } 861 dev_info->connection_func = connection_func; 862 863 fid_t fid = fibril_create(check_new_device_fibril, (void *)dev_info); 864 if (!fid) { 865 printf(NAME 866 ": failed to create hot-plug-watch fibril for %s.\n", 867 classname); 868 return; 869 } 870 fibril_add_ready(fid); 871 } 872 873 static bool console_init(char *input) 874 { 875 /* Connect to input device */ 876 kbd_phone = connect_keyboard(input); 877 if (kbd_phone < 0) { 732 878 return false; 879 } 880 881 mouse_phone = connect_mouse("/dev/hid_in/mouse"); 882 if (mouse_phone < 0) { 883 printf(NAME ": Failed to connect to mouse device: %s.\n", 884 str_error(mouse_phone)); 885 } 733 886 734 887 /* Connect to framebuffer driver */ 735 fb_info.phone = service_ obsolete_connect_blocking(SERVICE_VIDEO, 0, 0);888 fb_info.phone = service_connect_blocking(SERVICE_VIDEO, 0, 0); 736 889 if (fb_info.phone < 0) { 737 printf( "%s: Failed to connect to video service\n", NAME);738 return false;890 printf(NAME ": Failed to connect to video service\n"); 891 return -1; 739 892 } 740 893 … … 742 895 int rc = devmap_driver_register(NAME, client_connection); 743 896 if (rc < 0) { 744 printf( "%s: Unable to register driver (%d)\n", NAME, rc);897 printf(NAME ": Unable to register driver (%d)\n", rc); 745 898 return false; 746 899 } … … 750 903 751 904 /* Synchronize, the gcons could put something in queue */ 752 async_ obsolete_req_0_0(fb_info.phone, FB_FLUSH);753 async_ obsolete_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);754 async_ obsolete_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap);905 async_req_0_0(fb_info.phone, FB_FLUSH); 906 async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows); 907 async_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap); 755 908 756 909 /* Set up shared memory buffer. */ … … 763 916 764 917 if (interbuffer) { 765 if (async_ obsolete_share_out_start(fb_info.phone, interbuffer,918 if (async_share_out_start(fb_info.phone, interbuffer, 766 919 AS_AREA_READ) != EOK) { 767 920 as_area_destroy(interbuffer); … … 778 931 if (screenbuffer_init(&consoles[i].scr, 779 932 fb_info.cols, fb_info.rows) == NULL) { 780 printf( "%s: Unable to allocate screen buffer %zu\n", NAME, i);933 printf(NAME ": Unable to allocate screen buffer %zu\n", i); 781 934 return false; 782 935 } … … 790 943 791 944 if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) { 792 printf( "%s: Unable to register device %s\n", NAME, vc);945 printf(NAME ": Unable to register device %s\n", vc); 793 946 return false; 794 947 } … … 800 953 801 954 /* Initialize the screen */ 802 async_ obsolete_serialize_start();955 async_serialize_start(); 803 956 gcons_redraw_console(); 804 957 set_style(STYLE_NORMAL); … … 806 959 curs_goto(0, 0); 807 960 curs_visibility(active_console->scr.is_cursor_visible); 808 async_ obsolete_serialize_end();961 async_serialize_end(); 809 962 810 963 /* Receive kernel notifications */ 811 964 async_set_interrupt_received(interrupt_received); 812 965 if (event_subscribe(EVENT_KCONSOLE, 0) != EOK) 813 printf("%s: Error registering kconsole notifications\n", NAME); 814 966 printf(NAME ": Error registering kconsole notifications\n"); 967 968 /* Start fibril for checking on hot-plugged keyboards. */ 969 check_new_devices_in_background(connect_keyboard, "keyboard"); 970 check_new_devices_in_background(connect_mouse, "mouse"); 971 815 972 return true; 816 973 } … … 818 975 static void usage(void) 819 976 { 820 printf("Usage: console <input _dev>\n");977 printf("Usage: console <input>\n"); 821 978 } 822 979 … … 830 987 printf(NAME ": HelenOS Console service\n"); 831 988 832 if (!console_ srv_init(argv[1]))989 if (!console_init(argv[1])) 833 990 return -1; 834 991 835 992 printf(NAME ": Accepting connections\n"); 836 993 async_manager();
Note:
See TracChangeset
for help on using the changeset viewer.