Changes in uspace/srv/hid/input/input.c [c928bb7:73d8600] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/input/input.c
rc928bb7 r73d8600 42 42 #include <ipc/services.h> 43 43 #include <ipc/input.h> 44 #include < sysinfo.h>44 #include <config.h> 45 45 #include <stdio.h> 46 46 #include <unistd.h> 47 47 #include <stdlib.h> 48 #include <stdio.h>49 48 #include <ns.h> 50 49 #include <async.h> … … 54 53 #include <io/keycode.h> 55 54 #include <loc.h> 55 #include <str_error.h> 56 #include <char_dev_iface.h> 57 #include <fibril.h> 56 58 #include "layout.h" 57 59 #include "kbd.h" … … 60 62 #include "mouse.h" 61 63 #include "mouse_proto.h" 64 #include "serial.h" 62 65 #include "input.h" 63 66 … … 71 74 }; 72 75 73 static void kbd_devs_yield(void); 74 static void kbd_devs_reclaim(void); 75 76 async_sess_t *client_sess = NULL; 76 typedef struct { 77 /** Link into the list of clients */ 78 link_t link; 79 80 /** Indicate whether the client is active */ 81 bool active; 82 83 /** Client callback session */ 84 async_sess_t *sess; 85 } client_t; 86 87 /** List of clients */ 88 static list_t clients; 89 static client_t *active_client = NULL; 90 91 /** Kernel override */ 92 static bool active = true; 93 94 /** Serial console specified by the user */ 95 static char *serial_console; 77 96 78 97 /** List of keyboard devices */ … … 82 101 static list_t mouse_devs; 83 102 84 bool irc_service = false; 85 async_sess_t *irc_sess = NULL;103 /** List of serial devices */ 104 static list_t serial_devs; 86 105 87 106 static FIBRIL_MUTEX_INITIALIZE(discovery_lock); 107 108 static void *client_data_create(void) 109 { 110 client_t *client = (client_t *) calloc(1, sizeof(client_t)); 111 if (client == NULL) 112 return NULL; 113 114 link_initialize(&client->link); 115 client->active = false; 116 client->sess = NULL; 117 118 list_append(&client->link, &clients); 119 120 return client; 121 } 122 123 static void client_data_destroy(void *data) 124 { 125 client_t *client = (client_t *) data; 126 127 list_remove(&client->link); 128 free(client); 129 } 88 130 89 131 void kbd_push_data(kbd_dev_t *kdev, sysarg_t data) … … 103 145 104 146 switch (key) { 105 case KC_LCTRL: mod_mask = KM_LCTRL; break; 106 case KC_RCTRL: mod_mask = KM_RCTRL; break; 107 case KC_LSHIFT: mod_mask = KM_LSHIFT; break; 108 case KC_RSHIFT: mod_mask = KM_RSHIFT; break; 109 case KC_LALT: mod_mask = KM_LALT; break; 110 case KC_RALT: mod_mask = KM_RALT; break; 111 default: mod_mask = 0; break; 147 case KC_LCTRL: 148 mod_mask = KM_LCTRL; 149 break; 150 case KC_RCTRL: 151 mod_mask = KM_RCTRL; 152 break; 153 case KC_LSHIFT: 154 mod_mask = KM_LSHIFT; 155 break; 156 case KC_RSHIFT: 157 mod_mask = KM_RSHIFT; 158 break; 159 case KC_LALT: 160 mod_mask = KM_LALT; 161 break; 162 case KC_RALT: 163 mod_mask = KM_RALT; 164 break; 165 default: 166 mod_mask = 0; 112 167 } 113 168 … … 120 175 121 176 switch (key) { 122 case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break; 123 case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break; 124 case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break; 125 default: mod_mask = 0; break; 177 case KC_CAPS_LOCK: 178 mod_mask = KM_CAPS_LOCK; 179 break; 180 case KC_NUM_LOCK: 181 mod_mask = KM_NUM_LOCK; 182 break; 183 case KC_SCROLL_LOCK: 184 mod_mask = KM_SCROLL_LOCK; 185 break; 186 default: 187 mod_mask = 0; 126 188 } 127 189 … … 143 205 } 144 206 145 if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) && 146 key == KC_F1) { 207 // TODO: More elegant layout switching 208 209 if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) && 210 (key == KC_F1)) { 147 211 layout_destroy(kdev->active_layout); 148 212 kdev->active_layout = layout_create(layout[0]); … … 150 214 } 151 215 152 if ( type == KEY_PRESS&& (kdev->mods & KM_LCTRL) &&153 key == KC_F2) {216 if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) && 217 (key == KC_F2)) { 154 218 layout_destroy(kdev->active_layout); 155 219 kdev->active_layout = layout_create(layout[1]); … … 157 221 } 158 222 159 if ( type == KEY_PRESS&& (kdev->mods & KM_LCTRL) &&160 key == KC_F3) {223 if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) && 224 (key == KC_F3)) { 161 225 layout_destroy(kdev->active_layout); 162 226 kdev->active_layout = layout_create(layout[2]); … … 164 228 } 165 229 166 if ( type == KEY_PRESS&& (kdev->mods & KM_LCTRL) &&167 key == KC_F4) {230 if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) && 231 (key == KC_F4)) { 168 232 layout_destroy(kdev->active_layout); 169 233 kdev->active_layout = layout_create(layout[3]); … … 177 241 ev.c = layout_parse_ev(kdev->active_layout, &ev); 178 242 179 async_exch_t *exch = async_exchange_begin(client_sess); 180 async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c); 181 async_exchange_end(exch); 182 } 183 184 /** Mouse pointer has moved. */ 243 list_foreach(clients, link, client_t, client) { 244 if (client->active) { 245 async_exch_t *exch = async_exchange_begin(client->sess); 246 async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c); 247 async_exchange_end(exch); 248 } 249 } 250 } 251 252 /** Mouse pointer has moved (relative mode). */ 185 253 void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy, int dz) 186 254 { 187 async_exch_t *exch = async_exchange_begin(client_sess); 188 if (dx || dy) 189 async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy); 190 if (dz) { 191 // TODO: Implement proper wheel support 192 keycode_t code = dz > 0 ? KC_UP : KC_DOWN; 193 for (int i = 0; i < 3; ++i) { 194 async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0); 195 } 196 async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0); 197 } 198 async_exchange_end(exch); 199 } 200 201 /** Mouse pointer has moved in absolute mode. */ 255 list_foreach(clients, link, client_t, client) { 256 if (client->active) { 257 async_exch_t *exch = async_exchange_begin(client->sess); 258 259 if ((dx) || (dy)) 260 async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy); 261 262 if (dz) { 263 // TODO: Implement proper wheel support 264 keycode_t code = dz > 0 ? KC_UP : KC_DOWN; 265 266 for (unsigned int i = 0; i < 3; i++) 267 async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0); 268 269 async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0); 270 } 271 272 async_exchange_end(exch); 273 } 274 } 275 } 276 277 /** Mouse pointer has moved (absolute mode). */ 202 278 void mouse_push_event_abs_move(mouse_dev_t *mdev, unsigned int x, unsigned int y, 203 279 unsigned int max_x, unsigned int max_y) 204 280 { 205 if (max_x && max_y) { 206 async_exch_t *exch = async_exchange_begin(client_sess); 207 async_msg_4(exch, INPUT_EVENT_ABS_MOVE, x, y, max_x, max_y); 208 async_exchange_end(exch); 281 list_foreach(clients, link, client_t, client) { 282 if (client->active) { 283 if ((max_x) && (max_y)) { 284 async_exch_t *exch = async_exchange_begin(client->sess); 285 async_msg_4(exch, INPUT_EVENT_ABS_MOVE, x, y, max_x, max_y); 286 async_exchange_end(exch); 287 } 288 } 209 289 } 210 290 } … … 213 293 void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press) 214 294 { 215 async_exch_t *exch = async_exchange_begin(client_sess); 216 async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press); 217 async_exchange_end(exch); 218 } 219 295 list_foreach(clients, link, client_t, client) { 296 if (client->active) { 297 async_exch_t *exch = async_exchange_begin(client->sess); 298 async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press); 299 async_exchange_end(exch); 300 } 301 } 302 } 303 304 /** Arbitrate client actiovation */ 305 static void client_arbitration(void) 306 { 307 /* Mutual exclusion of active clients */ 308 list_foreach(clients, link, client_t, client) 309 client->active = ((active) && (client == active_client)); 310 311 /* Notify clients about the arbitration */ 312 list_foreach(clients, link, client_t, client) { 313 async_exch_t *exch = async_exchange_begin(client->sess); 314 async_msg_0(exch, client->active ? 315 INPUT_EVENT_ACTIVE : INPUT_EVENT_DEACTIVE); 316 async_exchange_end(exch); 317 } 318 } 319 320 /** New client connection */ 220 321 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 221 322 { 323 client_t *client = (client_t *) async_get_client_data(); 324 if (client == NULL) { 325 async_answer_0(iid, ENOMEM); 326 return; 327 } 328 222 329 async_answer_0(iid, EOK); 223 330 … … 227 334 228 335 if (!IPC_GET_IMETHOD(call)) { 229 if (client _sess != NULL) {230 async_hangup(client _sess);231 client _sess = NULL;336 if (client->sess != NULL) { 337 async_hangup(client->sess); 338 client->sess = NULL; 232 339 } 233 340 … … 239 346 async_callback_receive_start(EXCHANGE_SERIALIZE, &call); 240 347 if (sess != NULL) { 241 if (client _sess == NULL) {242 client _sess = sess;348 if (client->sess == NULL) { 349 client->sess = sess; 243 350 async_answer_0(callid, EOK); 244 351 } else … … 246 353 } else { 247 354 switch (IPC_GET_IMETHOD(call)) { 248 case INPUT_YIELD: 249 kbd_devs_yield(); 250 async_answer_0(callid, EOK); 251 break; 252 case INPUT_RECLAIM: 253 kbd_devs_reclaim(); 355 case INPUT_ACTIVATE: 356 active_client = client; 357 client_arbitration(); 254 358 async_answer_0(callid, EOK); 255 359 break; … … 261 365 } 262 366 367 static void kconsole_event_handler(ipc_callid_t callid, ipc_call_t *call, 368 void *arg) 369 { 370 if (IPC_GET_ARG1(*call)) { 371 /* Kernel console activated */ 372 active = false; 373 } else { 374 /* Kernel console deactivated */ 375 active = true; 376 } 377 378 client_arbitration(); 379 } 380 263 381 static kbd_dev_t *kbd_dev_new(void) 264 382 { … … 270 388 } 271 389 272 link_initialize(&kdev-> kbd_devs);390 link_initialize(&kdev->link); 273 391 274 392 kdev->mods = KM_NUM_LOCK; … … 283 401 mouse_dev_t *mdev = calloc(1, sizeof(mouse_dev_t)); 284 402 if (mdev == NULL) { 285 printf("%s: Error allocating keyboarddevice. "403 printf("%s: Error allocating mouse device. " 286 404 "Out of memory.\n", NAME); 287 405 return NULL; 288 406 } 289 407 290 link_initialize(&mdev-> mouse_devs);408 link_initialize(&mdev->link); 291 409 292 410 return mdev; 411 } 412 413 static serial_dev_t *serial_dev_new(void) 414 { 415 serial_dev_t *sdev = calloc(1, sizeof(serial_dev_t)); 416 if (sdev == NULL) { 417 printf("%s: Error allocating serial device. " 418 "Out of memory.\n", NAME); 419 return NULL; 420 } 421 422 sdev->kdev = kbd_dev_new(); 423 if (sdev->kdev == NULL) { 424 free(sdev); 425 return NULL; 426 } 427 428 link_initialize(&sdev->link); 429 430 return sdev; 293 431 } 294 432 … … 314 452 } 315 453 316 list_append(&kdev-> kbd_devs, &kbd_devs);454 list_append(&kdev->link, &kbd_devs); 317 455 return; 318 456 … … 342 480 } 343 481 344 list_append(&mdev-> mouse_devs, &mouse_devs);482 list_append(&mdev->link, &mouse_devs); 345 483 return; 346 484 … … 351 489 /** Add new kbdev device. 352 490 * 353 * @param service_id 491 * @param service_id Service ID of the keyboard device 354 492 * 355 493 */ … … 375 513 } 376 514 377 list_append(&kdev-> kbd_devs, &kbd_devs);515 list_append(&kdev->link, &kbd_devs); 378 516 *kdevp = kdev; 379 517 return EOK; … … 388 526 /** Add new mousedev device. 389 527 * 390 * @param service_id 528 * @param service_id Service ID of the mouse device 391 529 * 392 530 */ … … 412 550 } 413 551 414 list_append(&mdev-> mouse_devs, &mouse_devs);552 list_append(&mdev->link, &mouse_devs); 415 553 *mdevp = mdev; 416 554 return EOK; … … 420 558 return -1; 421 559 } 560 561 static int serial_consumer(void *arg) 562 { 563 serial_dev_t *sdev = (serial_dev_t *) arg; 564 565 while (true) { 566 uint8_t data; 567 568 char_dev_read(sdev->sess, &data, sizeof(data)); 569 kbd_push_data(sdev->kdev, data); 570 } 571 572 return EOK; 573 } 574 575 /** Add new serial console device. 576 * 577 * @param service_id Service ID of the chardev device 578 * 579 */ 580 static int serial_add_srldev(service_id_t service_id, serial_dev_t **sdevp) 581 { 582 bool match = false; 583 584 serial_dev_t *sdev = serial_dev_new(); 585 if (sdev == NULL) 586 return -1; 587 588 sdev->kdev->svc_id = service_id; 589 590 int rc = loc_service_get_name(service_id, &sdev->kdev->svc_name); 591 if (rc != EOK) 592 goto fail; 593 594 list_append(&sdev->link, &serial_devs); 595 596 /* 597 * Is this the device the user wants to use as a serial console? 598 */ 599 match = (serial_console != NULL) && 600 !str_cmp(serial_console, sdev->kdev->svc_name); 601 602 if (match) { 603 sdev->kdev->ctl_ops = &stty_ctl; 604 605 /* Initialize controller driver. */ 606 if ((*sdev->kdev->ctl_ops->init)(sdev->kdev) != 0) { 607 list_remove(&sdev->link); 608 goto fail; 609 } 610 611 sdev->sess = loc_service_connect(service_id, INTERFACE_DDF, 612 IPC_FLAG_BLOCKING); 613 614 fid_t fid = fibril_create(serial_consumer, sdev); 615 fibril_add_ready(fid); 616 } 617 618 *sdevp = sdev; 619 return EOK; 620 621 fail: 622 if (sdev->kdev->svc_name != NULL) 623 free(sdev->kdev->svc_name); 624 free(sdev->kdev); 625 free(sdev); 626 return -1; 627 } 628 422 629 423 630 /** Add legacy drivers/devices. */ … … 431 638 kbd_add_dev(&chardev_port, &stty_ctl); 432 639 #endif 433 #if defined(UARCH_arm32) && defined(MACHINE_integratorcp)434 kbd_add_dev(&pl050_port, &pc_ctl);435 #endif436 640 #if defined(MACHINE_ski) 437 641 kbd_add_dev(&ski_port, &stty_ctl); … … 440 644 kbd_add_dev(&msim_port, &stty_ctl); 441 645 #endif 442 #if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)443 kbd_add_dev(&gxemul_port, &gxe_fb_ctl);444 #endif445 #if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) && !defined(CONFIG_FB)446 kbd_add_dev(&gxemul_port, &stty_ctl);447 #endif448 646 #if defined(UARCH_ppc32) 449 647 kbd_add_dev(&adb_port, &apple_ctl); … … 451 649 #if defined(UARCH_sparc64) && defined(PROCESSOR_sun4v) 452 650 kbd_add_dev(&niagara_port, &stty_ctl); 453 #endif454 #if defined(UARCH_sparc64) && defined(MACHINE_generic)455 kbd_add_dev(&ns16550_port, &sun_ctl);456 651 #endif 457 652 /* Silence warning on abs32le about kbd_add_dev() being unused */ … … 473 668 } 474 669 475 static void kbd_devs_yield(void)476 {477 /* For each keyboard device */478 list_foreach(kbd_devs, kdev_link) {479 kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,480 kbd_devs);481 482 /* Yield port */483 if (kdev->port_ops != NULL)484 (*kdev->port_ops->yield)();485 }486 }487 488 static void kbd_devs_reclaim(void)489 {490 /* For each keyboard device */491 list_foreach(kbd_devs, kdev_link) {492 kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,493 kbd_devs);494 495 /* Reclaim port */496 if (kdev->port_ops != NULL)497 (*kdev->port_ops->reclaim)();498 }499 }500 501 670 static int dev_check_new_kbdevs(void) 502 671 { … … 527 696 528 697 /* Determine whether we already know this device. */ 529 list_foreach(kbd_devs, kdev_link) { 530 kbd_dev_t *kdev = list_get_instance(kdev_link, 531 kbd_dev_t, kbd_devs); 698 list_foreach(kbd_devs, link, kbd_dev_t, kdev) { 532 699 if (kdev->svc_id == svcs[i]) { 533 700 already_known = true; … … 580 747 581 748 /* Determine whether we already know this device. */ 582 list_foreach(mouse_devs, mdev_link) { 583 mouse_dev_t *mdev = list_get_instance(mdev_link, 584 mouse_dev_t, mouse_devs); 749 list_foreach(mouse_devs, link, mouse_dev_t, mdev) { 585 750 if (mdev->svc_id == svcs[i]) { 586 751 already_known = true; … … 605 770 } 606 771 772 static int dev_check_new_serialdevs(void) 773 { 774 category_id_t serial_cat; 775 service_id_t *svcs; 776 size_t count, i; 777 bool already_known; 778 int rc; 779 780 rc = loc_category_get_id("serial", &serial_cat, IPC_FLAG_BLOCKING); 781 if (rc != EOK) { 782 printf("%s: Failed resolving category 'serial'.\n", NAME); 783 return ENOENT; 784 } 785 786 /* 787 * Check for new serial devices 788 */ 789 rc = loc_category_get_svcs(serial_cat, &svcs, &count); 790 if (rc != EOK) { 791 printf("%s: Failed getting list of serial devices.\n", 792 NAME); 793 return EIO; 794 } 795 796 for (i = 0; i < count; i++) { 797 already_known = false; 798 799 /* Determine whether we already know this device. */ 800 list_foreach(serial_devs, link, serial_dev_t, sdev) { 801 if (sdev->kdev->svc_id == svcs[i]) { 802 already_known = true; 803 break; 804 } 805 } 806 807 if (!already_known) { 808 serial_dev_t *sdev; 809 if (serial_add_srldev(svcs[i], &sdev) == EOK) { 810 printf("%s: Connected serial device '%s'\n", 811 NAME, sdev->kdev->svc_name); 812 } 813 } 814 } 815 816 free(svcs); 817 818 /* XXX Handle device removal */ 819 820 return EOK; 821 } 822 607 823 static int dev_check_new(void) 608 824 { … … 611 827 fibril_mutex_lock(&discovery_lock); 612 828 613 rc = dev_check_new_kbdevs(); 614 if (rc != EOK) { 615 fibril_mutex_unlock(&discovery_lock); 616 return rc; 617 } 618 619 rc = dev_check_new_mousedevs(); 620 if (rc != EOK) { 621 fibril_mutex_unlock(&discovery_lock); 622 return rc; 829 if (!serial_console) { 830 rc = dev_check_new_kbdevs(); 831 if (rc != EOK) { 832 fibril_mutex_unlock(&discovery_lock); 833 return rc; 834 } 835 836 rc = dev_check_new_mousedevs(); 837 if (rc != EOK) { 838 fibril_mutex_unlock(&discovery_lock); 839 return rc; 840 } 841 } else { 842 rc = dev_check_new_serialdevs(); 843 if (rc != EOK) { 844 fibril_mutex_unlock(&discovery_lock); 845 return rc; 846 } 623 847 } 624 848 … … 636 860 static int input_start_dev_discovery(void) 637 861 { 638 int rc; 639 640 rc = loc_register_cat_change_cb(cat_change_cb); 862 int rc = loc_register_cat_change_cb(cat_change_cb); 641 863 if (rc != EOK) { 642 864 printf("%s: Failed registering callback for device discovery. " … … 644 866 return rc; 645 867 } 646 868 647 869 return dev_check_new(); 648 870 } … … 655 877 int main(int argc, char **argv) 656 878 { 879 int rc; 880 657 881 if (argc < 2) { 658 882 usage(argv[0]); … … 662 886 printf("%s: HelenOS input service\n", NAME); 663 887 664 sysarg_t obio; 665 888 list_initialize(&clients); 666 889 list_initialize(&kbd_devs); 667 890 list_initialize(&mouse_devs); 668 669 if ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio)) 670 irc_service = true; 671 672 if (irc_service) { 673 while (irc_sess == NULL) 674 irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE, 675 SERVICE_IRC, 0, 0); 676 } 891 list_initialize(&serial_devs); 892 893 serial_console = config_get_value("console"); 677 894 678 895 /* Add legacy keyboard devices. */ … … 683 900 684 901 /* Register driver */ 685 async_set_client_connection(client_connection); 686 int rc = loc_server_register(NAME); 902 async_set_client_data_constructor(client_data_create); 903 async_set_client_data_destructor(client_data_destroy); 904 async_set_fallback_port_handler(client_connection, NULL); 905 906 rc = loc_server_register(NAME); 687 907 if (rc != EOK) { 688 908 printf("%s: Unable to register server\n", NAME); … … 696 916 return rc; 697 917 } 918 919 /* Receive kernel notifications */ 920 rc = async_event_subscribe(EVENT_KCONSOLE, kconsole_event_handler, NULL); 921 if (rc != EOK) 922 printf("%s: Failed to register kconsole notifications (%s)\n", 923 NAME, str_error(rc)); 698 924 699 925 /* Start looking for new input devices */
Note:
See TracChangeset
for help on using the changeset viewer.