Changes in uspace/srv/hid/console/console.c [8c74d15:854eddd6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/console/console.c
r8c74d15 r854eddd6 1 1 /* 2 2 * Copyright (c) 2006 Josef Cejka 3 * Copyright (c) 2011 Jiri Svoboda 3 4 * All rights reserved. 4 5 * … … 34 35 35 36 #include <libc.h> 36 #include <ipc/ kbd.h>37 #include <ipc/input.h> 37 38 #include <io/keycode.h> 38 #include <ipc/mouse.h>39 39 #include <ipc/fb.h> 40 40 #include <ipc/services.h> 41 #include <ipc/ns.h> 41 #include <ns.h> 42 #include <ns_obsolete.h> 42 43 #include <errno.h> 43 44 #include <str_error.h> … … 45 46 #include <unistd.h> 46 47 #include <async.h> 48 #include <async_obsolete.h> 47 49 #include <adt/fifo.h> 48 50 #include <sys/mman.h> … … 52 54 #include <event.h> 53 55 #include <devmap.h> 56 #include <devmap_obsolete.h> 54 57 #include <fcntl.h> 55 58 #include <vfs/vfs.h> … … 57 60 #include <io/style.h> 58 61 #include <io/screenbuffer.h> 59 #include <inttypes.h>60 62 61 63 #include "console.h" … … 63 65 #include "keybuffer.h" 64 66 65 66 67 #define NAME "console" 67 68 #define NAMESPACE "term" 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; 69 70 /** Phone to the input server. */ 71 static int input_phone; 81 72 82 73 /** Information about framebuffer */ … … 97 88 } console_t; 98 89 99 100 101 90 /** Array of data for virtual consoles */ 102 91 static console_t consoles[CONSOLE_COUNT]; … … 122 111 static void curs_visibility(bool visible) 123 112 { 124 async_ msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);113 async_obsolete_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); 125 114 } 126 115 127 116 static void curs_hide_sync(void) 128 117 { 129 async_ req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);118 async_obsolete_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 130 119 } 131 120 132 121 static void curs_goto(sysarg_t x, sysarg_t y) 133 122 { 134 async_ msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);123 async_obsolete_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y); 135 124 } 136 125 137 126 static void screen_clear(void) 138 127 { 139 async_ msg_0(fb_info.phone, FB_CLEAR);128 async_obsolete_msg_0(fb_info.phone, FB_CLEAR); 140 129 } 141 130 142 131 static void screen_yield(void) 143 132 { 144 async_ req_0_0(fb_info.phone, FB_SCREEN_YIELD);133 async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_YIELD); 145 134 } 146 135 147 136 static void screen_reclaim(void) 148 137 { 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);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); 160 149 } 161 150 162 151 static void set_style(uint8_t style) 163 152 { 164 async_ msg_1(fb_info.phone, FB_SET_STYLE, style);153 async_obsolete_msg_1(fb_info.phone, FB_SET_STYLE, style); 165 154 } 166 155 167 156 static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags) 168 157 { 169 async_ msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);158 async_obsolete_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags); 170 159 } 171 160 172 161 static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor) 173 162 { 174 async_ msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);163 async_obsolete_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 175 164 } 176 165 … … 227 216 } 228 217 229 async_ req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,218 async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, 230 219 x0, y0, width, height); 231 220 } … … 268 257 static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row) 269 258 { 270 async_ msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);259 async_obsolete_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row); 271 260 } 272 261 … … 317 306 318 307 if (cons == active_console) 319 async_ msg_1(fb_info.phone, FB_SCROLL, 1);308 async_obsolete_msg_1(fb_info.phone, FB_SCROLL, 1); 320 309 } 321 310 … … 328 317 static void change_console(console_t *cons) 329 318 { 330 if (cons == active_console) {319 if (cons == active_console) 331 320 return; 332 }333 321 334 322 fb_pending_flush(); 335 323 336 324 if (cons == kernel_console) { 337 async_ serialize_start();325 async_obsolete_serialize_start(); 338 326 curs_hide_sync(); 339 327 gcons_in_kernel(); 340 328 screen_yield(); 341 kbd_yield();342 async_ serialize_end();329 input_yield(); 330 async_obsolete_serialize_end(); 343 331 344 332 if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) { … … 350 338 351 339 if (cons != kernel_console) { 352 async_ serialize_start();340 async_obsolete_serialize_start(); 353 341 354 342 if (active_console == kernel_console) { 355 343 screen_reclaim(); 356 kbd_reclaim();344 input_reclaim(); 357 345 gcons_redraw_console(); 358 346 } … … 377 365 378 366 /* This call can preempt, but we are already at the end */ 379 rc = async_ req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,367 rc = async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, 380 368 0, 0, cons->scr.size_x, 381 369 cons->scr.size_y); … … 405 393 curs_visibility(cons->scr.is_cursor_visible); 406 394 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) 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) 426 401 { 427 402 /* Ignore parameters, the connection is already opened */ … … 431 406 432 407 int retval; 433 console_event_t ev; 408 kbd_event_t ev; 409 410 if (!IPC_GET_IMETHOD(call)) { 411 /* TODO: Handle hangup */ 412 async_obsolete_hangup(input_phone); 413 return; 414 } 434 415 435 416 switch (IPC_GET_IMETHOD(call)) { 436 case IPC_M_PHONE_HUNGUP: 437 /* TODO: Handle hangup */ 438 close_driver_phone(iid); 439 return; 440 case KBD_EVENT: 441 /* Got event from keyboard driver. */ 417 case INPUT_EVENT_KEY: 418 /* Got key press/release event */ 442 419 retval = 0; 443 420 ev.type = IPC_GET_ARG1(call); … … 460 437 fibril_mutex_unlock(&input_mutex); 461 438 break; 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: 439 case INPUT_EVENT_MOVE: 440 /* Got pointer move event */ 494 441 gcons_mouse_move((int) IPC_GET_ARG1(call), 495 442 (int) IPC_GET_ARG2(call)); 496 443 retval = 0; 497 444 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; 498 454 default: 499 455 retval = ENOENT; 500 456 } 501 502 457 async_answer_0(callid, retval); 503 458 } … … 515 470 } 516 471 517 async_ serialize_start();472 async_obsolete_serialize_start(); 518 473 519 474 size_t off = 0; … … 523 478 } 524 479 525 async_ serialize_end();480 async_obsolete_serialize_end(); 526 481 527 482 gcons_notify_char(cons->index); … … 549 504 550 505 size_t pos = 0; 551 console_event_t ev;506 kbd_event_t ev; 552 507 fibril_mutex_lock(&input_mutex); 553 508 … … 574 529 static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request) 575 530 { 576 console_event_t ev;531 kbd_event_t ev; 577 532 578 533 fibril_mutex_lock(&input_mutex); … … 590 545 591 546 /** Default thread for new connections */ 592 static void client_connection(ipc_callid_t iid, ipc_call_t *icall )547 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 593 548 { 594 549 console_t *cons = NULL; … … 618 573 int rc; 619 574 620 async_ serialize_start();575 async_obsolete_serialize_start(); 621 576 if (cons->refcount == 0) 622 577 gcons_notify_connect(cons->index); … … 628 583 629 584 while (true) { 630 async_ serialize_end();585 async_obsolete_serialize_end(); 631 586 callid = async_get_call(&call); 632 async_ serialize_start();587 async_obsolete_serialize_start(); 633 588 634 589 arg1 = 0; … … 636 591 arg3 = 0; 637 592 638 switch (IPC_GET_IMETHOD(call)) { 639 case IPC_M_PHONE_HUNGUP: 593 if (!IPC_GET_IMETHOD(call)) { 640 594 cons->refcount--; 641 595 if (cons->refcount == 0) 642 596 gcons_notify_disconnect(cons->index); 643 597 return; 598 } 599 600 switch (IPC_GET_IMETHOD(call)) { 644 601 case VFS_OUT_READ: 645 async_ serialize_end();602 async_obsolete_serialize_end(); 646 603 cons_read(cons, callid, &call); 647 async_ serialize_start();604 async_obsolete_serialize_start(); 648 605 continue; 649 606 case VFS_OUT_WRITE: 650 async_ serialize_end();607 async_obsolete_serialize_end(); 651 608 cons_write(cons, callid, &call); 652 async_ serialize_start();609 async_obsolete_serialize_start(); 653 610 continue; 654 611 case VFS_OUT_SYNC: 655 612 fb_pending_flush(); 656 613 if (cons == active_console) { 657 async_ req_0_0(fb_info.phone, FB_FLUSH);614 async_obsolete_req_0_0(fb_info.phone, FB_FLUSH); 658 615 curs_goto(cons->scr.position_x, cons->scr.position_y); 659 616 } … … 662 619 /* Send message to fb */ 663 620 if (cons == active_console) 664 async_ msg_0(fb_info.phone, FB_CLEAR);621 async_obsolete_msg_0(fb_info.phone, FB_CLEAR); 665 622 666 623 screenbuffer_clear(&cons->scr); … … 721 678 break; 722 679 case CONSOLE_GET_EVENT: 723 async_ serialize_end();680 async_obsolete_serialize_end(); 724 681 cons_get_event(cons, callid, &call); 725 async_ serialize_start();682 async_obsolete_serialize_start(); 726 683 continue; 727 684 case CONSOLE_KCON_ENABLE: … … 738 695 } 739 696 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) 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 { 748 710 return rc; 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); 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 779 717 if (rc != EOK) { 780 async_hangup(phone); 781 printf(NAME ": " \ 782 "Failed to create callback from input device: %s.\n", 783 str_error(rc)); 718 async_obsolete_hangup(phone); 719 printf("%s: Failed to create callback from input device (%s).\n", 720 NAME, str_error(rc)); 784 721 return rc; 785 722 } 786 723 787 driver_phones[phone] = hash;788 789 printf(NAME ": found %s \"%s\" (%" PRIxn ").\n", devname, path, hash);790 791 724 return phone; 792 725 } 793 726 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) { 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) 878 732 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 }886 733 887 734 /* Connect to framebuffer driver */ 888 fb_info.phone = service_ connect_blocking(SERVICE_VIDEO, 0, 0);735 fb_info.phone = service_obsolete_connect_blocking(SERVICE_VIDEO, 0, 0); 889 736 if (fb_info.phone < 0) { 890 printf( NAME ": Failed to connect to video service\n");891 return -1;737 printf("%s: Failed to connect to video service\n", NAME); 738 return false; 892 739 } 893 740 … … 895 742 int rc = devmap_driver_register(NAME, client_connection); 896 743 if (rc < 0) { 897 printf( NAME ": Unable to register driver (%d)\n", rc);744 printf("%s: Unable to register driver (%d)\n", NAME, rc); 898 745 return false; 899 746 } … … 903 750 904 751 /* Synchronize, the gcons could put something in queue */ 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);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); 908 755 909 756 /* Set up shared memory buffer. */ … … 916 763 917 764 if (interbuffer) { 918 if (async_ share_out_start(fb_info.phone, interbuffer,765 if (async_obsolete_share_out_start(fb_info.phone, interbuffer, 919 766 AS_AREA_READ) != EOK) { 920 767 as_area_destroy(interbuffer); … … 931 778 if (screenbuffer_init(&consoles[i].scr, 932 779 fb_info.cols, fb_info.rows) == NULL) { 933 printf( NAME ": Unable to allocate screen buffer %zu\n", i);780 printf("%s: Unable to allocate screen buffer %zu\n", NAME, i); 934 781 return false; 935 782 } … … 943 790 944 791 if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) { 945 printf( NAME ": Unable to register device %s\n", vc);792 printf("%s: Unable to register device %s\n", NAME, vc); 946 793 return false; 947 794 } … … 953 800 954 801 /* Initialize the screen */ 955 async_ serialize_start();802 async_obsolete_serialize_start(); 956 803 gcons_redraw_console(); 957 804 set_style(STYLE_NORMAL); … … 959 806 curs_goto(0, 0); 960 807 curs_visibility(active_console->scr.is_cursor_visible); 961 async_ serialize_end();808 async_obsolete_serialize_end(); 962 809 963 810 /* Receive kernel notifications */ 964 811 async_set_interrupt_received(interrupt_received); 965 812 if (event_subscribe(EVENT_KCONSOLE, 0) != EOK) 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 813 printf("%s: Error registering kconsole notifications\n", NAME); 814 972 815 return true; 973 816 } … … 975 818 static void usage(void) 976 819 { 977 printf("Usage: console <input >\n");820 printf("Usage: console <input_dev>\n"); 978 821 } 979 822 … … 987 830 printf(NAME ": HelenOS Console service\n"); 988 831 989 if (!console_ init(argv[1]))832 if (!console_srv_init(argv[1])) 990 833 return -1; 991 834 992 835 printf(NAME ": Accepting connections\n"); 993 836 async_manager();
Note:
See TracChangeset
for help on using the changeset viewer.