Changeset eb522e8 in mainline for uspace/srv/hid/console/console.c
- Timestamp:
- 2011-06-01T08:43:42Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8d6c1f1
- Parents:
- 9e2e715 (diff), e51a514 (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
-
uspace/srv/hid/console/console.c (modified) (39 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/console/console.c
r9e2e715 reb522e8 34 34 35 35 #include <libc.h> 36 #include <ipc/ipc.h>37 36 #include <ipc/kbd.h> 38 37 #include <io/keycode.h> … … 40 39 #include <ipc/fb.h> 41 40 #include <ipc/services.h> 41 #include <ipc/ns.h> 42 42 #include <errno.h> 43 #include <str_error.h> 43 44 #include <ipc/console.h> 44 45 #include <unistd.h> … … 56 57 #include <io/style.h> 57 58 #include <io/screenbuffer.h> 59 #include <inttypes.h> 58 60 59 61 #include "console.h" … … 64 66 #define NAME "console" 65 67 #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 }; 66 75 67 76 /** Phone to the keyboard driver. */ … … 74 83 struct { 75 84 int phone; /**< Framebuffer phone */ 76 ipcarg_t cols; /**< Framebuffer columns */77 ipcarg_t rows; /**< Framebuffer rows */78 ipcarg_t color_cap; /**< Color capabilities (FB_CCAP_xxx) */85 sysarg_t cols; /**< Framebuffer columns */ 86 sysarg_t rows; /**< Framebuffer rows */ 87 sysarg_t color_cap; /**< Color capabilities (FB_CCAP_xxx) */ 79 88 } fb_info; 80 89 … … 82 91 size_t index; /**< Console index */ 83 92 size_t refcount; /**< Connection reference count */ 84 dev _handle_t dev_handle; /**< Device handle */93 devmap_handle_t devmap_handle; /**< Device handle */ 85 94 keybuffer_t keybuffer; /**< Buffer for incoming keys. */ 86 95 screenbuffer_t scr; /**< Screenbuffer for saving screen … … 88 97 } console_t; 89 98 99 100 90 101 /** Array of data for virtual consoles */ 91 102 static console_t consoles[CONSOLE_COUNT]; … … 101 112 /** Information on row-span yet unsent to FB driver. */ 102 113 struct { 103 ipcarg_t col; /**< Leftmost column of the span. */104 ipcarg_t row; /**< Row where the span lies. */105 ipcarg_t cnt; /**< Width of the span. */114 sysarg_t col; /**< Leftmost column of the span. */ 115 sysarg_t row; /**< Row where the span lies. */ 116 sysarg_t cnt; /**< Width of the span. */ 106 117 } fb_pending; 107 118 … … 116 127 static void curs_hide_sync(void) 117 128 { 118 ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);119 } 120 121 static void curs_goto( ipcarg_t x, ipcarg_t y)129 async_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 130 } 131 132 static void curs_goto(sysarg_t x, sysarg_t y) 122 133 { 123 134 async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y); … … 131 142 static void screen_yield(void) 132 143 { 133 ipc_call_sync_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 ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_RECLAIM);149 async_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM); 139 150 } 140 151 141 152 static void kbd_yield(void) 142 153 { 143 ipc_call_sync_0_0(kbd_phone, KBD_YIELD);154 async_req_0_0(kbd_phone, KBD_YIELD); 144 155 } 145 156 146 157 static void kbd_reclaim(void) 147 158 { 148 ipc_call_sync_0_0(kbd_phone, KBD_RECLAIM);159 async_req_0_0(kbd_phone, KBD_RECLAIM); 149 160 } 150 161 … … 180 191 } 181 192 182 static int ccap_fb_to_con( ipcarg_t ccap_fb, ipcarg_t *ccap_con)193 static int ccap_fb_to_con(sysarg_t ccap_fb, sysarg_t *ccap_con) 183 194 { 184 195 switch (ccap_fb) { … … 203 214 204 215 /** Send an area of screenbuffer to the FB driver. */ 205 static void fb_update_area(console_t *cons, ipcarg_t x0, ipcarg_t y0, ipcarg_t width, ipcarg_t height)216 static void fb_update_area(console_t *cons, sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height) 206 217 { 207 218 if (interbuffer) { 208 ipcarg_t x;209 ipcarg_t y;219 sysarg_t x; 220 sysarg_t y; 210 221 211 222 for (y = 0; y < height; y++) { … … 237 248 * 238 249 */ 239 static void cell_mark_changed( ipcarg_t col, ipcarg_t row)250 static void cell_mark_changed(sysarg_t col, sysarg_t row) 240 251 { 241 252 if (fb_pending.cnt != 0) { … … 255 266 256 267 /** Print a character to the active VC with buffering. */ 257 static void fb_putchar(wchar_t c, ipcarg_t col, ipcarg_t row)268 static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row) 258 269 { 259 270 async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row); … … 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(); … … 352 364 curs_visibility(false); 353 365 354 ipcarg_t x;355 ipcarg_t y;366 sysarg_t x; 367 sysarg_t y; 356 368 int rc = 0; 357 369 … … 397 409 } 398 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 399 424 /** Handler for keyboard */ 400 425 static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall) … … 408 433 console_event_t ev; 409 434 410 switch (IPC_GET_ METHOD(call)) {435 switch (IPC_GET_IMETHOD(call)) { 411 436 case IPC_M_PHONE_HUNGUP: 412 437 /* TODO: Handle hangup */ 438 close_driver_phone(iid); 413 439 return; 414 440 case KBD_EVENT: … … 437 463 retval = ENOENT; 438 464 } 439 ipc_answer_0(callid, retval);465 async_answer_0(callid, retval); 440 466 } 441 467 } … … 451 477 int retval; 452 478 453 switch (IPC_GET_ METHOD(call)) {479 switch (IPC_GET_IMETHOD(call)) { 454 480 case IPC_M_PHONE_HUNGUP: 455 481 /* TODO: Handle hangup */ 482 close_driver_phone(iid); 456 483 return; 457 484 case MEVENT_BUTTON: 458 485 if (IPC_GET_ARG1(call) == 1) { 459 486 int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call)); 460 if (newcon != -1) 487 if (newcon != -1) { 461 488 change_console(&consoles[newcon]); 489 } 462 490 } 463 491 retval = 0; … … 472 500 } 473 501 474 ipc_answer_0(callid, retval);502 async_answer_0(callid, retval); 475 503 } 476 504 } … … 483 511 484 512 if (rc != EOK) { 485 ipc_answer_0(rid, rc);513 async_answer_0(rid, rc); 486 514 return; 487 515 } … … 498 526 499 527 gcons_notify_char(cons->index); 500 ipc_answer_1(rid, EOK, size);528 async_answer_1(rid, EOK, size); 501 529 502 530 free(buf); … … 508 536 size_t size; 509 537 if (!async_data_read_receive(&callid, &size)) { 510 ipc_answer_0(callid, EINVAL);511 ipc_answer_0(rid, EINVAL);538 async_answer_0(callid, EINVAL); 539 async_answer_0(rid, EINVAL); 512 540 return; 513 541 } … … 515 543 char *buf = (char *) malloc(size); 516 544 if (buf == NULL) { 517 ipc_answer_0(callid, ENOMEM);518 ipc_answer_0(rid, ENOMEM);545 async_answer_0(callid, ENOMEM); 546 async_answer_0(rid, ENOMEM); 519 547 return; 520 548 } … … 534 562 if (pos == size) { 535 563 (void) async_data_read_finalize(callid, buf, size); 536 ipc_answer_1(rid, EOK, size);564 async_answer_1(rid, EOK, size); 537 565 free(buf); 538 566 } else { … … 552 580 recheck: 553 581 if (keybuffer_pop(&cons->keybuffer, &ev)) { 554 ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);582 async_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c); 555 583 } else { 556 584 fibril_condvar_wait(&input_cv, &input_mutex); … … 571 599 continue; 572 600 573 if (consoles[i].dev _handle == (dev_handle_t) IPC_GET_ARG1(*icall)) {601 if (consoles[i].devmap_handle == (devmap_handle_t) IPC_GET_ARG1(*icall)) { 574 602 cons = &consoles[i]; 575 603 break; … … 578 606 579 607 if (cons == NULL) { 580 ipc_answer_0(iid, ENOENT);608 async_answer_0(iid, ENOENT); 581 609 return; 582 610 } … … 584 612 ipc_callid_t callid; 585 613 ipc_call_t call; 586 ipcarg_t arg1;587 ipcarg_t arg2;588 ipcarg_t arg3;614 sysarg_t arg1; 615 sysarg_t arg2; 616 sysarg_t arg3; 589 617 590 618 int rc; … … 597 625 598 626 /* Accept the connection */ 599 ipc_answer_0(iid, EOK);627 async_answer_0(iid, EOK); 600 628 601 629 while (true) { … … 608 636 arg3 = 0; 609 637 610 switch (IPC_GET_ METHOD(call)) {638 switch (IPC_GET_IMETHOD(call)) { 611 639 case IPC_M_PHONE_HUNGUP: 612 640 cons->refcount--; … … 657 685 rc = ccap_fb_to_con(fb_info.color_cap, &arg1); 658 686 if (rc != EOK) { 659 ipc_answer_0(callid, rc);687 async_answer_0(callid, rc); 660 688 continue; 661 689 } … … 701 729 break; 702 730 } 703 ipc_answer_3(callid, EOK, arg1, arg2, arg3);731 async_answer_3(callid, EOK, arg1, arg2, arg3); 704 732 } 705 733 } … … 710 738 } 711 739 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) 748 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); 779 if (rc != EOK) { 780 async_hangup(phone); 781 printf(NAME ": " \ 782 "Failed to create callback from input device: %s.\n", 783 str_error(rc)); 784 return rc; 785 } 786 787 driver_phones[phone] = hash; 788 789 printf(NAME ": found %s \"%s\" (%" PRIxn ").\n", devname, path, hash); 790 791 return phone; 792 } 793 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 712 873 static bool console_init(char *input) 713 874 { 714 875 /* Connect to input device */ 715 int input_fd = open(input, O_RDONLY); 716 if (input_fd < 0) { 717 printf(NAME ": Failed opening %s\n", input); 876 kbd_phone = connect_keyboard(input); 877 if (kbd_phone < 0) { 718 878 return false; 719 879 } 720 721 kbd_phone = fd_phone(input_fd); 722 if (kbd_phone < 0) { 723 printf(NAME ": Failed to connect to input device\n"); 724 return false; 725 } 726 727 /* NB: The callback connection is slotted for removal */ 728 ipcarg_t phonehash; 729 if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) { 730 printf(NAME ": Failed to create callback from input device\n"); 731 return false; 732 } 733 734 async_new_connection(phonehash, 0, NULL, keyboard_events); 735 736 /* Connect to mouse device */ 737 mouse_phone = -1; 738 int mouse_fd = open("/dev/hid_in/mouse", O_RDONLY); 739 740 if (mouse_fd < 0) { 741 printf(NAME ": Notice - failed opening %s\n", "/dev/hid_in/mouse"); 742 goto skip_mouse; 743 } 744 745 mouse_phone = fd_phone(mouse_fd); 880 881 mouse_phone = connect_mouse("/dev/hid_in/mouse"); 746 882 if (mouse_phone < 0) { 747 printf(NAME ": Failed to connect to mouse device\n"); 748 goto skip_mouse; 749 } 750 751 if (ipc_connect_to_me(mouse_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) { 752 printf(NAME ": Failed to create callback from mouse device\n"); 753 mouse_phone = -1; 754 goto skip_mouse; 755 } 756 757 async_new_connection(phonehash, 0, NULL, mouse_events); 758 skip_mouse: 883 printf(NAME ": Failed to connect to mouse device: %s.\n", 884 str_error(mouse_phone)); 885 } 759 886 760 887 /* Connect to framebuffer driver */ 761 fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS,SERVICE_VIDEO, 0, 0);888 fb_info.phone = service_connect_blocking(SERVICE_VIDEO, 0, 0); 762 889 if (fb_info.phone < 0) { 763 890 printf(NAME ": Failed to connect to video service\n"); … … 804 931 if (screenbuffer_init(&consoles[i].scr, 805 932 fb_info.cols, fb_info.rows) == NULL) { 806 printf(NAME ": Unable to allocate screen buffer % u\n", i);933 printf(NAME ": Unable to allocate screen buffer %zu\n", i); 807 934 return false; 808 935 } … … 813 940 814 941 char vc[DEVMAP_NAME_MAXLEN + 1]; 815 snprintf(vc, DEVMAP_NAME_MAXLEN, "%s/vc% u", NAMESPACE, i);942 snprintf(vc, DEVMAP_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i); 816 943 817 if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) { 818 devmap_hangup_phone(DEVMAP_DRIVER); 944 if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) { 819 945 printf(NAME ": Unable to register device %s\n", vc); 820 946 return false; … … 836 962 837 963 /* Receive kernel notifications */ 964 async_set_interrupt_received(interrupt_received); 838 965 if (event_subscribe(EVENT_KCONSOLE, 0) != EOK) 839 966 printf(NAME ": Error registering kconsole notifications\n"); 840 967 841 async_set_interrupt_received(interrupt_received); 842 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 843 972 return true; 844 973 } … … 860 989 if (!console_init(argv[1])) 861 990 return -1; 862 991 863 992 printf(NAME ": Accepting connections\n"); 864 993 async_manager();
Note:
See TracChangeset
for help on using the changeset viewer.
