kbdmux.c revision 356013
150477Speter/* 21598Srgrimes * kbdmux.c 3156813Sru */ 4156813Sru 558284Speter/*- 6156813Sru * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com> 7116865Speter * All rights reserved. 8129269Scognet * 91598Srgrimes * Redistribution and use in source and binary forms, with or without 10143145Sgrog * modification, are permitted provided that the following conditions 11179174Sobrien * are met: 12179315Sbz * 1. Redistributions of source code must retain the above copyright 13171245Sbz * notice, this list of conditions and the following disclaimer. 14175593Smaxim * 2. Redistributions in binary form must reproduce the above copyright 15175593Smaxim * notice, this list of conditions and the following disclaimer in the 16143145Sgrog * documentation and/or other materials provided with the distribution. 17143268Sgrog * 18143145Sgrog * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19124610Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20143145Sgrog * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2161744Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2261744Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2361744Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2461744Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2527356Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2627356Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27171245Sbz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28179174Sobrien * SUCH DAMAGE. 29179174Sobrien * 30179174Sobrien * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $ 31143145Sgrog * $FreeBSD: stable/11/sys/dev/kbdmux/kbdmux.c 356013 2019-12-22 17:15:48Z kevans $ 32179174Sobrien */ 33179174Sobrien 34179174Sobrien#include "opt_compat.h" 35143145Sgrog#include "opt_evdev.h" 36179174Sobrien#include "opt_kbd.h" 37179174Sobrien#include "opt_kbdmux.h" 38179174Sobrien 39171245Sbz#include <sys/param.h> 40179174Sobrien#include <sys/bus.h> 41143145Sgrog#include <sys/conf.h> 42179174Sobrien#include <sys/consio.h> 43143145Sgrog#include <sys/fcntl.h> 441598Srgrimes#include <sys/kbio.h> 45#include <sys/kernel.h> 46#include <sys/limits.h> 47#include <sys/lock.h> 48#include <sys/malloc.h> 49#include <sys/module.h> 50#include <sys/mutex.h> 51#include <sys/poll.h> 52#include <sys/proc.h> 53#include <sys/queue.h> 54#include <sys/selinfo.h> 55#include <sys/systm.h> 56#include <sys/taskqueue.h> 57#include <sys/uio.h> 58#include <dev/kbd/kbdreg.h> 59 60/* the initial key map, accent map and fkey strings */ 61#ifdef KBDMUX_DFLT_KEYMAP 62#define KBD_DFLT_KEYMAP 63#include "kbdmuxmap.h" 64#endif 65 66#include <dev/kbd/kbdtables.h> 67 68#ifdef EVDEV_SUPPORT 69#include <dev/evdev/evdev.h> 70#include <dev/evdev/input.h> 71#endif 72 73#define KEYBOARD_NAME "kbdmux" 74 75MALLOC_DECLARE(M_KBDMUX); 76MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor"); 77 78/***************************************************************************** 79 ***************************************************************************** 80 ** Keyboard state 81 ***************************************************************************** 82 *****************************************************************************/ 83 84#define KBDMUX_Q_SIZE 512 /* input queue size */ 85 86/* 87 * XXX 88 * For now rely on Giant mutex to protect our data structures. 89 * Just like the rest of keyboard drivers and syscons(4) do. 90 * Note that callout is initialized as not MP-safe to make sure 91 * Giant is held. 92 */ 93 94#if 0 /* not yet */ 95#define KBDMUX_LOCK_DECL_GLOBAL \ 96 struct mtx ks_lock 97#define KBDMUX_LOCK_INIT(s) \ 98 mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE) 99#define KBDMUX_LOCK_DESTROY(s) \ 100 mtx_destroy(&(s)->ks_lock) 101#define KBDMUX_LOCK(s) \ 102 mtx_lock(&(s)->ks_lock) 103#define KBDMUX_UNLOCK(s) \ 104 mtx_unlock(&(s)->ks_lock) 105#define KBDMUX_LOCK_ASSERT(s, w) \ 106 mtx_assert(&(s)->ks_lock, (w)) 107#define KBDMUX_SLEEP(s, f, d, t) \ 108 msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t)) 109#define KBDMUX_CALLOUT_INIT(s) \ 110 callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0) 111#define KBDMUX_QUEUE_INTR(s) \ 112 taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task) 113#else 114#define KBDMUX_LOCK_DECL_GLOBAL 115 116#define KBDMUX_LOCK_INIT(s) 117 118#define KBDMUX_LOCK_DESTROY(s) 119 120#define KBDMUX_LOCK(s) 121 122#define KBDMUX_UNLOCK(s) 123 124#define KBDMUX_LOCK_ASSERT(s, w) 125 126#define KBDMUX_SLEEP(s, f, d, t) \ 127 tsleep(&(s)->f, PCATCH | (PZERO + 1), (d), (t)) 128#define KBDMUX_CALLOUT_INIT(s) \ 129 callout_init(&(s)->ks_timo, 0) 130#define KBDMUX_QUEUE_INTR(s) \ 131 taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task) 132#endif /* not yet */ 133 134/* 135 * kbdmux keyboard 136 */ 137struct kbdmux_kbd 138{ 139 keyboard_t *kbd; /* keyboard */ 140 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */ 141}; 142 143typedef struct kbdmux_kbd kbdmux_kbd_t; 144 145/* 146 * kbdmux state 147 */ 148struct kbdmux_state 149{ 150 char ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */ 151 unsigned int ks_inq_start; 152 unsigned int ks_inq_length; 153 struct task ks_task; /* interrupt task */ 154 struct callout ks_timo; /* timeout handler */ 155#define TICKS (hz) /* rate */ 156 157 int ks_flags; /* flags */ 158#define COMPOSE (1 << 0) /* compose char flag */ 159#define TASK (1 << 2) /* interrupt task queued */ 160 161 int ks_polling; /* poll nesting count */ 162 int ks_mode; /* K_XLATE, K_RAW, K_CODE */ 163 int ks_state; /* state */ 164 int ks_accents; /* accent key index (> 0) */ 165 u_int ks_composed_char; /* composed char code */ 166 u_char ks_prefix; /* AT scan code prefix */ 167 168#ifdef EVDEV_SUPPORT 169 struct evdev_dev * ks_evdev; 170 int ks_evdev_state; 171#endif 172 173 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */ 174 175 KBDMUX_LOCK_DECL_GLOBAL; 176}; 177 178typedef struct kbdmux_state kbdmux_state_t; 179 180/***************************************************************************** 181 ***************************************************************************** 182 ** Helper functions 183 ***************************************************************************** 184 *****************************************************************************/ 185 186static task_fn_t kbdmux_kbd_intr; 187static timeout_t kbdmux_kbd_intr_timo; 188static kbd_callback_func_t kbdmux_kbd_event; 189 190static void 191kbdmux_kbd_putc(kbdmux_state_t *state, char c) 192{ 193 unsigned int p; 194 195 if (state->ks_inq_length == KBDMUX_Q_SIZE) 196 return; 197 198 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE; 199 state->ks_inq[p] = c; 200 state->ks_inq_length++; 201} 202 203static int 204kbdmux_kbd_getc(kbdmux_state_t *state) 205{ 206 unsigned char c; 207 208 if (state->ks_inq_length == 0) 209 return (-1); 210 211 c = state->ks_inq[state->ks_inq_start]; 212 state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE; 213 state->ks_inq_length--; 214 215 return (c); 216} 217 218/* 219 * Interrupt handler task 220 */ 221void 222kbdmux_kbd_intr(void *xkbd, int pending) 223{ 224 keyboard_t *kbd = (keyboard_t *) xkbd; 225 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 226 227 kbdd_intr(kbd, NULL); 228 229 KBDMUX_LOCK(state); 230 231 state->ks_flags &= ~TASK; 232 wakeup(&state->ks_task); 233 234 KBDMUX_UNLOCK(state); 235} 236 237/* 238 * Schedule interrupt handler on timeout. Called with locked state. 239 */ 240void 241kbdmux_kbd_intr_timo(void *xstate) 242{ 243 kbdmux_state_t *state = (kbdmux_state_t *) xstate; 244 245 KBDMUX_LOCK_ASSERT(state, MA_OWNED); 246 247 if (callout_pending(&state->ks_timo)) 248 return; /* callout was reset */ 249 250 if (!callout_active(&state->ks_timo)) 251 return; /* callout was stopped */ 252 253 callout_deactivate(&state->ks_timo); 254 255 /* queue interrupt task if needed */ 256 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) && 257 KBDMUX_QUEUE_INTR(state) == 0) 258 state->ks_flags |= TASK; 259 260 /* re-schedule timeout */ 261 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state); 262} 263 264/* 265 * Process event from one of our keyboards 266 */ 267static int 268kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg) 269{ 270 kbdmux_state_t *state = (kbdmux_state_t *) arg; 271 272 switch (event) { 273 case KBDIO_KEYINPUT: { 274 int c; 275 276 KBDMUX_LOCK(state); 277 278 /* 279 * Read all chars from the keyboard 280 * 281 * Turns out that atkbd(4) check_char() method may return 282 * "true" while read_char() method returns NOKEY. If this 283 * happens we could stuck in the loop below. Avoid this 284 * by breaking out of the loop if read_char() method returns 285 * NOKEY. 286 */ 287 288 while (kbdd_check_char(kbd)) { 289 c = kbdd_read_char(kbd, 0); 290 if (c == NOKEY) 291 break; 292 if (c == ERRKEY) 293 continue; /* XXX ring bell */ 294 if (!KBD_IS_BUSY(kbd)) 295 continue; /* not open - discard the input */ 296 297 kbdmux_kbd_putc(state, c); 298 } 299 300 /* queue interrupt task if needed */ 301 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) && 302 KBDMUX_QUEUE_INTR(state) == 0) 303 state->ks_flags |= TASK; 304 305 KBDMUX_UNLOCK(state); 306 } break; 307 308 case KBDIO_UNLOADING: { 309 kbdmux_kbd_t *k; 310 311 KBDMUX_LOCK(state); 312 313 SLIST_FOREACH(k, &state->ks_kbds, next) 314 if (k->kbd == kbd) 315 break; 316 317 if (k != NULL) { 318 kbd_release(k->kbd, &k->kbd); 319 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next); 320 321 k->kbd = NULL; 322 323 free(k, M_KBDMUX); 324 } 325 326 KBDMUX_UNLOCK(state); 327 } break; 328 329 default: 330 return (EINVAL); 331 /* NOT REACHED */ 332 } 333 334 return (0); 335} 336 337/**************************************************************************** 338 **************************************************************************** 339 ** Keyboard driver 340 **************************************************************************** 341 ****************************************************************************/ 342 343static int kbdmux_configure(int flags); 344static kbd_probe_t kbdmux_probe; 345static kbd_init_t kbdmux_init; 346static kbd_term_t kbdmux_term; 347static kbd_intr_t kbdmux_intr; 348static kbd_test_if_t kbdmux_test_if; 349static kbd_enable_t kbdmux_enable; 350static kbd_disable_t kbdmux_disable; 351static kbd_read_t kbdmux_read; 352static kbd_check_t kbdmux_check; 353static kbd_read_char_t kbdmux_read_char; 354static kbd_check_char_t kbdmux_check_char; 355static kbd_ioctl_t kbdmux_ioctl; 356static kbd_lock_t kbdmux_lock; 357static void kbdmux_clear_state_locked(kbdmux_state_t *state); 358static kbd_clear_state_t kbdmux_clear_state; 359static kbd_get_state_t kbdmux_get_state; 360static kbd_set_state_t kbdmux_set_state; 361static kbd_poll_mode_t kbdmux_poll; 362 363static keyboard_switch_t kbdmuxsw = { 364 .probe = kbdmux_probe, 365 .init = kbdmux_init, 366 .term = kbdmux_term, 367 .intr = kbdmux_intr, 368 .test_if = kbdmux_test_if, 369 .enable = kbdmux_enable, 370 .disable = kbdmux_disable, 371 .read = kbdmux_read, 372 .check = kbdmux_check, 373 .read_char = kbdmux_read_char, 374 .check_char = kbdmux_check_char, 375 .ioctl = kbdmux_ioctl, 376 .lock = kbdmux_lock, 377 .clear_state = kbdmux_clear_state, 378 .get_state = kbdmux_get_state, 379 .set_state = kbdmux_set_state, 380 .poll = kbdmux_poll, 381}; 382 383#ifdef EVDEV_SUPPORT 384static const struct evdev_methods kbdmux_evdev_methods = { 385 .ev_event = evdev_ev_kbd_event, 386}; 387#endif 388 389/* 390 * Return the number of found keyboards 391 */ 392static int 393kbdmux_configure(int flags) 394{ 395 return (1); 396} 397 398/* 399 * Detect a keyboard 400 */ 401static int 402kbdmux_probe(int unit, void *arg, int flags) 403{ 404 if (resource_disabled(KEYBOARD_NAME, unit)) 405 return (ENXIO); 406 407 return (0); 408} 409 410/* 411 * Reset and initialize the keyboard (stolen from atkbd.c) 412 */ 413static int 414kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags) 415{ 416 keyboard_t *kbd = NULL; 417 kbdmux_state_t *state = NULL; 418 keymap_t *keymap = NULL; 419 accentmap_t *accmap = NULL; 420 fkeytab_t *fkeymap = NULL; 421 int error, needfree, fkeymap_size, delay[2]; 422#ifdef EVDEV_SUPPORT 423 struct evdev_dev *evdev; 424 char phys_loc[NAMELEN]; 425#endif 426 427 if (*kbdp == NULL) { 428 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO); 429 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO); 430 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT); 431 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT); 432 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT); 433 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]); 434 needfree = 1; 435 436 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) || 437 (accmap == NULL) || (fkeymap == NULL)) { 438 error = ENOMEM; 439 goto bad; 440 } 441 442 KBDMUX_LOCK_INIT(state); 443 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd); 444 KBDMUX_CALLOUT_INIT(state); 445 SLIST_INIT(&state->ks_kbds); 446 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) { 447 return (0); 448 } else { 449 kbd = *kbdp; 450 state = (kbdmux_state_t *) kbd->kb_data; 451 keymap = kbd->kb_keymap; 452 accmap = kbd->kb_accentmap; 453 fkeymap = kbd->kb_fkeytab; 454 fkeymap_size = kbd->kb_fkeytab_size; 455 needfree = 0; 456 } 457 458 if (!KBD_IS_PROBED(kbd)) { 459 /* XXX assume 101/102 keys keyboard */ 460 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0); 461 bcopy(&key_map, keymap, sizeof(key_map)); 462 bcopy(&accent_map, accmap, sizeof(accent_map)); 463 bcopy(fkey_tab, fkeymap, 464 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab))); 465 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); 466 kbd->kb_data = (void *)state; 467 468 KBD_FOUND_DEVICE(kbd); 469 KBD_PROBE_DONE(kbd); 470 471 KBDMUX_LOCK(state); 472 kbdmux_clear_state_locked(state); 473 state->ks_mode = K_XLATE; 474 KBDMUX_UNLOCK(state); 475 } 476 477 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { 478 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY; 479 480 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); 481 482 delay[0] = kbd->kb_delay1; 483 delay[1] = kbd->kb_delay2; 484 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); 485 486#ifdef EVDEV_SUPPORT 487 /* register as evdev provider */ 488 evdev = evdev_alloc(); 489 evdev_set_name(evdev, "System keyboard multiplexer"); 490 snprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit); 491 evdev_set_phys(evdev, phys_loc); 492 evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0); 493 evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods); 494 evdev_support_event(evdev, EV_SYN); 495 evdev_support_event(evdev, EV_KEY); 496 evdev_support_event(evdev, EV_LED); 497 evdev_support_event(evdev, EV_REP); 498 evdev_support_all_known_keys(evdev); 499 evdev_support_led(evdev, LED_NUML); 500 evdev_support_led(evdev, LED_CAPSL); 501 evdev_support_led(evdev, LED_SCROLLL); 502 503 if (evdev_register(evdev)) 504 evdev_free(evdev); 505 else 506 state->ks_evdev = evdev; 507 state->ks_evdev_state = 0; 508#endif 509 510 KBD_INIT_DONE(kbd); 511 } 512 513 if (!KBD_IS_CONFIGURED(kbd)) { 514 if (kbd_register(kbd) < 0) { 515 error = ENXIO; 516 goto bad; 517 } 518 519 KBD_CONFIG_DONE(kbd); 520 521 KBDMUX_LOCK(state); 522 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state); 523 KBDMUX_UNLOCK(state); 524 } 525 526 return (0); 527bad: 528 if (needfree) { 529 if (state != NULL) 530 free(state, M_KBDMUX); 531 if (keymap != NULL) 532 free(keymap, M_KBDMUX); 533 if (accmap != NULL) 534 free(accmap, M_KBDMUX); 535 if (fkeymap != NULL) 536 free(fkeymap, M_KBDMUX); 537 if (kbd != NULL) { 538 free(kbd, M_KBDMUX); 539 *kbdp = NULL; /* insure ref doesn't leak to caller */ 540 } 541 } 542 543 return (error); 544} 545 546/* 547 * Finish using this keyboard 548 */ 549static int 550kbdmux_term(keyboard_t *kbd) 551{ 552 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 553 kbdmux_kbd_t *k; 554 555 KBDMUX_LOCK(state); 556 557 /* kill callout */ 558 callout_stop(&state->ks_timo); 559 560 /* wait for interrupt task */ 561 while (state->ks_flags & TASK) 562 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0); 563 564 /* release all keyboards from the mux */ 565 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) { 566 kbd_release(k->kbd, &k->kbd); 567 SLIST_REMOVE_HEAD(&state->ks_kbds, next); 568 569 k->kbd = NULL; 570 571 free(k, M_KBDMUX); 572 } 573 574 KBDMUX_UNLOCK(state); 575 576 kbd_unregister(kbd); 577 578#ifdef EVDEV_SUPPORT 579 evdev_free(state->ks_evdev); 580#endif 581 582 KBDMUX_LOCK_DESTROY(state); 583 bzero(state, sizeof(*state)); 584 free(state, M_KBDMUX); 585 586 free(kbd->kb_keymap, M_KBDMUX); 587 free(kbd->kb_accentmap, M_KBDMUX); 588 free(kbd->kb_fkeytab, M_KBDMUX); 589 free(kbd, M_KBDMUX); 590 591 return (0); 592} 593 594/* 595 * Keyboard interrupt routine 596 */ 597static int 598kbdmux_intr(keyboard_t *kbd, void *arg) 599{ 600 int c; 601 602 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) { 603 /* let the callback function to process the input */ 604 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT, 605 kbd->kb_callback.kc_arg); 606 } else { 607 /* read and discard the input; no one is waiting for input */ 608 do { 609 c = kbdmux_read_char(kbd, FALSE); 610 } while (c != NOKEY); 611 } 612 613 return (0); 614} 615 616/* 617 * Test the interface to the device 618 */ 619static int 620kbdmux_test_if(keyboard_t *kbd) 621{ 622 return (0); 623} 624 625/* 626 * Enable the access to the device; until this function is called, 627 * the client cannot read from the keyboard. 628 */ 629static int 630kbdmux_enable(keyboard_t *kbd) 631{ 632 KBD_ACTIVATE(kbd); 633 return (0); 634} 635 636/* 637 * Disallow the access to the device 638 */ 639static int 640kbdmux_disable(keyboard_t *kbd) 641{ 642 KBD_DEACTIVATE(kbd); 643 return (0); 644} 645 646/* 647 * Read one byte from the keyboard if it's allowed 648 */ 649static int 650kbdmux_read(keyboard_t *kbd, int wait) 651{ 652 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 653 int c; 654 655 KBDMUX_LOCK(state); 656 c = kbdmux_kbd_getc(state); 657 KBDMUX_UNLOCK(state); 658 659 if (c != -1) 660 kbd->kb_count ++; 661 662 return (KBD_IS_ACTIVE(kbd)? c : -1); 663} 664 665/* 666 * Check if data is waiting 667 */ 668static int 669kbdmux_check(keyboard_t *kbd) 670{ 671 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 672 int ready; 673 674 if (!KBD_IS_ACTIVE(kbd)) 675 return (FALSE); 676 677 KBDMUX_LOCK(state); 678 ready = (state->ks_inq_length > 0) ? TRUE : FALSE; 679 KBDMUX_UNLOCK(state); 680 681 return (ready); 682} 683 684/* 685 * Read char from the keyboard (stolen from atkbd.c) 686 */ 687static u_int 688kbdmux_read_char(keyboard_t *kbd, int wait) 689{ 690 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 691 u_int action; 692 int scancode, keycode; 693 694 KBDMUX_LOCK(state); 695 696next_code: 697 698 /* do we have a composed char to return? */ 699 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) { 700 action = state->ks_composed_char; 701 state->ks_composed_char = 0; 702 if (action > UCHAR_MAX) { 703 KBDMUX_UNLOCK(state); 704 705 return (ERRKEY); 706 } 707 708 KBDMUX_UNLOCK(state); 709 710 return (action); 711 } 712 713 /* see if there is something in the keyboard queue */ 714 scancode = kbdmux_kbd_getc(state); 715 if (scancode == -1) { 716 if (state->ks_polling != 0) { 717 kbdmux_kbd_t *k; 718 719 SLIST_FOREACH(k, &state->ks_kbds, next) { 720 while (kbdd_check_char(k->kbd)) { 721 scancode = kbdd_read_char(k->kbd, 0); 722 if (scancode == NOKEY) 723 break; 724 if (scancode == ERRKEY) 725 continue; 726 if (!KBD_IS_BUSY(k->kbd)) 727 continue; 728 729 kbdmux_kbd_putc(state, scancode); 730 } 731 } 732 733 if (state->ks_inq_length > 0) 734 goto next_code; 735 } 736 737 KBDMUX_UNLOCK(state); 738 return (NOKEY); 739 } 740 /* XXX FIXME: check for -1 if wait == 1! */ 741 742 kbd->kb_count ++; 743 744#ifdef EVDEV_SUPPORT 745 /* push evdev event */ 746 if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) { 747 uint16_t key = evdev_scancode2key(&state->ks_evdev_state, 748 scancode); 749 750 if (key != KEY_RESERVED) { 751 evdev_push_event(state->ks_evdev, EV_KEY, 752 key, scancode & 0x80 ? 0 : 1); 753 evdev_sync(state->ks_evdev); 754 } 755 } 756#endif 757 758 /* return the byte as is for the K_RAW mode */ 759 if (state->ks_mode == K_RAW) { 760 KBDMUX_UNLOCK(state); 761 return (scancode); 762 } 763 764 /* translate the scan code into a keycode */ 765 keycode = scancode & 0x7F; 766 switch (state->ks_prefix) { 767 case 0x00: /* normal scancode */ 768 switch(scancode) { 769 case 0xB8: /* left alt (compose key) released */ 770 if (state->ks_flags & COMPOSE) { 771 state->ks_flags &= ~COMPOSE; 772 if (state->ks_composed_char > UCHAR_MAX) 773 state->ks_composed_char = 0; 774 } 775 break; 776 case 0x38: /* left alt (compose key) pressed */ 777 if (!(state->ks_flags & COMPOSE)) { 778 state->ks_flags |= COMPOSE; 779 state->ks_composed_char = 0; 780 } 781 break; 782 case 0xE0: 783 case 0xE1: 784 state->ks_prefix = scancode; 785 goto next_code; 786 } 787 break; 788 case 0xE0: /* 0xE0 prefix */ 789 state->ks_prefix = 0; 790 switch (keycode) { 791 case 0x1C: /* right enter key */ 792 keycode = 0x59; 793 break; 794 case 0x1D: /* right ctrl key */ 795 keycode = 0x5A; 796 break; 797 case 0x35: /* keypad divide key */ 798 keycode = 0x5B; 799 break; 800 case 0x37: /* print scrn key */ 801 keycode = 0x5C; 802 break; 803 case 0x38: /* right alt key (alt gr) */ 804 keycode = 0x5D; 805 break; 806 case 0x46: /* ctrl-pause/break on AT 101 (see below) */ 807 keycode = 0x68; 808 break; 809 case 0x47: /* grey home key */ 810 keycode = 0x5E; 811 break; 812 case 0x48: /* grey up arrow key */ 813 keycode = 0x5F; 814 break; 815 case 0x49: /* grey page up key */ 816 keycode = 0x60; 817 break; 818 case 0x4B: /* grey left arrow key */ 819 keycode = 0x61; 820 break; 821 case 0x4D: /* grey right arrow key */ 822 keycode = 0x62; 823 break; 824 case 0x4F: /* grey end key */ 825 keycode = 0x63; 826 break; 827 case 0x50: /* grey down arrow key */ 828 keycode = 0x64; 829 break; 830 case 0x51: /* grey page down key */ 831 keycode = 0x65; 832 break; 833 case 0x52: /* grey insert key */ 834 keycode = 0x66; 835 break; 836 case 0x53: /* grey delete key */ 837 keycode = 0x67; 838 break; 839 /* the following 3 are only used on the MS "Natural" keyboard */ 840 case 0x5b: /* left Window key */ 841 keycode = 0x69; 842 break; 843 case 0x5c: /* right Window key */ 844 keycode = 0x6a; 845 break; 846 case 0x5d: /* menu key */ 847 keycode = 0x6b; 848 break; 849 case 0x5e: /* power key */ 850 keycode = 0x6d; 851 break; 852 case 0x5f: /* sleep key */ 853 keycode = 0x6e; 854 break; 855 case 0x63: /* wake key */ 856 keycode = 0x6f; 857 break; 858 case 0x64: /* [JP106USB] backslash, underscore */ 859 keycode = 0x73; 860 break; 861 default: /* ignore everything else */ 862 goto next_code; 863 } 864 break; 865 case 0xE1: /* 0xE1 prefix */ 866 /* 867 * The pause/break key on the 101 keyboard produces: 868 * E1-1D-45 E1-9D-C5 869 * Ctrl-pause/break produces: 870 * E0-46 E0-C6 (See above.) 871 */ 872 state->ks_prefix = 0; 873 if (keycode == 0x1D) 874 state->ks_prefix = 0x1D; 875 goto next_code; 876 /* NOT REACHED */ 877 case 0x1D: /* pause / break */ 878 state->ks_prefix = 0; 879 if (keycode != 0x45) 880 goto next_code; 881 keycode = 0x68; 882 break; 883 } 884 885 /* XXX assume 101/102 keys AT keyboard */ 886 switch (keycode) { 887 case 0x5c: /* print screen */ 888 if (state->ks_flags & ALTS) 889 keycode = 0x54; /* sysrq */ 890 break; 891 case 0x68: /* pause/break */ 892 if (state->ks_flags & CTLS) 893 keycode = 0x6c; /* break */ 894 break; 895 } 896 897 /* return the key code in the K_CODE mode */ 898 if (state->ks_mode == K_CODE) { 899 KBDMUX_UNLOCK(state); 900 return (keycode | (scancode & 0x80)); 901 } 902 903 /* compose a character code */ 904 if (state->ks_flags & COMPOSE) { 905 switch (keycode | (scancode & 0x80)) { 906 /* key pressed, process it */ 907 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 908 state->ks_composed_char *= 10; 909 state->ks_composed_char += keycode - 0x40; 910 if (state->ks_composed_char > UCHAR_MAX) { 911 KBDMUX_UNLOCK(state); 912 return (ERRKEY); 913 } 914 goto next_code; 915 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 916 state->ks_composed_char *= 10; 917 state->ks_composed_char += keycode - 0x47; 918 if (state->ks_composed_char > UCHAR_MAX) { 919 KBDMUX_UNLOCK(state); 920 return (ERRKEY); 921 } 922 goto next_code; 923 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 924 state->ks_composed_char *= 10; 925 state->ks_composed_char += keycode - 0x4E; 926 if (state->ks_composed_char > UCHAR_MAX) { 927 KBDMUX_UNLOCK(state); 928 return (ERRKEY); 929 } 930 goto next_code; 931 case 0x52: /* keypad 0 */ 932 state->ks_composed_char *= 10; 933 if (state->ks_composed_char > UCHAR_MAX) { 934 KBDMUX_UNLOCK(state); 935 return (ERRKEY); 936 } 937 goto next_code; 938 939 /* key released, no interest here */ 940 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 941 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 942 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 943 case 0xD2: /* keypad 0 */ 944 goto next_code; 945 946 case 0x38: /* left alt key */ 947 break; 948 949 default: 950 if (state->ks_composed_char > 0) { 951 state->ks_flags &= ~COMPOSE; 952 state->ks_composed_char = 0; 953 KBDMUX_UNLOCK(state); 954 return (ERRKEY); 955 } 956 break; 957 } 958 } 959 960 /* keycode to key action */ 961 action = genkbd_keyaction(kbd, keycode, scancode & 0x80, 962 &state->ks_state, &state->ks_accents); 963 if (action == NOKEY) 964 goto next_code; 965 966 KBDMUX_UNLOCK(state); 967 968 return (action); 969} 970 971/* 972 * Check if char is waiting 973 */ 974static int 975kbdmux_check_char(keyboard_t *kbd) 976{ 977 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 978 int ready; 979 980 if (!KBD_IS_ACTIVE(kbd)) 981 return (FALSE); 982 983 KBDMUX_LOCK(state); 984 985 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0)) 986 ready = TRUE; 987 else 988 ready = (state->ks_inq_length > 0) ? TRUE : FALSE; 989 990 KBDMUX_UNLOCK(state); 991 992 return (ready); 993} 994 995/* 996 * Keyboard ioctl's 997 */ 998static int 999kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 1000{ 1001 static int delays[] = { 1002 250, 500, 750, 1000 1003 }; 1004 1005 static int rates[] = { 1006 34, 38, 42, 46, 50, 55, 59, 63, 1007 68, 76, 84, 92, 100, 110, 118, 126, 1008 136, 152, 168, 184, 200, 220, 236, 252, 1009 272, 304, 336, 368, 400, 440, 472, 504 1010 }; 1011 1012 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 1013 kbdmux_kbd_t *k; 1014 keyboard_info_t *ki; 1015 int error = 0, mode; 1016#ifdef COMPAT_FREEBSD6 1017 int ival; 1018#endif 1019 1020 if (state == NULL) 1021 return (ENXIO); 1022 1023 switch (cmd) { 1024 case KBADDKBD: /* add keyboard to the mux */ 1025 ki = (keyboard_info_t *) arg; 1026 1027 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' || 1028 strcmp(ki->kb_name, "*") == 0) 1029 return (EINVAL); /* bad input */ 1030 1031 KBDMUX_LOCK(state); 1032 1033 SLIST_FOREACH(k, &state->ks_kbds, next) 1034 if (k->kbd->kb_unit == ki->kb_unit && 1035 strcmp(k->kbd->kb_name, ki->kb_name) == 0) 1036 break; 1037 1038 if (k != NULL) { 1039 KBDMUX_UNLOCK(state); 1040 1041 return (0); /* keyboard already in the mux */ 1042 } 1043 1044 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO); 1045 if (k == NULL) { 1046 KBDMUX_UNLOCK(state); 1047 1048 return (ENOMEM); /* out of memory */ 1049 } 1050 1051 k->kbd = kbd_get_keyboard( 1052 kbd_allocate( 1053 ki->kb_name, 1054 ki->kb_unit, 1055 (void *) &k->kbd, 1056 kbdmux_kbd_event, (void *) state)); 1057 if (k->kbd == NULL) { 1058 KBDMUX_UNLOCK(state); 1059 free(k, M_KBDMUX); 1060 1061 return (EINVAL); /* bad keyboard */ 1062 } 1063 1064 kbdd_enable(k->kbd); 1065 kbdd_clear_state(k->kbd); 1066 1067 /* set K_RAW mode on slave keyboard */ 1068 mode = K_RAW; 1069 error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode); 1070 if (error == 0) { 1071 /* set lock keys state on slave keyboard */ 1072 mode = state->ks_state & LOCK_MASK; 1073 error = kbdd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode); 1074 } 1075 1076 if (error != 0) { 1077 KBDMUX_UNLOCK(state); 1078 1079 kbd_release(k->kbd, &k->kbd); 1080 k->kbd = NULL; 1081 1082 free(k, M_KBDMUX); 1083 1084 return (error); /* could not set mode */ 1085 } 1086 1087 SLIST_INSERT_HEAD(&state->ks_kbds, k, next); 1088 1089 KBDMUX_UNLOCK(state); 1090 break; 1091 1092 case KBRELKBD: /* release keyboard from the mux */ 1093 ki = (keyboard_info_t *) arg; 1094 1095 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' || 1096 strcmp(ki->kb_name, "*") == 0) 1097 return (EINVAL); /* bad input */ 1098 1099 KBDMUX_LOCK(state); 1100 1101 SLIST_FOREACH(k, &state->ks_kbds, next) 1102 if (k->kbd->kb_unit == ki->kb_unit && 1103 strcmp(k->kbd->kb_name, ki->kb_name) == 0) 1104 break; 1105 1106 if (k != NULL) { 1107 error = kbd_release(k->kbd, &k->kbd); 1108 if (error == 0) { 1109 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next); 1110 1111 k->kbd = NULL; 1112 1113 free(k, M_KBDMUX); 1114 } 1115 } else 1116 error = ENXIO; /* keyboard is not in the mux */ 1117 1118 KBDMUX_UNLOCK(state); 1119 break; 1120 1121 case KDGKBMODE: /* get kyboard mode */ 1122 KBDMUX_LOCK(state); 1123 *(int *)arg = state->ks_mode; 1124 KBDMUX_UNLOCK(state); 1125 break; 1126 1127#ifdef COMPAT_FREEBSD6 1128 case _IO('K', 7): 1129 ival = IOCPARM_IVAL(arg); 1130 arg = (caddr_t)&ival; 1131 /* FALLTHROUGH */ 1132#endif 1133 case KDSKBMODE: /* set keyboard mode */ 1134 KBDMUX_LOCK(state); 1135 1136 switch (*(int *)arg) { 1137 case K_XLATE: 1138 if (state->ks_mode != K_XLATE) { 1139 /* make lock key state and LED state match */ 1140 state->ks_state &= ~LOCK_MASK; 1141 state->ks_state |= KBD_LED_VAL(kbd); 1142 } 1143 /* FALLTHROUGH */ 1144 1145 case K_RAW: 1146 case K_CODE: 1147 if (state->ks_mode != *(int *)arg) { 1148 kbdmux_clear_state_locked(state); 1149 state->ks_mode = *(int *)arg; 1150 } 1151 break; 1152 1153 default: 1154 error = EINVAL; 1155 break; 1156 } 1157 1158 KBDMUX_UNLOCK(state); 1159 break; 1160 1161 case KDGETLED: /* get keyboard LED */ 1162 KBDMUX_LOCK(state); 1163 *(int *)arg = KBD_LED_VAL(kbd); 1164 KBDMUX_UNLOCK(state); 1165 break; 1166 1167#ifdef COMPAT_FREEBSD6 1168 case _IO('K', 66): 1169 ival = IOCPARM_IVAL(arg); 1170 arg = (caddr_t)&ival; 1171 /* FALLTHROUGH */ 1172#endif 1173 case KDSETLED: /* set keyboard LED */ 1174 KBDMUX_LOCK(state); 1175 1176 /* NOTE: lock key state in ks_state won't be changed */ 1177 if (*(int *)arg & ~LOCK_MASK) { 1178 KBDMUX_UNLOCK(state); 1179 1180 return (EINVAL); 1181 } 1182 1183 KBD_LED_VAL(kbd) = *(int *)arg; 1184#ifdef EVDEV_SUPPORT 1185 if (state->ks_evdev != NULL && 1186 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX) 1187 evdev_push_leds(state->ks_evdev, *(int *)arg); 1188#endif 1189 /* KDSETLED on all slave keyboards */ 1190 SLIST_FOREACH(k, &state->ks_kbds, next) 1191 (void)kbdd_ioctl(k->kbd, KDSETLED, arg); 1192 1193 KBDMUX_UNLOCK(state); 1194 break; 1195 1196 case KDGKBSTATE: /* get lock key state */ 1197 KBDMUX_LOCK(state); 1198 *(int *)arg = state->ks_state & LOCK_MASK; 1199 KBDMUX_UNLOCK(state); 1200 break; 1201 1202#ifdef COMPAT_FREEBSD6 1203 case _IO('K', 20): 1204 ival = IOCPARM_IVAL(arg); 1205 arg = (caddr_t)&ival; 1206 /* FALLTHROUGH */ 1207#endif 1208 case KDSKBSTATE: /* set lock key state */ 1209 KBDMUX_LOCK(state); 1210 1211 if (*(int *)arg & ~LOCK_MASK) { 1212 KBDMUX_UNLOCK(state); 1213 1214 return (EINVAL); 1215 } 1216 1217 state->ks_state &= ~LOCK_MASK; 1218 state->ks_state |= *(int *)arg; 1219 1220 /* KDSKBSTATE on all slave keyboards */ 1221 SLIST_FOREACH(k, &state->ks_kbds, next) 1222 (void)kbdd_ioctl(k->kbd, KDSKBSTATE, arg); 1223 1224 KBDMUX_UNLOCK(state); 1225 1226 return (kbdmux_ioctl(kbd, KDSETLED, arg)); 1227 /* NOT REACHED */ 1228 1229#ifdef COMPAT_FREEBSD6 1230 case _IO('K', 67): 1231 cmd = KDSETRAD; 1232 ival = IOCPARM_IVAL(arg); 1233 arg = (caddr_t)&ival; 1234 /* FALLTHROUGH */ 1235#endif 1236 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */ 1237 case KDSETRAD: /* set keyboard repeat rate (old interface) */ 1238 KBDMUX_LOCK(state); 1239 1240 if (cmd == KDSETREPEAT) { 1241 int i; 1242 1243 /* lookup delay */ 1244 for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --) 1245 if (((int *)arg)[0] >= delays[i]) 1246 break; 1247 mode = i << 5; 1248 1249 /* lookup rate */ 1250 for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --) 1251 if (((int *)arg)[1] >= rates[i]) 1252 break; 1253 mode |= i; 1254 } else 1255 mode = *(int *)arg; 1256 1257 if (mode & ~0x7f) { 1258 KBDMUX_UNLOCK(state); 1259 1260 return (EINVAL); 1261 } 1262 1263 kbd->kb_delay1 = delays[(mode >> 5) & 3]; 1264 kbd->kb_delay2 = rates[mode & 0x1f]; 1265#ifdef EVDEV_SUPPORT 1266 if (state->ks_evdev != NULL && 1267 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX) 1268 evdev_push_repeats(state->ks_evdev, kbd); 1269#endif 1270 /* perform command on all slave keyboards */ 1271 SLIST_FOREACH(k, &state->ks_kbds, next) 1272 (void)kbdd_ioctl(k->kbd, cmd, arg); 1273 1274 KBDMUX_UNLOCK(state); 1275 break; 1276 1277 case PIO_KEYMAP: /* set keyboard translation table */ 1278 case OPIO_KEYMAP: /* set keyboard translation table (compat) */ 1279 case PIO_KEYMAPENT: /* set keyboard translation table entry */ 1280 case PIO_DEADKEYMAP: /* set accent key translation table */ 1281 KBDMUX_LOCK(state); 1282 state->ks_accents = 0; 1283 1284 /* perform command on all slave keyboards */ 1285 SLIST_FOREACH(k, &state->ks_kbds, next) 1286 (void)kbdd_ioctl(k->kbd, cmd, arg); 1287 1288 KBDMUX_UNLOCK(state); 1289 /* FALLTHROUGH */ 1290 1291 default: 1292 error = genkbd_commonioctl(kbd, cmd, arg); 1293 break; 1294 } 1295 1296 return (error); 1297} 1298 1299/* 1300 * Lock the access to the keyboard 1301 */ 1302static int 1303kbdmux_lock(keyboard_t *kbd, int lock) 1304{ 1305 return (1); /* XXX */ 1306} 1307 1308/* 1309 * Clear the internal state of the keyboard 1310 */ 1311static void 1312kbdmux_clear_state_locked(kbdmux_state_t *state) 1313{ 1314 KBDMUX_LOCK_ASSERT(state, MA_OWNED); 1315 1316 state->ks_flags &= ~COMPOSE; 1317 state->ks_polling = 0; 1318 state->ks_state &= LOCK_MASK; /* preserve locking key state */ 1319 state->ks_accents = 0; 1320 state->ks_composed_char = 0; 1321/* state->ks_prefix = 0; XXX */ 1322 state->ks_inq_length = 0; 1323} 1324 1325static void 1326kbdmux_clear_state(keyboard_t *kbd) 1327{ 1328 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 1329 1330 KBDMUX_LOCK(state); 1331 kbdmux_clear_state_locked(state); 1332 KBDMUX_UNLOCK(state); 1333} 1334 1335/* 1336 * Save the internal state 1337 */ 1338static int 1339kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len) 1340{ 1341 if (len == 0) 1342 return (sizeof(kbdmux_state_t)); 1343 if (len < sizeof(kbdmux_state_t)) 1344 return (-1); 1345 1346 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */ 1347 1348 return (0); 1349} 1350 1351/* 1352 * Set the internal state 1353 */ 1354static int 1355kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len) 1356{ 1357 if (len < sizeof(kbdmux_state_t)) 1358 return (ENOMEM); 1359 1360 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */ 1361 1362 return (0); 1363} 1364 1365/* 1366 * Set polling 1367 */ 1368static int 1369kbdmux_poll(keyboard_t *kbd, int on) 1370{ 1371 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 1372 kbdmux_kbd_t *k; 1373 1374 KBDMUX_LOCK(state); 1375 1376 if (on) 1377 state->ks_polling++; 1378 else 1379 state->ks_polling--; 1380 1381 /* set poll on slave keyboards */ 1382 SLIST_FOREACH(k, &state->ks_kbds, next) 1383 kbdd_poll(k->kbd, on); 1384 1385 KBDMUX_UNLOCK(state); 1386 1387 return (0); 1388} 1389 1390/***************************************************************************** 1391 ***************************************************************************** 1392 ** Module 1393 ***************************************************************************** 1394 *****************************************************************************/ 1395 1396KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure); 1397 1398static int 1399kbdmux_modevent(module_t mod, int type, void *data) 1400{ 1401 keyboard_switch_t *sw; 1402 keyboard_t *kbd; 1403 int error; 1404 1405 switch (type) { 1406 case MOD_LOAD: 1407 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0) 1408 break; 1409 1410 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) { 1411 kbd_delete_driver(&kbdmux_kbd_driver); 1412 error = ENXIO; 1413 break; 1414 } 1415 1416 kbd = NULL; 1417 1418 if ((error = (*sw->probe)(0, NULL, 0)) != 0 || 1419 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) { 1420 kbd_delete_driver(&kbdmux_kbd_driver); 1421 break; 1422 } 1423 1424#ifdef KBD_INSTALL_CDEV 1425 if ((error = kbd_attach(kbd)) != 0) { 1426 (*sw->term)(kbd); 1427 kbd_delete_driver(&kbdmux_kbd_driver); 1428 break; 1429 } 1430#endif 1431 1432 if ((error = (*sw->enable)(kbd)) != 0) { 1433 (*sw->disable)(kbd); 1434#ifdef KBD_INSTALL_CDEV 1435 kbd_detach(kbd); 1436#endif 1437 (*sw->term)(kbd); 1438 kbd_delete_driver(&kbdmux_kbd_driver); 1439 break; 1440 } 1441 break; 1442 1443 case MOD_UNLOAD: 1444 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) 1445 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL"); 1446 1447 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0)); 1448 if (kbd != NULL) { 1449 (*sw->disable)(kbd); 1450#ifdef KBD_INSTALL_CDEV 1451 kbd_detach(kbd); 1452#endif 1453 (*sw->term)(kbd); 1454 kbd_delete_driver(&kbdmux_kbd_driver); 1455 } 1456 error = 0; 1457 break; 1458 1459 default: 1460 error = EOPNOTSUPP; 1461 break; 1462 } 1463 1464 return (error); 1465} 1466 1467DEV_MODULE(kbdmux, kbdmux_modevent, NULL); 1468#ifdef EVDEV_SUPPORT 1469MODULE_DEPEND(kbdmux, evdev, 1, 1, 1); 1470#endif 1471