Changes in uspace/srv/hid/input/input.c [73d8600:c928bb7] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/input/input.c
r73d8600 rc928bb7 42 42 #include <ipc/services.h> 43 43 #include <ipc/input.h> 44 #include < config.h>44 #include <sysinfo.h> 45 45 #include <stdio.h> 46 46 #include <unistd.h> 47 47 #include <stdlib.h> 48 #include <stdio.h> 48 49 #include <ns.h> 49 50 #include <async.h> … … 53 54 #include <io/keycode.h> 54 55 #include <loc.h> 55 #include <str_error.h>56 #include <char_dev_iface.h>57 #include <fibril.h>58 56 #include "layout.h" 59 57 #include "kbd.h" … … 62 60 #include "mouse.h" 63 61 #include "mouse_proto.h" 64 #include "serial.h"65 62 #include "input.h" 66 63 … … 74 71 }; 75 72 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; 73 static void kbd_devs_yield(void); 74 static void kbd_devs_reclaim(void); 75 76 async_sess_t *client_sess = NULL; 96 77 97 78 /** List of keyboard devices */ … … 101 82 static list_t mouse_devs; 102 83 103 /** List of serial devices */ 104 static list_t serial_devs;84 bool irc_service = false; 85 async_sess_t *irc_sess = NULL; 105 86 106 87 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 }130 88 131 89 void kbd_push_data(kbd_dev_t *kdev, sysarg_t data) … … 145 103 146 104 switch (key) { 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; 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; 167 112 } 168 113 … … 175 120 176 121 switch (key) { 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; 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; 188 126 } 189 127 … … 205 143 } 206 144 207 // TODO: More elegant layout switching 208 209 if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) && 210 (key == KC_F1)) { 145 if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) && 146 key == KC_F1) { 211 147 layout_destroy(kdev->active_layout); 212 148 kdev->active_layout = layout_create(layout[0]); … … 214 150 } 215 151 216 if ( (type == KEY_PRESS)&& (kdev->mods & KM_LCTRL) &&217 (key == KC_F2)) {152 if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) && 153 key == KC_F2) { 218 154 layout_destroy(kdev->active_layout); 219 155 kdev->active_layout = layout_create(layout[1]); … … 221 157 } 222 158 223 if ( (type == KEY_PRESS)&& (kdev->mods & KM_LCTRL) &&224 (key == KC_F3)) {159 if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) && 160 key == KC_F3) { 225 161 layout_destroy(kdev->active_layout); 226 162 kdev->active_layout = layout_create(layout[2]); … … 228 164 } 229 165 230 if ( (type == KEY_PRESS)&& (kdev->mods & KM_LCTRL) &&231 (key == KC_F4)) {166 if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) && 167 key == KC_F4) { 232 168 layout_destroy(kdev->active_layout); 233 169 kdev->active_layout = layout_create(layout[3]); … … 241 177 ev.c = layout_parse_ev(kdev->active_layout, &ev); 242 178 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); 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. */ 185 void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy, int dz) 186 { 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); 248 195 } 249 } 250 } 251 252 /** Mouse pointer has moved (relative mode). */ 253 void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy, int dz) 254 { 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). */ 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. */ 278 202 void mouse_push_event_abs_move(mouse_dev_t *mdev, unsigned int x, unsigned int y, 279 203 unsigned int max_x, unsigned int max_y) 280 204 { 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 } 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); 289 209 } 290 210 } … … 293 213 void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press) 294 214 { 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 */ 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 321 220 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 322 221 { 323 client_t *client = (client_t *) async_get_client_data();324 if (client == NULL) {325 async_answer_0(iid, ENOMEM);326 return;327 }328 329 222 async_answer_0(iid, EOK); 330 223 … … 334 227 335 228 if (!IPC_GET_IMETHOD(call)) { 336 if (client ->sess != NULL) {337 async_hangup(client ->sess);338 client ->sess = NULL;229 if (client_sess != NULL) { 230 async_hangup(client_sess); 231 client_sess = NULL; 339 232 } 340 233 … … 346 239 async_callback_receive_start(EXCHANGE_SERIALIZE, &call); 347 240 if (sess != NULL) { 348 if (client ->sess == NULL) {349 client ->sess = sess;241 if (client_sess == NULL) { 242 client_sess = sess; 350 243 async_answer_0(callid, EOK); 351 244 } else … … 353 246 } else { 354 247 switch (IPC_GET_IMETHOD(call)) { 355 case INPUT_ACTIVATE: 356 active_client = client; 357 client_arbitration(); 248 case INPUT_YIELD: 249 kbd_devs_yield(); 250 async_answer_0(callid, EOK); 251 break; 252 case INPUT_RECLAIM: 253 kbd_devs_reclaim(); 358 254 async_answer_0(callid, EOK); 359 255 break; … … 365 261 } 366 262 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 381 263 static kbd_dev_t *kbd_dev_new(void) 382 264 { … … 388 270 } 389 271 390 link_initialize(&kdev-> link);272 link_initialize(&kdev->kbd_devs); 391 273 392 274 kdev->mods = KM_NUM_LOCK; … … 401 283 mouse_dev_t *mdev = calloc(1, sizeof(mouse_dev_t)); 402 284 if (mdev == NULL) { 403 printf("%s: Error allocating mousedevice. "285 printf("%s: Error allocating keyboard device. " 404 286 "Out of memory.\n", NAME); 405 287 return NULL; 406 288 } 407 289 408 link_initialize(&mdev-> link);290 link_initialize(&mdev->mouse_devs); 409 291 410 292 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;431 293 } 432 294 … … 452 314 } 453 315 454 list_append(&kdev-> link, &kbd_devs);316 list_append(&kdev->kbd_devs, &kbd_devs); 455 317 return; 456 318 … … 480 342 } 481 343 482 list_append(&mdev-> link, &mouse_devs);344 list_append(&mdev->mouse_devs, &mouse_devs); 483 345 return; 484 346 … … 489 351 /** Add new kbdev device. 490 352 * 491 * @param service_id 353 * @param service_id Service ID of the keyboard device 492 354 * 493 355 */ … … 513 375 } 514 376 515 list_append(&kdev-> link, &kbd_devs);377 list_append(&kdev->kbd_devs, &kbd_devs); 516 378 *kdevp = kdev; 517 379 return EOK; … … 526 388 /** Add new mousedev device. 527 389 * 528 * @param service_id 390 * @param service_id Service ID of the mouse device 529 391 * 530 392 */ … … 550 412 } 551 413 552 list_append(&mdev-> link, &mouse_devs);414 list_append(&mdev->mouse_devs, &mouse_devs); 553 415 *mdevp = mdev; 554 416 return EOK; … … 558 420 return -1; 559 421 } 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 device578 *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 629 422 630 423 /** Add legacy drivers/devices. */ … … 638 431 kbd_add_dev(&chardev_port, &stty_ctl); 639 432 #endif 433 #if defined(UARCH_arm32) && defined(MACHINE_integratorcp) 434 kbd_add_dev(&pl050_port, &pc_ctl); 435 #endif 640 436 #if defined(MACHINE_ski) 641 437 kbd_add_dev(&ski_port, &stty_ctl); … … 644 440 kbd_add_dev(&msim_port, &stty_ctl); 645 441 #endif 442 #if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB) 443 kbd_add_dev(&gxemul_port, &gxe_fb_ctl); 444 #endif 445 #if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) && !defined(CONFIG_FB) 446 kbd_add_dev(&gxemul_port, &stty_ctl); 447 #endif 646 448 #if defined(UARCH_ppc32) 647 449 kbd_add_dev(&adb_port, &apple_ctl); … … 649 451 #if defined(UARCH_sparc64) && defined(PROCESSOR_sun4v) 650 452 kbd_add_dev(&niagara_port, &stty_ctl); 453 #endif 454 #if defined(UARCH_sparc64) && defined(MACHINE_generic) 455 kbd_add_dev(&ns16550_port, &sun_ctl); 651 456 #endif 652 457 /* Silence warning on abs32le about kbd_add_dev() being unused */ … … 668 473 } 669 474 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 670 501 static int dev_check_new_kbdevs(void) 671 502 { … … 696 527 697 528 /* Determine whether we already know this device. */ 698 list_foreach(kbd_devs, link, kbd_dev_t, kdev) { 529 list_foreach(kbd_devs, kdev_link) { 530 kbd_dev_t *kdev = list_get_instance(kdev_link, 531 kbd_dev_t, kbd_devs); 699 532 if (kdev->svc_id == svcs[i]) { 700 533 already_known = true; … … 747 580 748 581 /* Determine whether we already know this device. */ 749 list_foreach(mouse_devs, link, mouse_dev_t, mdev) { 582 list_foreach(mouse_devs, mdev_link) { 583 mouse_dev_t *mdev = list_get_instance(mdev_link, 584 mouse_dev_t, mouse_devs); 750 585 if (mdev->svc_id == svcs[i]) { 751 586 already_known = true; … … 770 605 } 771 606 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; 607 static int dev_check_new(void) 608 { 778 609 int rc; 779 610 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 devices788 */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 823 static int dev_check_new(void)824 {825 int rc;826 827 611 fibril_mutex_lock(&discovery_lock); 828 612 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 } 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; 847 623 } 848 624 … … 860 636 static int input_start_dev_discovery(void) 861 637 { 862 int rc = loc_register_cat_change_cb(cat_change_cb); 638 int rc; 639 640 rc = loc_register_cat_change_cb(cat_change_cb); 863 641 if (rc != EOK) { 864 642 printf("%s: Failed registering callback for device discovery. " … … 866 644 return rc; 867 645 } 868 646 869 647 return dev_check_new(); 870 648 } … … 877 655 int main(int argc, char **argv) 878 656 { 879 int rc;880 881 657 if (argc < 2) { 882 658 usage(argv[0]); … … 886 662 printf("%s: HelenOS input service\n", NAME); 887 663 888 list_initialize(&clients); 664 sysarg_t obio; 665 889 666 list_initialize(&kbd_devs); 890 667 list_initialize(&mouse_devs); 891 list_initialize(&serial_devs); 892 893 serial_console = config_get_value("console"); 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 } 894 677 895 678 /* Add legacy keyboard devices. */ … … 900 683 901 684 /* Register driver */ 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); 685 async_set_client_connection(client_connection); 686 int rc = loc_server_register(NAME); 907 687 if (rc != EOK) { 908 688 printf("%s: Unable to register server\n", NAME); … … 916 696 return rc; 917 697 } 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));924 698 925 699 /* Start looking for new input devices */
Note:
See TracChangeset
for help on using the changeset viewer.