Changeset 8ff0bd2 in mainline for uspace/srv/hid/console/console.c
- Timestamp:
- 2011-09-04T11:30:58Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 03bc76a
- Parents:
- d2c67e7 (diff), deac215e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/console/console.c
rd2c67e7 r8ff0bd2 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> … … 53 53 #include <sysinfo.h> 54 54 #include <event.h> 55 #include <devmap.h> 56 #include <devmap_obsolete.h> 55 #include <loc.h> 57 56 #include <fcntl.h> 58 57 #include <vfs/vfs.h> … … 60 59 #include <io/style.h> 61 60 #include <io/screenbuffer.h> 62 #include <inttypes.h>63 61 64 62 #include "console.h" … … 66 64 #include "keybuffer.h" 67 65 68 // FIXME: remove this header69 #include <kernel/ipc/ipc_methods.h>70 71 66 #define NAME "console" 72 67 #define NAMESPACE "term" 73 68 74 /** Interval for checking for new keyboard (1/4s). */ 75 #define HOTPLUG_WATCH_INTERVAL (1000 * 250) 76 77 /* Kernel defines 32 but does not export it. */ 78 #define MAX_IPC_OUTGOING_PHONES 128 79 80 /** To allow proper phone closing. */ 81 static ipc_callid_t driver_phones[MAX_IPC_OUTGOING_PHONES] = { 0 }; 82 83 /** Phone to the keyboard driver. */ 84 static int kbd_phone; 85 86 /** Phone to the mouse driver. */ 87 static int mouse_phone; 69 /** Session with the input server. */ 70 static async_sess_t *input_sess; 88 71 89 72 /** Information about framebuffer */ … … 98 81 size_t index; /**< Console index */ 99 82 size_t refcount; /**< Connection reference count */ 100 devmap_handle_t devmap_handle; /**< Device handle*/83 service_id_t service_id; /**< Service ID */ 101 84 keybuffer_t keybuffer; /**< Buffer for incoming keys. */ 102 85 screenbuffer_t scr; /**< Screenbuffer for saving screen … … 125 108 static FIBRIL_CONDVAR_INITIALIZE(input_cv); 126 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 127 122 static void curs_visibility(bool visible) 128 123 { … … 155 150 } 156 151 157 static void kbd_yield(void) 158 { 159 async_obsolete_req_0_0(kbd_phone, KBD_YIELD); 160 } 161 162 static void kbd_reclaim(void) 163 { 164 async_obsolete_req_0_0(kbd_phone, KBD_RECLAIM); 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); 158 return; 159 } 160 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); 165 176 } 166 177 … … 339 350 340 351 if (cons == kernel_console) { 341 async_obsolete_serialize_start();352 console_serialize_start(); 342 353 curs_hide_sync(); 343 354 gcons_in_kernel(); 344 355 screen_yield(); 345 kbd_yield();346 async_obsolete_serialize_end();347 348 if ( __SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {356 input_yield(); 357 console_serialize_end(); 358 359 if (console_kcon()) { 349 360 prev_console = active_console; 350 361 active_console = kernel_console; … … 354 365 355 366 if (cons != kernel_console) { 356 async_obsolete_serialize_start();367 console_serialize_start(); 357 368 358 369 if (active_console == kernel_console) { 359 370 screen_reclaim(); 360 kbd_reclaim();371 input_reclaim(); 361 372 gcons_redraw_console(); 362 373 } … … 409 420 curs_visibility(cons->scr.is_cursor_visible); 410 421 411 async_obsolete_serialize_end(); 412 } 413 } 414 415 static void close_driver_phone(ipc_callid_t hash) 416 { 417 int i; 418 for (i = 0; i < MAX_IPC_OUTGOING_PHONES; i++) { 419 if (driver_phones[i] == hash) { 420 printf("Device %" PRIxn " gone.\n", hash); 421 driver_phones[i] = 0; 422 async_obsolete_hangup(i); 423 return; 424 } 425 } 426 } 427 428 /** Handler for keyboard */ 429 static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall) 422 console_serialize_end(); 423 } 424 } 425 426 /** Handler for input events */ 427 static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg) 430 428 { 431 429 /* Ignore parameters, the connection is already opened */ … … 439 437 if (!IPC_GET_IMETHOD(call)) { 440 438 /* TODO: Handle hangup */ 441 close_driver_phone(iid);439 async_hangup(input_sess); 442 440 return; 443 441 } 444 442 445 443 switch (IPC_GET_IMETHOD(call)) { 446 case KBD_EVENT:447 /* Got event from keyboard driver.*/444 case INPUT_EVENT_KEY: 445 /* Got key press/release event */ 448 446 retval = 0; 449 447 ev.type = IPC_GET_ARG1(call); … … 466 464 fibril_mutex_unlock(&input_mutex); 467 465 break; 468 default: 469 retval = ENOENT; 470 } 471 async_answer_0(callid, retval); 472 } 473 } 474 475 /** Handler for mouse events */ 476 static void mouse_events(ipc_callid_t iid, ipc_call_t *icall) 477 { 478 /* Ignore parameters, the connection is already opened */ 479 while (true) { 480 ipc_call_t call; 481 ipc_callid_t callid = async_get_call(&call); 482 483 int retval; 484 485 if (!IPC_GET_IMETHOD(call)) { 486 /* TODO: Handle hangup */ 487 close_driver_phone(iid); 488 return; 489 } 490 491 switch (IPC_GET_IMETHOD(call)) { 492 case MEVENT_BUTTON: 466 case INPUT_EVENT_MOVE: 467 /* Got pointer move event */ 468 gcons_mouse_move((int) IPC_GET_ARG1(call), 469 (int) IPC_GET_ARG2(call)); 470 retval = 0; 471 break; 472 case INPUT_EVENT_BUTTON: 473 /* Got pointer button press/release event */ 493 474 if (IPC_GET_ARG1(call) == 1) { 494 475 int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call)); … … 498 479 retval = 0; 499 480 break; 500 case MEVENT_MOVE:501 gcons_mouse_move((int) IPC_GET_ARG1(call),502 (int) IPC_GET_ARG2(call));503 retval = 0;504 break;505 481 default: 506 482 retval = ENOENT; … … 522 498 } 523 499 524 async_obsolete_serialize_start();500 console_serialize_start(); 525 501 526 502 size_t off = 0; … … 530 506 } 531 507 532 async_obsolete_serialize_end();508 console_serialize_end(); 533 509 534 510 gcons_notify_char(cons->index); … … 597 573 598 574 /** Default thread for new connections */ 599 static void client_connection(ipc_callid_t iid, ipc_call_t *icall )575 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 600 576 { 601 577 console_t *cons = NULL; … … 606 582 continue; 607 583 608 if (consoles[i]. devmap_handle == (devmap_handle_t) IPC_GET_ARG1(*icall)) {584 if (consoles[i].service_id == (service_id_t) IPC_GET_ARG1(*icall)) { 609 585 cons = &consoles[i]; 610 586 break; … … 625 601 int rc; 626 602 627 async_obsolete_serialize_start();603 console_serialize_start(); 628 604 if (cons->refcount == 0) 629 605 gcons_notify_connect(cons->index); … … 635 611 636 612 while (true) { 637 async_obsolete_serialize_end();613 console_serialize_end(); 638 614 callid = async_get_call(&call); 639 async_obsolete_serialize_start();615 console_serialize_start(); 640 616 641 617 arg1 = 0; … … 647 623 if (cons->refcount == 0) 648 624 gcons_notify_disconnect(cons->index); 625 console_serialize_end(); 649 626 return; 650 627 } … … 652 629 switch (IPC_GET_IMETHOD(call)) { 653 630 case VFS_OUT_READ: 654 async_obsolete_serialize_end();631 console_serialize_end(); 655 632 cons_read(cons, callid, &call); 656 async_obsolete_serialize_start();633 console_serialize_start(); 657 634 continue; 658 635 case VFS_OUT_WRITE: 659 async_obsolete_serialize_end();636 console_serialize_end(); 660 637 cons_write(cons, callid, &call); 661 async_obsolete_serialize_start();638 console_serialize_start(); 662 639 continue; 663 640 case VFS_OUT_SYNC: … … 730 707 break; 731 708 case CONSOLE_GET_EVENT: 732 async_obsolete_serialize_end();709 console_serialize_end(); 733 710 cons_get_event(cons, callid, &call); 734 async_obsolete_serialize_start();711 console_serialize_start(); 735 712 continue; 736 case CONSOLE_KCON_ENABLE:737 change_console(kernel_console);738 break;739 713 } 740 714 async_answer_3(callid, EOK, arg1, arg2, arg3); … … 747 721 } 748 722 749 static int async_connect_to_me_hack(int phone, sysarg_t arg1, sysarg_t arg2, 750 sysarg_t arg3, async_client_conn_t client_receiver, ipc_callid_t *hash) 751 { 752 sysarg_t task_hash; 753 sysarg_t phone_hash; 754 int rc = async_obsolete_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 755 NULL, NULL, NULL, &task_hash, &phone_hash); 756 if (rc != EOK) 757 return rc; 758 759 if (client_receiver != NULL) 760 async_new_connection(task_hash, phone_hash, phone_hash, NULL, 761 client_receiver); 762 763 if (hash != NULL) 764 *hash = phone_hash; 765 766 return EOK; 767 } 768 769 static int connect_keyboard_or_mouse(const char *devname, 770 async_client_conn_t handler, const char *dev) 771 { 772 int phone; 773 devmap_handle_t handle; 774 775 int rc = devmap_device_get_handle(dev, &handle, 0); 723 static async_sess_t *connect_input(const char *svc_path) 724 { 725 async_sess_t *sess; 726 async_exch_t *exch; 727 service_id_t service_id; 728 729 int rc = loc_service_get_id(svc_path, &service_id, 0); 776 730 if (rc == EOK) { 777 phone = devmap_obsolete_device_connect(handle, 0); 778 if (phone < 0) { 779 printf("%s: Failed to connect to input device\n", NAME); 780 return phone; 781 } 782 } else 783 return rc; 731 sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0); 732 if (sess == NULL) { 733 printf("%s: Failed to connect to input server\n", NAME); 734 return NULL; 735 } 736 } else { 737 return NULL; 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 } 784 745 785 746 /* NB: The callback connection is slotted for removal */ 786 ipc_callid_t hash; 787 rc = async_connect_to_me_hack(phone, SERVICE_CONSOLE, 0, phone, 788 handler, &hash); 747 rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL); 748 749 async_exchange_end(exch); 750 789 751 if (rc != EOK) { 790 async_ obsolete_hangup(phone);791 printf("%s: Failed to create callback from input device(%s).\n",752 async_hangup(sess); 753 printf("%s: Failed to create callback from input server (%s).\n", 792 754 NAME, str_error(rc)); 793 return rc; 794 } 795 796 driver_phones[phone] = hash; 797 printf("%s: found %s \"%s\" (%" PRIxn ").\n", NAME, devname, dev, hash); 798 return phone; 799 } 800 801 static int connect_keyboard(const char *dev) 802 { 803 return connect_keyboard_or_mouse("keyboard", keyboard_events, dev); 804 } 805 806 static int connect_mouse(const char *dev) 807 { 808 return connect_keyboard_or_mouse("mouse", mouse_events, dev); 809 } 810 811 struct hid_class_info { 812 char *classname; 813 int (*connection_func)(const char *); 814 }; 815 816 /** Periodically check for new keyboards in /dev/class/. 817 * 818 * @param arg Class name. 819 * 820 * @return This function should never exit. 821 * 822 */ 823 static int check_new_device_fibril(void *arg) 824 { 825 struct hid_class_info *dev_info = (struct hid_class_info *) arg; 826 827 size_t index = 1; 828 829 while (true) { 830 async_usleep(HOTPLUG_WATCH_INTERVAL); 831 832 char *dev; 833 int rc = asprintf(&dev, "class/%s\\%zu", 834 dev_info->classname, index); 835 if (rc < 0) 836 continue; 837 838 rc = dev_info->connection_func(dev); 839 if (rc > 0) { 840 /* We do not allow unplug. */ 841 index++; 842 } 843 844 free(dev); 845 } 846 847 return EOK; 848 } 849 850 /** Start a fibril monitoring hot-plugged keyboards. 851 */ 852 static void check_new_devices_in_background(int (*connection_func)(const char *), 853 const char *classname) 854 { 855 struct hid_class_info *dev_info = malloc(sizeof(struct hid_class_info)); 856 if (dev_info == NULL) { 857 printf("%s: Out of memory, no hot-plug support.\n", NAME); 858 return; 859 } 860 861 int rc = asprintf(&dev_info->classname, "%s", classname); 862 if (rc < 0) { 863 printf("%s: Failed to format classname: %s.\n", NAME, 864 str_error(rc)); 865 return; 866 } 867 868 dev_info->connection_func = connection_func; 869 870 fid_t fid = fibril_create(check_new_device_fibril, (void *) dev_info); 871 if (!fid) { 872 printf("%s: Failed to create hot-plug fibril for %s.\n", NAME, 873 classname); 874 return; 875 } 876 877 fibril_add_ready(fid); 878 } 879 880 static bool console_srv_init(char *kdev) 881 { 882 /* Connect to input device */ 883 kbd_phone = connect_keyboard(kdev); 884 if (kbd_phone < 0) 755 return NULL; 756 } 757 758 return sess; 759 } 760 761 static bool console_srv_init(char *input_dev) 762 { 763 /* Connect to input server */ 764 input_sess = connect_input(input_dev); 765 if (input_sess == NULL) 885 766 return false; 886 887 mouse_phone = connect_mouse("hid_in/mouse");888 if (mouse_phone < 0) {889 printf("%s: Failed to connect to mouse device %s\n", NAME,890 str_error(mouse_phone));891 }892 767 893 768 /* Connect to framebuffer driver */ … … 898 773 } 899 774 900 /* Register driver */901 int rc = devmap_driver_register(NAME, client_connection);775 /* Register server */ 776 int rc = loc_server_register(NAME, client_connection); 902 777 if (rc < 0) { 903 printf("%s: Unable to register driver (%d)\n", NAME, rc);778 printf("%s: Unable to register server (%d)\n", NAME, rc); 904 779 return false; 905 780 } … … 945 820 consoles[i].refcount = 0; 946 821 947 char vc[ DEVMAP_NAME_MAXLEN + 1];948 snprintf(vc, DEVMAP_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);822 char vc[LOC_NAME_MAXLEN + 1]; 823 snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i); 949 824 950 if ( devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) {951 printf("%s: Unable to register device %s\n", NAME, vc);825 if (loc_service_register(vc, &consoles[i].service_id) != EOK) { 826 printf("%s: Unable to register service %s\n", NAME, vc); 952 827 return false; 953 828 } … … 955 830 } 956 831 957 /* Disable kernel output to the console */958 __SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);959 960 832 /* Initialize the screen */ 961 async_obsolete_serialize_start();833 console_serialize_start(); 962 834 gcons_redraw_console(); 963 835 set_style(STYLE_NORMAL); … … 965 837 curs_goto(0, 0); 966 838 curs_visibility(active_console->scr.is_cursor_visible); 967 async_obsolete_serialize_end();839 console_serialize_end(); 968 840 969 841 /* Receive kernel notifications */ … … 972 844 printf("%s: Error registering kconsole notifications\n", NAME); 973 845 974 /* Start fibril for checking on hot-plugged keyboards. */975 check_new_devices_in_background(connect_keyboard, "keyboard");976 check_new_devices_in_background(connect_mouse, "mouse");977 978 846 return true; 979 847 } … … 981 849 static void usage(void) 982 850 { 983 printf("Usage: console <input >\n");851 printf("Usage: console <input_dev>\n"); 984 852 } 985 853
Note:
See TracChangeset
for help on using the changeset viewer.