1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Generic keyboard support: streams and administration. 29 */ 30 31 #define KEYMAP_SIZE_VARIABLE 32 33 #include <sys/types.h> 34 #include <sys/cred.h> 35 #include <sys/stream.h> 36 #include <sys/stropts.h> 37 #include <sys/strsun.h> 38 #include <sys/ddi.h> 39 #include <sys/vuid_event.h> 40 #include <sys/modctl.h> 41 #include <sys/errno.h> 42 #include <sys/kmem.h> 43 #include <sys/cmn_err.h> 44 #include <sys/kbd.h> 45 #include <sys/kbio.h> 46 #include <sys/consdev.h> 47 #include <sys/kbtrans.h> 48 #include <sys/policy.h> 49 #include <sys/sunldi.h> 50 #include "kbtrans_lower.h" 51 #include "kbtrans_streams.h" 52 53 #ifdef DEBUG 54 int kbtrans_errmask; 55 int kbtrans_errlevel; 56 #endif 57 58 #define KB_NR_FUNCKEYS 12 59 60 /* 61 * Repeat rates set in static variables so they can be tweeked with 62 * debugger. 63 */ 64 static int kbtrans_repeat_rate; 65 static int kbtrans_repeat_delay; 66 67 /* Printing message on q overflow */ 68 static int kbtrans_overflow_msg = 1; 69 70 /* 71 * This value corresponds approximately to max 10 fingers 72 */ 73 static int kbtrans_downs_size = 15; 74 75 /* 76 * modload support 77 */ 78 extern struct mod_ops mod_miscops; 79 80 static struct modlmisc modlmisc = { 81 &mod_miscops, /* Type of module */ 82 "kbtrans (key translation)" 83 }; 84 85 static struct modlinkage modlinkage = { 86 MODREV_1, (void *)&modlmisc, NULL 87 }; 88 89 int 90 _init(void) 91 { 92 return (mod_install(&modlinkage)); 93 } 94 95 int 96 _fini(void) 97 { 98 return (mod_remove(&modlinkage)); 99 } 100 101 int 102 _info(struct modinfo *modinfop) 103 { 104 return (mod_info(&modlinkage, modinfop)); 105 } 106 107 /* 108 * Internal Function Prototypes 109 */ 110 static char *kbtrans_strsetwithdecimal(char *, uint_t, uint_t); 111 static void kbtrans_set_translation_callback(struct kbtrans *); 112 static void kbtrans_reioctl(void *); 113 static void kbtrans_send_esc_event(char, struct kbtrans *); 114 static void kbtrans_keypressed(struct kbtrans *, uchar_t, Firm_event *, 115 ushort_t); 116 static void kbtrans_putbuf(char *, queue_t *); 117 static void kbtrans_cancelrpt(struct kbtrans *); 118 static void kbtrans_queuepress(struct kbtrans *, uchar_t, Firm_event *); 119 static void kbtrans_putcode(register struct kbtrans *, uint_t); 120 static void kbtrans_keyreleased(struct kbtrans *, uchar_t); 121 static void kbtrans_queueevent(struct kbtrans *, Firm_event *); 122 static void kbtrans_untrans_keypressed_raw(struct kbtrans *, kbtrans_key_t); 123 static void kbtrans_untrans_keyreleased_raw(struct kbtrans *, 124 kbtrans_key_t); 125 static void kbtrans_ascii_keypressed(struct kbtrans *, uint_t, 126 kbtrans_key_t, uint_t); 127 static void kbtrans_ascii_keyreleased(struct kbtrans *, kbtrans_key_t); 128 static void kbtrans_ascii_setup_repeat(struct kbtrans *, uint_t, 129 kbtrans_key_t); 130 static void kbtrans_trans_event_keypressed(struct kbtrans *, uint_t, 131 kbtrans_key_t, uint_t); 132 static void kbtrans_trans_event_keyreleased(struct kbtrans *, 133 kbtrans_key_t); 134 static void kbtrans_trans_event_setup_repeat(struct kbtrans *, uint_t, 135 kbtrans_key_t); 136 static void kbtrans_rpt(void *); 137 static void kbtrans_setled(struct kbtrans *); 138 static void kbtrans_flush(struct kbtrans *); 139 static enum kbtrans_message_response kbtrans_ioctl(struct kbtrans *upper, 140 mblk_t *mp); 141 static int kbtrans_setkey(struct kbtrans_lower *, struct kiockey *, 142 cred_t *); 143 static int kbtrans_getkey(struct kbtrans_lower *, struct kiockey *); 144 static int kbtrans_skey(struct kbtrans_lower *, struct kiockeymap *, 145 cred_t *cr); 146 static int kbtrans_gkey(struct kbtrans_lower *, struct kiockeymap *); 147 148 /* 149 * Keyboard Translation Mode (TR_NONE) 150 * 151 * Functions to be called when keyboard translation is turned off 152 * and up/down key codes are reported. 153 */ 154 struct keyboard_callback untrans_event_callback = { 155 kbtrans_untrans_keypressed_raw, 156 kbtrans_untrans_keyreleased_raw, 157 NULL, 158 NULL, 159 NULL, 160 NULL, 161 NULL, 162 }; 163 164 /* 165 * Keyboard Translation Mode (TR_ASCII) 166 * 167 * Functions to be called when ISO 8859/1 codes are reported 168 */ 169 struct keyboard_callback ascii_callback = { 170 NULL, 171 NULL, 172 kbtrans_ascii_keypressed, 173 kbtrans_ascii_keyreleased, 174 kbtrans_ascii_setup_repeat, 175 kbtrans_cancelrpt, 176 kbtrans_setled, 177 }; 178 179 /* 180 * Keyboard Translation Mode (TR_EVENT) 181 * 182 * Functions to be called when firm_events are reported. 183 */ 184 struct keyboard_callback trans_event_callback = { 185 NULL, 186 NULL, 187 kbtrans_trans_event_keypressed, 188 kbtrans_trans_event_keyreleased, 189 kbtrans_trans_event_setup_repeat, 190 kbtrans_cancelrpt, 191 kbtrans_setled, 192 }; 193 194 /* 195 * kbtrans_streams_init: 196 * Initialize the stream, keytables, callbacks, etc. 197 */ 198 int 199 kbtrans_streams_init( 200 queue_t *q, 201 int sflag, 202 cred_t *crp, 203 struct kbtrans_hardware *hw, 204 struct kbtrans_callbacks *hw_cb, 205 struct kbtrans **ret_kbd, 206 int initial_leds, 207 int initial_led_mask) 208 { 209 struct kbtrans *upper; 210 struct kbtrans_lower *lower; 211 int err; 212 213 /* 214 * Default to relatively generic tables. 215 */ 216 extern signed char kb_compose_map[]; 217 extern struct compose_sequence_t kb_compose_table[]; 218 extern struct fltaccent_sequence_t kb_fltaccent_table[]; 219 extern char keystringtab[][KTAB_STRLEN]; 220 extern unsigned char kb_numlock_table[]; 221 222 /* Set these up only once so that they could be changed from adb */ 223 if (!kbtrans_repeat_rate) { 224 kbtrans_repeat_rate = (hz+29)/30; 225 kbtrans_repeat_delay = hz/2; 226 } 227 228 /* 229 * Only allow open requests to succeed for privileged users. This 230 * necessary to prevent users from pushing the this module again 231 * on the stream associated with /dev/kbd. 232 */ 233 err = secpolicy_console(crp); 234 235 if (err != 0) { 236 return (err); 237 } 238 239 switch (sflag) { 240 241 case MODOPEN: 242 break; 243 244 case CLONEOPEN: 245 DPRINTF(PRINT_L1, PRINT_MASK_OPEN, (NULL, 246 "kbtrans_streams_init: Clone open not supported")); 247 248 return (EINVAL); 249 } 250 251 /* allocate keyboard state structure */ 252 upper = kmem_zalloc(sizeof (struct kbtrans), KM_SLEEP); 253 254 *ret_kbd = upper; 255 256 upper->kbtrans_polled_buf[0] = '\0'; 257 upper->kbtrans_polled_pending_chars = upper->kbtrans_polled_buf; 258 259 upper->kbtrans_streams_hw = hw; 260 upper->kbtrans_streams_hw_callbacks = hw_cb; 261 upper->kbtrans_streams_readq = q; 262 upper->kbtrans_streams_iocpending = NULL; 263 upper->kbtrans_streams_translatable = TR_CAN; 264 upper->kbtrans_overflow_cnt = 0; 265 upper->kbtrans_streams_translate_mode = TR_ASCII; 266 267 /* Set the translation callback based on the translation type */ 268 kbtrans_set_translation_callback(upper); 269 270 lower = &upper->kbtrans_lower; 271 272 /* 273 * Set defaults for relatively generic tables. 274 */ 275 lower->kbtrans_compose_map = kb_compose_map; 276 lower->kbtrans_compose_table = kb_compose_table; 277 lower->kbtrans_fltaccent_table = kb_fltaccent_table; 278 lower->kbtrans_numlock_table = kb_numlock_table; 279 lower->kbtrans_keystringtab = keystringtab; 280 281 lower->kbtrans_upper = upper; 282 lower->kbtrans_compat = 1; 283 284 /* 285 * We have a generic default for the LED state, and let the 286 * hardware-specific driver supply overrides. 287 */ 288 lower->kbtrans_led_state = 0; 289 lower->kbtrans_led_state &= ~initial_led_mask; 290 lower->kbtrans_led_state |= initial_leds; 291 lower->kbtrans_togglemask = 0; 292 293 if (lower->kbtrans_led_state & LED_CAPS_LOCK) 294 lower->kbtrans_togglemask |= CAPSMASK; 295 if (lower->kbtrans_led_state & LED_NUM_LOCK) 296 lower->kbtrans_togglemask |= NUMLOCKMASK; 297 298 #if defined(SCROLLMASK) 299 if (lower->kbtrans_led_state & LED_SCROLL_LOCK) 300 lower->kbtrans_togglemask |= SCROLLMASK; 301 #endif 302 303 lower->kbtrans_shiftmask = lower->kbtrans_togglemask; 304 305 upper->kbtrans_streams_vuid_addr.ascii = ASCII_FIRST; 306 upper->kbtrans_streams_vuid_addr.top = TOP_FIRST; 307 upper->kbtrans_streams_vuid_addr.vkey = VKEY_FIRST; 308 309 /* Allocate dynamic memory for downs table */ 310 upper->kbtrans_streams_num_downs_entries = kbtrans_downs_size; 311 upper->kbtrans_streams_downs_bytes = 312 (uint32_t)(kbtrans_downs_size * sizeof (Key_event)); 313 upper->kbtrans_streams_downs = 314 kmem_zalloc(upper->kbtrans_streams_downs_bytes, KM_SLEEP); 315 upper->kbtrans_streams_abortable = B_FALSE; 316 317 upper->kbtrans_streams_flags = KBTRANS_STREAMS_OPEN; 318 319 DPRINTF(PRINT_L1, PRINT_MASK_OPEN, (upper, "kbtrans_streams_init " 320 "exiting")); 321 return (0); 322 } 323 324 325 /* 326 * kbtrans_streams_fini: 327 * Free structures and uninitialize the stream 328 */ 329 int 330 kbtrans_streams_fini(struct kbtrans *upper) 331 { 332 /* 333 * Since we're about to destroy our private data, turn off 334 * our open flag first, so we don't accept any more input 335 * and try to use that data. 336 */ 337 upper->kbtrans_streams_flags = 0; 338 339 /* clear all timeouts */ 340 if (upper->kbtrans_streams_bufcallid) { 341 qunbufcall(upper->kbtrans_streams_readq, 342 upper->kbtrans_streams_bufcallid); 343 } 344 if (upper->kbtrans_streams_rptid) { 345 (void) quntimeout(upper->kbtrans_streams_readq, 346 upper->kbtrans_streams_rptid); 347 } 348 kmem_free(upper->kbtrans_streams_downs, 349 upper->kbtrans_streams_downs_bytes); 350 kmem_free(upper, sizeof (struct kbtrans)); 351 352 DPRINTF(PRINT_L1, PRINT_MASK_CLOSE, (upper, "kbtrans_streams_fini " 353 "exiting")); 354 return (0); 355 } 356 357 /* 358 * kbtrans_streams_releaseall : 359 * This function releases all the held keys. 360 */ 361 void 362 kbtrans_streams_releaseall(struct kbtrans *upper) 363 { 364 register struct key_event *ke; 365 register int i; 366 367 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "USBKBM RELEASE ALL\n")); 368 369 /* Scan table of down key stations */ 370 for (i = 0, ke = upper->kbtrans_streams_downs; 371 i < upper->kbtrans_streams_num_downs_entries; i++, ke++) { 372 373 /* Key station not zero */ 374 if (ke->key_station) { 375 376 kbtrans_keyreleased(upper, ke->key_station); 377 /* kbtrans_keyreleased resets downs entry */ 378 } 379 } 380 } 381 382 /* 383 * kbtrans_streams_message: 384 * keyboard module output queue put procedure: handles M_IOCTL 385 * messages. 386 * 387 * Return KBTRANS_MESSAGE_HANDLED if the message was handled by 388 * kbtrans and KBTRANS_MESSAGE_NOT_HANDLED otherwise. If 389 * KBTRANS_MESSAGE_HANDLED is returned, no further action is required. 390 * If KBTRANS_MESSAGE_NOT_HANDLED is returned, the hardware module 391 * is responsible for any action. 392 */ 393 enum kbtrans_message_response 394 kbtrans_streams_message(struct kbtrans *upper, register mblk_t *mp) 395 { 396 queue_t *q = upper->kbtrans_streams_readq; 397 enum kbtrans_message_response ret; 398 399 DPRINTF(PRINT_L1, PRINT_MASK_ALL, (upper, 400 "kbtrans_streams_message entering")); 401 /* 402 * Process M_FLUSH, and some M_IOCTL, messages here; pass 403 * everything else down. 404 */ 405 switch (mp->b_datap->db_type) { 406 407 case M_IOCTL: 408 ret = kbtrans_ioctl(upper, mp); 409 break; 410 411 case M_FLUSH: 412 if (*mp->b_rptr & FLUSHW) 413 flushq(q, FLUSHDATA); 414 if (*mp->b_rptr & FLUSHR) 415 flushq(RD(q), FLUSHDATA); 416 /* 417 * White lie: we say we didn't handle the message, 418 * so that it gets handled by our client. 419 */ 420 ret = KBTRANS_MESSAGE_NOT_HANDLED; 421 break; 422 423 default: 424 ret = KBTRANS_MESSAGE_NOT_HANDLED; 425 break; 426 427 } 428 DPRINTF(PRINT_L1, PRINT_MASK_ALL, (upper, 429 "kbtrans_streams_message exiting\n")); 430 431 return (ret); 432 } 433 434 /* 435 * kbtrans_streams_key: 436 * When a key is pressed or released, the hardware module should 437 * call kbtrans, passing the key number and its new 438 * state. kbtrans is responsible for autorepeat handling; 439 * the hardware module should report only actual press/release 440 * events, suppressing any hardware-generated autorepeat. 441 */ 442 void 443 kbtrans_streams_key( 444 struct kbtrans *upper, 445 kbtrans_key_t key, 446 enum keystate state) 447 { 448 struct kbtrans_lower *lower; 449 struct keyboard *kp; 450 451 static int attempt_one_reset = 1; 452 453 lower = &upper->kbtrans_lower; 454 kp = lower->kbtrans_keyboard; 455 456 /* trigger switch back to text mode */ 457 if (attempt_one_reset == 1) { 458 ldi_ident_t li; 459 extern void progressbar_key_abort(ldi_ident_t); 460 461 if (ldi_ident_from_stream(upper->kbtrans_streams_readq, &li) 462 != 0) { 463 cmn_err(CE_NOTE, "!ldi_ident_from_stream failed"); 464 } else { 465 progressbar_key_abort(li); 466 ldi_ident_release(li); 467 } 468 attempt_one_reset = 0; 469 } 470 471 if (upper->kbtrans_streams_abortable) { 472 switch (upper->kbtrans_streams_abort_state) { 473 case ABORT_NORMAL: 474 if (state != KEY_PRESSED) 475 break; 476 477 if (key == (kbtrans_key_t)kp->k_abort1 || 478 key == (kbtrans_key_t)kp->k_abort1a) { 479 upper->kbtrans_streams_abort_state = 480 ABORT_ABORT1_RECEIVED; 481 upper->kbtrans_streams_abort1_key = key; 482 return; 483 } 484 /* Shift key needs to be sent to upper immediately */ 485 if (key == (kbtrans_key_t)kp->k_newabort1 || 486 key == (kbtrans_key_t)kp->k_newabort1a) { 487 upper->kbtrans_streams_abort_state = 488 NEW_ABORT_ABORT1_RECEIVED; 489 upper->kbtrans_streams_new_abort1_key = key; 490 } 491 break; 492 case ABORT_ABORT1_RECEIVED: 493 upper->kbtrans_streams_abort_state = ABORT_NORMAL; 494 if (state == KEY_PRESSED && 495 key == (kbtrans_key_t)kp->k_abort2) { 496 abort_sequence_enter((char *)NULL); 497 return; 498 } else { 499 kbtrans_processkey(lower, 500 upper->kbtrans_streams_callback, 501 upper->kbtrans_streams_abort1_key, 502 KEY_PRESSED); 503 } 504 break; 505 case NEW_ABORT_ABORT1_RECEIVED: 506 upper->kbtrans_streams_abort_state = ABORT_NORMAL; 507 if (state == KEY_PRESSED && 508 key == (kbtrans_key_t)kp->k_newabort2) { 509 abort_sequence_enter((char *)NULL); 510 kbtrans_processkey(lower, 511 upper->kbtrans_streams_callback, 512 upper->kbtrans_streams_new_abort1_key, 513 KEY_RELEASED); 514 return; 515 } 516 } 517 } 518 519 kbtrans_processkey(lower, upper->kbtrans_streams_callback, key, state); 520 } 521 522 /* 523 * kbtrans_streams_set_keyboard: 524 * At any time after calling kbtrans_streams_init, the hardware 525 * module should make this call to report the id of the keyboard 526 * attached. id is the keyboard type, typically KB_SUN4, 527 * KB_PC, or KB_USB. 528 */ 529 void 530 kbtrans_streams_set_keyboard( 531 struct kbtrans *upper, 532 int id, 533 struct keyboard *k) 534 { 535 upper->kbtrans_lower.kbtrans_keyboard = k; 536 upper->kbtrans_streams_id = id; 537 } 538 539 /* 540 * kbtrans_streams_has_reset: 541 * At any time between kbtrans_streams_init and kbtrans_streams_fini, 542 * the hardware module can call this routine to report that the 543 * keyboard has been reset, e.g. by being unplugged and reattached. 544 */ 545 /*ARGSUSED*/ 546 void 547 kbtrans_streams_has_reset(struct kbtrans *upper) 548 { 549 /* 550 * If this routine is implemented it should probably (a) 551 * simulate releases of all pressed keys and (b) call 552 * the hardware module to set the LEDs. 553 */ 554 } 555 556 /* 557 * kbtrans_streams_enable: 558 * This is the routine that is called back when the the stream is ready 559 * to take messages. 560 */ 561 void 562 kbtrans_streams_enable(struct kbtrans *upper) 563 { 564 /* Set the LED's */ 565 kbtrans_setled(upper); 566 } 567 568 /* 569 * kbtrans_streams_setled(): 570 * This is the routine that is called to only update the led state 571 * in kbtrans. 572 */ 573 void 574 kbtrans_streams_setled(struct kbtrans *upper, int led_state) 575 { 576 struct kbtrans_lower *lower; 577 578 lower = &upper->kbtrans_lower; 579 lower->kbtrans_led_state = (uchar_t)led_state; 580 581 if (lower->kbtrans_led_state & LED_CAPS_LOCK) 582 lower->kbtrans_togglemask |= CAPSMASK; 583 if (lower->kbtrans_led_state & LED_NUM_LOCK) 584 lower->kbtrans_togglemask |= NUMLOCKMASK; 585 586 #if defined(SCROLLMASK) 587 if (lower->kbtrans_led_state & LED_SCROLL_LOCK) 588 lower->kbtrans_togglemask |= SCROLLMASK; 589 #endif 590 591 lower->kbtrans_shiftmask = lower->kbtrans_togglemask; 592 593 } 594 595 /* 596 * kbtrans_streams_set_queue: 597 * Set the overlying queue, to support multiplexors. 598 */ 599 void 600 kbtrans_streams_set_queue(struct kbtrans *upper, queue_t *q) 601 { 602 603 upper->kbtrans_streams_readq = q; 604 } 605 606 /* 607 * kbtrans_streams_get_queue: 608 * Return the overlying queue. 609 */ 610 queue_t * 611 kbtrans_streams_get_queue(struct kbtrans *upper) 612 { 613 return (upper->kbtrans_streams_readq); 614 } 615 616 /* 617 * kbtrans_streams_untimeout 618 * Cancell all timeout 619 */ 620 void 621 kbtrans_streams_untimeout(struct kbtrans *upper) 622 { 623 /* clear all timeouts */ 624 if (upper->kbtrans_streams_bufcallid) { 625 qunbufcall(upper->kbtrans_streams_readq, 626 upper->kbtrans_streams_bufcallid); 627 upper->kbtrans_streams_bufcallid = 0; 628 } 629 if (upper->kbtrans_streams_rptid) { 630 (void) quntimeout(upper->kbtrans_streams_readq, 631 upper->kbtrans_streams_rptid); 632 upper->kbtrans_streams_rptid = 0; 633 } 634 } 635 636 /* 637 * kbtrans_reioctl: 638 * This function is set up as call-back function should an ioctl fail 639 * to allocate required resources. 640 */ 641 static void 642 kbtrans_reioctl(void *arg) 643 { 644 struct kbtrans *upper = (struct kbtrans *)arg; 645 mblk_t *mp; 646 647 upper->kbtrans_streams_bufcallid = 0; 648 649 if ((mp = upper->kbtrans_streams_iocpending) != NULL) { 650 /* not pending any more */ 651 upper->kbtrans_streams_iocpending = NULL; 652 (void) kbtrans_ioctl(upper, mp); 653 } 654 } 655 656 /* 657 * kbtrans_ioctl: 658 * process ioctls we recognize and own. Otherwise, pass it down. 659 */ 660 static enum kbtrans_message_response 661 kbtrans_ioctl(struct kbtrans *upper, register mblk_t *mp) 662 { 663 register struct iocblk *iocp; 664 register short new_translate; 665 register Vuid_addr_probe *addr_probe; 666 register short *addr_ptr; 667 size_t ioctlrespsize; 668 int err = 0; 669 struct kbtrans_lower *lower; 670 mblk_t *datap; 671 int translate; 672 673 static int kiocgetkey, kiocsetkey; 674 675 lower = &upper->kbtrans_lower; 676 677 iocp = (struct iocblk *)mp->b_rptr; 678 679 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, 680 "kbtrans_ioctl: ioc_cmd 0x%x - ", iocp->ioc_cmd)); 681 switch (iocp->ioc_cmd) { 682 683 case VUIDSFORMAT: 684 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSFORMAT\n")); 685 686 err = miocpullup(mp, sizeof (int)); 687 if (err != 0) 688 break; 689 new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ? 690 TR_ASCII : TR_EVENT; 691 692 if (new_translate == upper->kbtrans_streams_translate_mode) 693 break; 694 upper->kbtrans_streams_translate_mode = new_translate; 695 696 kbtrans_set_translation_callback(upper); 697 698 kbtrans_flush(upper); 699 break; 700 701 case KIOCTRANS: 702 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANS\n")); 703 err = miocpullup(mp, sizeof (int)); 704 if (err != 0) 705 break; 706 new_translate = *(int *)mp->b_cont->b_rptr; 707 if (new_translate == upper->kbtrans_streams_translate_mode) 708 break; 709 upper->kbtrans_streams_translate_mode = new_translate; 710 kbtrans_set_translation_callback(upper); 711 712 kbtrans_flush(upper); 713 break; 714 715 case KIOCSLED: 716 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSLED\n")); 717 718 err = miocpullup(mp, sizeof (uchar_t)); 719 if (err != 0) 720 break; 721 lower->kbtrans_led_state = *(uchar_t *)mp->b_cont->b_rptr; 722 723 kbtrans_setled(upper); 724 break; 725 726 case KIOCGLED: 727 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGLED\n")); 728 if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) { 729 ioctlrespsize = sizeof (int); 730 goto allocfailure; 731 } 732 733 *(uchar_t *)datap->b_wptr = lower->kbtrans_led_state; 734 datap->b_wptr += sizeof (uchar_t); 735 if (mp->b_cont) 736 freemsg(mp->b_cont); 737 mp->b_cont = datap; 738 iocp->ioc_count = sizeof (uchar_t); 739 break; 740 741 case VUIDGFORMAT: 742 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGFORMAT\n")); 743 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 744 ioctlrespsize = sizeof (int); 745 goto allocfailure; 746 } 747 *(int *)datap->b_wptr = 748 (upper->kbtrans_streams_translate_mode == TR_EVENT || 749 upper->kbtrans_streams_translate_mode == TR_UNTRANS_EVENT) ? 750 VUID_FIRM_EVENT: VUID_NATIVE; 751 datap->b_wptr += sizeof (int); 752 if (mp->b_cont) /* free msg to prevent memory leak */ 753 freemsg(mp->b_cont); 754 mp->b_cont = datap; 755 iocp->ioc_count = sizeof (int); 756 break; 757 758 case KIOCGTRANS: 759 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANS\n")); 760 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 761 ioctlrespsize = sizeof (int); 762 goto allocfailure; 763 } 764 *(int *)datap->b_wptr = upper->kbtrans_streams_translate_mode; 765 datap->b_wptr += sizeof (int); 766 if (mp->b_cont) /* free msg to prevent memory leak */ 767 freemsg(mp->b_cont); 768 mp->b_cont = datap; 769 iocp->ioc_count = sizeof (int); 770 break; 771 772 case VUIDSADDR: 773 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSADDR\n")); 774 775 err = miocpullup(mp, sizeof (Vuid_addr_probe)); 776 if (err != 0) 777 break; 778 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 779 switch (addr_probe->base) { 780 781 case ASCII_FIRST: 782 addr_ptr = &upper->kbtrans_streams_vuid_addr.ascii; 783 break; 784 785 case TOP_FIRST: 786 addr_ptr = &upper->kbtrans_streams_vuid_addr.top; 787 break; 788 789 case VKEY_FIRST: 790 addr_ptr = &upper->kbtrans_streams_vuid_addr.vkey; 791 break; 792 793 default: 794 err = ENODEV; 795 } 796 797 if ((err == 0) && (*addr_ptr != addr_probe->data.next)) { 798 *addr_ptr = addr_probe->data.next; 799 kbtrans_flush(upper); 800 } 801 break; 802 803 case VUIDGADDR: 804 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGADDR\n")); 805 806 err = miocpullup(mp, sizeof (Vuid_addr_probe)); 807 if (err != 0) 808 break; 809 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 810 switch (addr_probe->base) { 811 812 case ASCII_FIRST: 813 addr_probe->data.current = 814 upper->kbtrans_streams_vuid_addr.ascii; 815 break; 816 817 case TOP_FIRST: 818 addr_probe->data.current = 819 upper->kbtrans_streams_vuid_addr.top; 820 break; 821 822 case VKEY_FIRST: 823 addr_probe->data.current = 824 upper->kbtrans_streams_vuid_addr.vkey; 825 break; 826 827 default: 828 err = ENODEV; 829 } 830 break; 831 832 case KIOCTRANSABLE: 833 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANSABLE\n")); 834 835 err = miocpullup(mp, sizeof (int)); 836 if (err != 0) 837 break; 838 /* 839 * called during console setup in kbconfig() 840 * If set to false, means we are a serial keyboard, 841 * and we should pass all data up without modification. 842 */ 843 translate = *(int *)mp->b_cont->b_rptr; 844 if (upper->kbtrans_streams_translatable != translate) 845 upper->kbtrans_streams_translatable = translate; 846 847 if (translate != TR_CAN) 848 DPRINTF(PRINT_L4, PRINT_MASK_ALL, (upper, 849 "Cannot translate keyboard using tables.\n")); 850 break; 851 852 case KIOCGTRANSABLE: 853 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANSABLE\n")); 854 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 855 ioctlrespsize = sizeof (int); 856 goto allocfailure; 857 } 858 *(int *)datap->b_wptr = upper->kbtrans_streams_translatable; 859 datap->b_wptr += sizeof (int); 860 if (mp->b_cont) /* free msg to prevent memory leak */ 861 freemsg(mp->b_cont); 862 mp->b_cont = datap; 863 iocp->ioc_count = sizeof (int); 864 break; 865 866 case KIOCSCOMPAT: 867 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSCOMPAT\n")); 868 869 err = miocpullup(mp, sizeof (int)); 870 if (err != 0) 871 break; 872 lower->kbtrans_compat = *(int *)mp->b_cont->b_rptr; 873 break; 874 875 case KIOCGCOMPAT: 876 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGCOMPAT\n")); 877 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 878 ioctlrespsize = sizeof (int); 879 goto allocfailure; 880 } 881 *(int *)datap->b_wptr = lower->kbtrans_compat; 882 datap->b_wptr += sizeof (int); 883 if (mp->b_cont) /* free msg to prevent memory leak */ 884 freemsg(mp->b_cont); 885 mp->b_cont = datap; 886 iocp->ioc_count = sizeof (int); 887 break; 888 889 case KIOCSETKEY: 890 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSETKEY %d\n", 891 kiocsetkey++)); 892 err = miocpullup(mp, sizeof (struct kiockey)); 893 if (err != 0) 894 break; 895 err = kbtrans_setkey(&upper->kbtrans_lower, 896 (struct kiockey *)mp->b_cont->b_rptr, iocp->ioc_cr); 897 /* 898 * Since this only affects any subsequent key presses, 899 * don't flush soft state. One might want to 900 * toggle the keytable entries dynamically. 901 */ 902 break; 903 904 case KIOCGETKEY: 905 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGETKEY %d\n", 906 kiocgetkey++)); 907 err = miocpullup(mp, sizeof (struct kiockey)); 908 if (err != 0) 909 break; 910 err = kbtrans_getkey(&upper->kbtrans_lower, 911 (struct kiockey *)mp->b_cont->b_rptr); 912 break; 913 914 case KIOCSKEY: 915 err = miocpullup(mp, sizeof (struct kiockeymap)); 916 if (err != 0) 917 break; 918 err = kbtrans_skey(&upper->kbtrans_lower, 919 (struct kiockeymap *)mp->b_cont->b_rptr, iocp->ioc_cr); 920 /* 921 * Since this only affects any subsequent key presses, 922 * don't flush soft state. One might want to 923 * toggle the keytable entries dynamically. 924 */ 925 break; 926 927 case KIOCGKEY: 928 err = miocpullup(mp, sizeof (struct kiockeymap)); 929 if (err != 0) 930 break; 931 err = kbtrans_gkey(&upper->kbtrans_lower, 932 (struct kiockeymap *)mp->b_cont->b_rptr); 933 break; 934 935 case KIOCSDIRECT: 936 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSDIRECT\n")); 937 kbtrans_flush(upper); 938 break; 939 940 case KIOCGDIRECT: 941 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSGDIRECT\n")); 942 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 943 ioctlrespsize = sizeof (int); 944 goto allocfailure; 945 } 946 *(int *)datap->b_wptr = 1; /* always direct */ 947 datap->b_wptr += sizeof (int); 948 if (mp->b_cont) /* free msg to prevent memory leak */ 949 freemsg(mp->b_cont); 950 mp->b_cont = datap; 951 iocp->ioc_count = sizeof (int); 952 break; 953 954 case KIOCTYPE: 955 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTYPE\n")); 956 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 957 ioctlrespsize = sizeof (int); 958 goto allocfailure; 959 } 960 *(int *)datap->b_wptr = upper->kbtrans_streams_id; 961 datap->b_wptr += sizeof (int); 962 if (mp->b_cont) /* free msg to prevent memory leak */ 963 freemsg(mp->b_cont); 964 mp->b_cont = datap; 965 iocp->ioc_count = sizeof (int); 966 break; 967 968 case CONSSETABORTENABLE: 969 /* 970 * Peek as it goes by; must be a TRANSPARENT ioctl. 971 */ 972 if (iocp->ioc_count != TRANSPARENT) { 973 err = EINVAL; 974 break; 975 } 976 977 upper->kbtrans_streams_abortable = 978 (boolean_t)*(intptr_t *)mp->b_cont->b_rptr; 979 980 /* 981 * Let the hardware module see it too. 982 */ 983 return (KBTRANS_MESSAGE_NOT_HANDLED); 984 985 case KIOCGRPTDELAY: 986 /* 987 * Report the autorepeat delay, unit in millisecond 988 */ 989 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTDELAY\n")); 990 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 991 ioctlrespsize = sizeof (int); 992 goto allocfailure; 993 } 994 *(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_delay); 995 datap->b_wptr += sizeof (int); 996 997 /* free msg to prevent memory leak */ 998 if (mp->b_cont != NULL) 999 freemsg(mp->b_cont); 1000 mp->b_cont = datap; 1001 iocp->ioc_count = sizeof (int); 1002 break; 1003 1004 case KIOCSRPTDELAY: 1005 /* 1006 * Set the autorepeat delay 1007 */ 1008 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTDELAY\n")); 1009 err = miocpullup(mp, sizeof (int)); 1010 1011 if (err != 0) 1012 break; 1013 1014 /* validate the input */ 1015 if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) { 1016 err = EINVAL; 1017 break; 1018 } 1019 kbtrans_repeat_delay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 1020 if (kbtrans_repeat_delay <= 0) 1021 kbtrans_repeat_delay = 1; 1022 break; 1023 1024 case KIOCGRPTRATE: 1025 /* 1026 * Report the autorepeat rate 1027 */ 1028 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTRATE\n")); 1029 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 1030 ioctlrespsize = sizeof (int); 1031 goto allocfailure; 1032 } 1033 *(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_rate); 1034 datap->b_wptr += sizeof (int); 1035 1036 /* free msg to prevent memory leak */ 1037 if (mp->b_cont != NULL) 1038 freemsg(mp->b_cont); 1039 mp->b_cont = datap; 1040 iocp->ioc_count = sizeof (int); 1041 break; 1042 1043 case KIOCSRPTRATE: 1044 /* 1045 * Set the autorepeat rate 1046 */ 1047 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTRATE\n")); 1048 err = miocpullup(mp, sizeof (int)); 1049 1050 if (err != 0) 1051 break; 1052 1053 /* validate the input */ 1054 if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) { 1055 err = EINVAL; 1056 break; 1057 } 1058 kbtrans_repeat_rate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 1059 if (kbtrans_repeat_rate <= 0) 1060 kbtrans_repeat_rate = 1; 1061 break; 1062 1063 default: 1064 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "unknown\n")); 1065 return (KBTRANS_MESSAGE_NOT_HANDLED); 1066 } /* end switch */ 1067 1068 if (err != 0) { 1069 iocp->ioc_rval = 0; 1070 iocp->ioc_error = err; 1071 mp->b_datap->db_type = M_IOCNAK; 1072 } else { 1073 iocp->ioc_rval = 0; 1074 iocp->ioc_error = 0; /* brain rot */ 1075 mp->b_datap->db_type = M_IOCACK; 1076 } 1077 putnext(upper->kbtrans_streams_readq, mp); 1078 1079 return (KBTRANS_MESSAGE_HANDLED); 1080 1081 allocfailure: 1082 /* 1083 * We needed to allocate something to handle this "ioctl", but 1084 * couldn't; save this "ioctl" and arrange to get called back when 1085 * it's more likely that we can get what we need. 1086 * If there's already one being saved, throw it out, since it 1087 * must have timed out. 1088 */ 1089 if (upper->kbtrans_streams_iocpending != NULL) 1090 freemsg(upper->kbtrans_streams_iocpending); 1091 upper->kbtrans_streams_iocpending = mp; 1092 if (upper->kbtrans_streams_bufcallid) { 1093 qunbufcall(upper->kbtrans_streams_readq, 1094 upper->kbtrans_streams_bufcallid); 1095 } 1096 upper->kbtrans_streams_bufcallid = 1097 qbufcall(upper->kbtrans_streams_readq, ioctlrespsize, BPRI_HI, 1098 kbtrans_reioctl, upper); 1099 /* 1100 * This is a white lie... we *will* handle it, eventually. 1101 */ 1102 return (KBTRANS_MESSAGE_HANDLED); 1103 } 1104 1105 /* 1106 * kbtrans_flush: 1107 * Flush data upstream 1108 */ 1109 static void 1110 kbtrans_flush(register struct kbtrans *upper) 1111 { 1112 register queue_t *q; 1113 1114 /* Flush pending data already sent upstream */ 1115 if ((q = upper->kbtrans_streams_readq) != NULL && q->q_next != NULL) 1116 (void) putnextctl1(q, M_FLUSH, FLUSHR); 1117 1118 /* Flush pending ups */ 1119 bzero(upper->kbtrans_streams_downs, upper->kbtrans_streams_downs_bytes); 1120 1121 kbtrans_cancelrpt(upper); 1122 } 1123 1124 /* 1125 * kbtrans_setled: 1126 * Update the keyboard LEDs to match the current keyboard state. 1127 */ 1128 static void 1129 kbtrans_setled(struct kbtrans *upper) 1130 { 1131 upper->kbtrans_streams_hw_callbacks->kbtrans_streams_setled( 1132 upper->kbtrans_streams_hw, 1133 upper->kbtrans_lower.kbtrans_led_state); 1134 } 1135 1136 /* 1137 * kbtrans_rpt: 1138 * If a key is held down, this function is set up to be called 1139 * after kbtrans_repeat_rate time elapses. 1140 */ 1141 static void 1142 kbtrans_rpt(void *arg) 1143 { 1144 struct kbtrans *upper = arg; 1145 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1146 1147 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, 1148 "kbtrans_rpt: repeat key %X\n", 1149 lower->kbtrans_repeatkey)); 1150 1151 upper->kbtrans_streams_rptid = 0; 1152 1153 /* 1154 * NB: polled code zaps kbtrans_repeatkey without cancelling 1155 * timeout. 1156 */ 1157 if (lower->kbtrans_repeatkey != 0) { 1158 kbtrans_keyreleased(upper, lower->kbtrans_repeatkey); 1159 1160 kbtrans_processkey(lower, 1161 upper->kbtrans_streams_callback, 1162 lower->kbtrans_repeatkey, 1163 KEY_PRESSED); 1164 1165 upper->kbtrans_streams_rptid = 1166 qtimeout(upper->kbtrans_streams_readq, kbtrans_rpt, 1167 (caddr_t)upper, kbtrans_repeat_rate); 1168 } 1169 } 1170 1171 /* 1172 * kbtrans_cancelrpt: 1173 * Cancel the repeating key 1174 */ 1175 static void 1176 kbtrans_cancelrpt(struct kbtrans *upper) 1177 { 1178 upper->kbtrans_lower.kbtrans_repeatkey = 0; 1179 1180 if (upper->kbtrans_streams_rptid != 0) { 1181 (void) quntimeout(upper->kbtrans_streams_readq, 1182 upper->kbtrans_streams_rptid); 1183 upper->kbtrans_streams_rptid = 0; 1184 } 1185 } 1186 1187 /* 1188 * kbtrans_send_esc_event: 1189 * Send character up stream. Used for the case of 1190 * sending strings upstream. 1191 */ 1192 static void 1193 kbtrans_send_esc_event(char c, register struct kbtrans *upper) 1194 { 1195 Firm_event fe; 1196 1197 fe.id = c; 1198 fe.value = 1; 1199 fe.pair_type = FE_PAIR_NONE; 1200 fe.pair = 0; 1201 /* 1202 * Pretend as if each cp pushed and released 1203 * Calling kbtrans_queueevent avoids addr translation 1204 * and pair base determination of kbtrans_keypressed. 1205 */ 1206 kbtrans_queueevent(upper, &fe); 1207 fe.value = 0; 1208 kbtrans_queueevent(upper, &fe); 1209 } 1210 1211 /* 1212 * kbtrans_strsetwithdecimal: 1213 * Used for expanding a function key to the ascii equivalent 1214 */ 1215 static char * 1216 kbtrans_strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs) 1217 { 1218 int hradix = 5; 1219 char *bp; 1220 int lowbit; 1221 char *tab = "0123456789abcdef"; 1222 1223 bp = buf + maxdigs; 1224 *(--bp) = '\0'; 1225 while (val) { 1226 lowbit = val & 1; 1227 val = (val >> 1); 1228 *(--bp) = tab[val % hradix * 2 + lowbit]; 1229 val /= hradix; 1230 } 1231 return (bp); 1232 } 1233 1234 /* 1235 * kbtrans_keypressed: 1236 * Modify Firm event to be sent up the stream 1237 */ 1238 static void 1239 kbtrans_keypressed(struct kbtrans *upper, uchar_t key_station, 1240 Firm_event *fe, ushort_t base) 1241 { 1242 1243 register short id_addr; 1244 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1245 1246 /* Set pair values */ 1247 if (fe->id < (ushort_t)VKEY_FIRST) { 1248 /* 1249 * If CTRLed, find the ID that would have been used had it 1250 * not been CTRLed. 1251 */ 1252 if (lower->kbtrans_shiftmask & (CTRLMASK | CTLSMASK)) { 1253 unsigned short *ke; 1254 unsigned int mask; 1255 1256 mask = lower->kbtrans_shiftmask & 1257 ~(CTRLMASK | CTLSMASK | UPMASK); 1258 1259 ke = kbtrans_find_entry(lower, mask, key_station); 1260 if (ke == NULL) 1261 return; 1262 1263 base = *ke; 1264 } 1265 if (base != fe->id) { 1266 fe->pair_type = FE_PAIR_SET; 1267 fe->pair = (uchar_t)base; 1268 1269 goto send; 1270 } 1271 } 1272 fe->pair_type = FE_PAIR_NONE; 1273 fe->pair = 0; 1274 1275 send: 1276 /* Adjust event id address for multiple keyboard/workstation support */ 1277 switch (vuid_id_addr(fe->id)) { 1278 case ASCII_FIRST: 1279 id_addr = upper->kbtrans_streams_vuid_addr.ascii; 1280 break; 1281 case TOP_FIRST: 1282 id_addr = upper->kbtrans_streams_vuid_addr.top; 1283 break; 1284 case VKEY_FIRST: 1285 id_addr = upper->kbtrans_streams_vuid_addr.vkey; 1286 break; 1287 default: 1288 id_addr = vuid_id_addr(fe->id); 1289 break; 1290 } 1291 fe->id = vuid_id_offset(fe->id) | id_addr; 1292 1293 kbtrans_queuepress(upper, key_station, fe); 1294 } 1295 1296 /* 1297 * kbtrans_queuepress: 1298 * Add keypress to the "downs" table 1299 */ 1300 static void 1301 kbtrans_queuepress(struct kbtrans *upper, 1302 uchar_t key_station, Firm_event *fe) 1303 { 1304 register struct key_event *ke, *ke_free; 1305 register int i; 1306 1307 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "kbtrans_queuepress:" 1308 " key=%d", key_station)); 1309 1310 ke_free = 0; 1311 1312 /* Scan table of down key stations */ 1313 1314 for (i = 0, ke = upper->kbtrans_streams_downs; 1315 i < upper->kbtrans_streams_num_downs_entries; i++, ke++) { 1316 1317 /* Keycode already down? */ 1318 if (ke->key_station == key_station) { 1319 1320 DPRINTF(PRINT_L0, PRINT_MASK_ALL, 1321 (NULL, "kbtrans: Double " 1322 "entry in downs table (%d,%d)!\n", 1323 key_station, i)); 1324 1325 goto add_event; 1326 } 1327 1328 if (ke->key_station == 0) 1329 ke_free = ke; 1330 } 1331 1332 if (ke_free) { 1333 ke = ke_free; 1334 goto add_event; 1335 } 1336 1337 ke = upper->kbtrans_streams_downs; 1338 1339 add_event: 1340 ke->key_station = key_station; 1341 ke->event = *fe; 1342 kbtrans_queueevent(upper, fe); 1343 } 1344 1345 /* 1346 * kbtrans_keyreleased: 1347 * Remove entry from the downs table 1348 */ 1349 static void 1350 kbtrans_keyreleased(register struct kbtrans *upper, uchar_t key_station) 1351 { 1352 register struct key_event *ke; 1353 register int i; 1354 1355 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "RELEASE key=%d\n", 1356 key_station)); 1357 1358 if (upper->kbtrans_streams_translate_mode != TR_EVENT && 1359 upper->kbtrans_streams_translate_mode != TR_UNTRANS_EVENT) { 1360 1361 return; 1362 } 1363 1364 /* Scan table of down key stations */ 1365 for (i = 0, ke = upper->kbtrans_streams_downs; 1366 i < upper->kbtrans_streams_num_downs_entries; 1367 i++, ke++) { 1368 /* Found? */ 1369 if (ke->key_station == key_station) { 1370 ke->key_station = 0; 1371 ke->event.value = 0; 1372 kbtrans_queueevent(upper, &ke->event); 1373 } 1374 } 1375 1376 /* 1377 * Ignore if couldn't find because may be called twice 1378 * for the same key station in the case of the kbtrans_rpt 1379 * routine being called unnecessarily. 1380 */ 1381 } 1382 1383 1384 /* 1385 * kbtrans_putcode: 1386 * Pass a keycode up the stream, if you can, otherwise throw it away. 1387 */ 1388 static void 1389 kbtrans_putcode(register struct kbtrans *upper, uint_t code) 1390 { 1391 register mblk_t *bp; 1392 1393 /* 1394 * If we can't send it up, then we just drop it. 1395 */ 1396 if (!canputnext(upper->kbtrans_streams_readq)) { 1397 1398 return; 1399 } 1400 1401 /* 1402 * Allocate a messsage block to send up. 1403 */ 1404 if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) { 1405 1406 cmn_err(CE_WARN, "kbtrans_putcode: Can't allocate block\ 1407 for keycode."); 1408 1409 return; 1410 } 1411 1412 /* 1413 * We will strip out any high order information here. 1414 */ 1415 /* NOTE the implicit cast here */ 1416 *bp->b_wptr++ = (uchar_t)code; 1417 1418 /* 1419 * Send the message up. 1420 */ 1421 (void) putnext(upper->kbtrans_streams_readq, bp); 1422 } 1423 1424 1425 /* 1426 * kbtrans_putbuf: 1427 * Pass generated keycode sequence to upstream, if possible. 1428 */ 1429 static void 1430 kbtrans_putbuf(char *buf, queue_t *q) 1431 { 1432 register mblk_t *bp; 1433 1434 if (!canputnext(q)) { 1435 cmn_err(CE_WARN, "kbtrans_putbuf: Can't put block for keycode"); 1436 } else { 1437 if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) { 1438 cmn_err(CE_WARN, "kbtrans_putbuf: " 1439 "Can't allocate block for keycode"); 1440 } else { 1441 while (*buf) { 1442 *bp->b_wptr++ = *buf; 1443 buf++; 1444 } 1445 putnext(q, bp); 1446 } 1447 } 1448 } 1449 1450 /* 1451 * kbtrans_queueevent: 1452 * Pass a VUID "firm event" up the stream, if you can. 1453 */ 1454 static void 1455 kbtrans_queueevent(struct kbtrans *upper, Firm_event *fe) 1456 { 1457 register queue_t *q; 1458 register mblk_t *bp; 1459 1460 if ((q = upper->kbtrans_streams_readq) == NULL) 1461 1462 return; 1463 1464 if (!canputnext(q)) { 1465 if (kbtrans_overflow_msg) { 1466 DPRINTF(PRINT_L2, PRINT_MASK_ALL, (NULL, 1467 "kbtrans: Buffer flushed when overflowed.")); 1468 } 1469 1470 kbtrans_flush(upper); 1471 upper->kbtrans_overflow_cnt++; 1472 } else { 1473 if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) { 1474 cmn_err(CE_WARN, "kbtrans_queueevent: Can't allocate \ 1475 block for event."); 1476 } else { 1477 uniqtime32(&fe->time); 1478 *(Firm_event *)bp->b_wptr = *fe; 1479 bp->b_wptr += sizeof (Firm_event); 1480 (void) putnext(q, bp); 1481 1482 1483 } 1484 } 1485 } 1486 1487 /* 1488 * kbtrans_set_translation_callback: 1489 * This code sets the translation_callback pointer based on the 1490 * translation mode. 1491 */ 1492 static void 1493 kbtrans_set_translation_callback(register struct kbtrans *upper) 1494 { 1495 switch (upper->kbtrans_streams_translate_mode) { 1496 1497 default: 1498 case TR_ASCII: 1499 upper->vt_switch_keystate = VT_SWITCH_KEY_NONE; 1500 1501 /* Discard any obsolete CTRL/ALT/SHIFT keys */ 1502 upper->kbtrans_lower.kbtrans_shiftmask &= 1503 ~(CTRLMASK | ALTMASK | SHIFTMASK); 1504 upper->kbtrans_lower.kbtrans_togglemask &= 1505 ~(CTRLMASK | ALTMASK | SHIFTMASK); 1506 1507 upper->kbtrans_streams_callback = &ascii_callback; 1508 1509 break; 1510 1511 case TR_EVENT: 1512 upper->kbtrans_streams_callback = &trans_event_callback; 1513 1514 break; 1515 1516 case TR_UNTRANS_EVENT: 1517 upper->kbtrans_streams_callback = &untrans_event_callback; 1518 1519 break; 1520 } 1521 } 1522 1523 /* 1524 * kbtrans_untrans_keypressed_raw: 1525 * This is the callback we get if we are in TR_UNTRANS_EVENT and a 1526 * key is pressed. This code will just send the scancode up the 1527 * stream. 1528 */ 1529 static void 1530 kbtrans_untrans_keypressed_raw(struct kbtrans *upper, kbtrans_key_t key) 1531 { 1532 Firm_event fe; 1533 1534 bzero(&fe, sizeof (fe)); 1535 1536 /* 1537 * fill in the event 1538 */ 1539 fe.id = (unsigned short)key; 1540 fe.value = 1; 1541 1542 /* 1543 * Send the event upstream. 1544 */ 1545 kbtrans_queuepress(upper, key, &fe); 1546 } 1547 1548 /* 1549 * kbtrans_untrans_keyreleased_raw: 1550 * This is the callback we get if we are in TR_UNTRANS_EVENT mode 1551 * and a key is released. This code will just send the scancode up 1552 * the stream. 1553 */ 1554 static void 1555 kbtrans_untrans_keyreleased_raw(struct kbtrans *upper, kbtrans_key_t key) 1556 { 1557 /* 1558 * Deal with a key released event. 1559 */ 1560 kbtrans_keyreleased(upper, key); 1561 } 1562 1563 /* 1564 * kbtrans_vt_compose: 1565 * To compose the key sequences for virtual terminal switching. 1566 * 1567 * 'ALTL + F#' for 1-12 terminals 1568 * 'ALTGR + F#' for 13-24 terminals 1569 * 'ALT + UPARROW' for last terminal 1570 * 'ALT + LEFTARROW' for previous terminal 1571 * 'ALT + RIGHTARROW' for next terminal 1572 * 1573 * the vt switching message is encoded as: 1574 * 1575 * ------------------------------------------------------------- 1576 * | \033 | 'Q' | vtno + 'A' | opcode | 'z' | '\0' | 1577 * ------------------------------------------------------------- 1578 * 1579 * opcode: 1580 * 'B' to switch to previous terminal 1581 * 'F' to switch to next terminal 1582 * 'L' to switch to last terminal 1583 * 'H' to switch to the terminal as specified by vtno, 1584 * which is from 1 to 24. 1585 * 1586 * Here keyid is the keycode of UPARROW, LEFTARROW, or RIGHTARROW 1587 * when it is a kind of arrow key as indicated by is_arrow_key, 1588 * otherwise it indicates a function key and keyid is the number 1589 * corresponding to that function key. 1590 */ 1591 static void 1592 kbtrans_vt_compose(struct kbtrans *upper, unsigned short keyid, 1593 boolean_t is_arrow_key, char *buf) 1594 { 1595 char *bufp; 1596 1597 bufp = buf; 1598 *bufp++ = '\033'; /* Escape */ 1599 *bufp++ = 'Q'; 1600 if (is_arrow_key) { 1601 *bufp++ = 'A'; 1602 switch (keyid) { 1603 case UPARROW: /* last vt */ 1604 *bufp++ = 'L'; 1605 break; 1606 case LEFTARROW: /* previous vt */ 1607 *bufp++ = 'B'; 1608 break; 1609 case RIGHTARROW: /* next vt */ 1610 *bufp++ = 'F'; 1611 break; 1612 default: 1613 break; 1614 } 1615 } else { 1616 /* this is funckey specifying vtno for switch */ 1617 *bufp++ = keyid + 1618 (upper->vt_switch_keystate - VT_SWITCH_KEY_ALT) * 1619 KB_NR_FUNCKEYS + 'A'; 1620 *bufp++ = 'H'; 1621 } 1622 *bufp++ = 'z'; 1623 *bufp = '\0'; 1624 1625 /* 1626 * Send the result upstream. 1627 */ 1628 kbtrans_putbuf(buf, upper->kbtrans_streams_readq); 1629 1630 } 1631 1632 /* 1633 * kbtrans_ascii_keypressed: 1634 * This is the code if we are in TR_ASCII mode and a key 1635 * is pressed. This is where we will do any special processing that 1636 * is specific to ASCII key translation. 1637 */ 1638 /* ARGSUSED */ 1639 static void 1640 kbtrans_ascii_keypressed( 1641 struct kbtrans *upper, 1642 uint_t entrytype, 1643 kbtrans_key_t key, 1644 uint_t entry) 1645 { 1646 register char *cp; 1647 register char *bufp; 1648 char buf[14]; 1649 unsigned short keyid; 1650 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1651 1652 /* 1653 * Based on the type of key, we may need to do some ASCII 1654 * specific post processing. Note that the translated entry 1655 * is constructed as the actual keycode plus entrytype. see 1656 * sys/kbd.h for details of each entrytype. 1657 */ 1658 switch (entrytype) { 1659 1660 case BUCKYBITS: 1661 return; 1662 1663 case SHIFTKEYS: 1664 keyid = entry & 0xFF; 1665 if (keyid == ALT) { 1666 upper->vt_switch_keystate = VT_SWITCH_KEY_ALT; 1667 } else if (keyid == ALTGRAPH) { 1668 upper->vt_switch_keystate = VT_SWITCH_KEY_ALTGR; 1669 } 1670 return; 1671 1672 case FUNNY: 1673 /* 1674 * There is no ascii equivalent. We will ignore these 1675 * keys 1676 */ 1677 return; 1678 1679 case FUNCKEYS: 1680 if (upper->vt_switch_keystate > VT_SWITCH_KEY_NONE) { 1681 if (entry >= TOPFUNC && 1682 entry < (TOPFUNC + KB_NR_FUNCKEYS)) { 1683 1684 /* 1685 * keyid is the number correspoding to F# 1686 * and its value is from 1 to 12. 1687 */ 1688 keyid = (entry & 0xF) + 1; 1689 1690 kbtrans_vt_compose(upper, keyid, B_FALSE, buf); 1691 return; 1692 } 1693 } 1694 1695 /* 1696 * We need to expand this key to get the ascii 1697 * equivalent. These are the function keys (F1, F2 ...) 1698 */ 1699 bufp = buf; 1700 cp = kbtrans_strsetwithdecimal(bufp + 2, 1701 (uint_t)((entry & 0x003F) + 192), 1702 sizeof (buf) - 5); 1703 *bufp++ = '\033'; /* Escape */ 1704 *bufp++ = '['; 1705 while (*cp != '\0') 1706 *bufp++ = *cp++; 1707 *bufp++ = 'z'; 1708 *bufp = '\0'; 1709 1710 /* 1711 * Send the result upstream. 1712 */ 1713 kbtrans_putbuf(buf, upper->kbtrans_streams_readq); 1714 1715 return; 1716 1717 case STRING: 1718 if (upper->vt_switch_keystate > VT_SWITCH_KEY_NONE) { 1719 keyid = entry & 0xFF; 1720 if (keyid == UPARROW || 1721 keyid == RIGHTARROW || 1722 keyid == LEFTARROW) { 1723 1724 kbtrans_vt_compose(upper, keyid, B_TRUE, buf); 1725 return; 1726 } 1727 } 1728 1729 /* 1730 * These are the multi byte keys (Home, Up, Down ...) 1731 */ 1732 cp = &lower->kbtrans_keystringtab[entry & 0x0F][0]; 1733 1734 /* 1735 * Copy the string from the keystringtable, and send it 1736 * upstream a character at a time. 1737 */ 1738 while (*cp != '\0') { 1739 1740 kbtrans_putcode(upper, (uchar_t)*cp); 1741 1742 cp++; 1743 } 1744 1745 return; 1746 1747 case PADKEYS: 1748 /* 1749 * These are the keys on the keypad. Look up the 1750 * answer in the kb_numlock_table and send it upstream. 1751 */ 1752 kbtrans_putcode(upper, 1753 lower->kbtrans_numlock_table[entry&0x1F]); 1754 1755 return; 1756 1757 case 0: /* normal character */ 1758 default: 1759 break; 1760 } 1761 1762 /* 1763 * Send the byte upstream. 1764 */ 1765 kbtrans_putcode(upper, entry); 1766 1767 } 1768 1769 #define KB_SCANCODE_ALT 0xe2 1770 #define KB_SCANCODE_ALTGRAPH 0xe6 1771 1772 /* 1773 * kbtrans_ascii_keyreleased: 1774 * This is the function if we are in TR_ASCII mode and a key 1775 * is released. ASCII doesn't have the concept of released keys, 1776 * or make/break codes. So there is nothing for us to do except 1777 * checking 'Alt/AltGraph' release key in order to reset the state 1778 * of vt switch key sequence. 1779 */ 1780 /* ARGSUSED */ 1781 static void 1782 kbtrans_ascii_keyreleased(struct kbtrans *upper, kbtrans_key_t key) 1783 { 1784 if (key == KB_SCANCODE_ALT || key == KB_SCANCODE_ALTGRAPH) { 1785 upper->vt_switch_keystate = VT_SWITCH_KEY_NONE; 1786 } 1787 } 1788 1789 /* 1790 * kbtrans_ascii_setup_repeat: 1791 * This is the function if we are in TR_ASCII mode and the 1792 * translation module has decided that a key needs to be repeated. 1793 */ 1794 /* ARGSUSED */ 1795 static void 1796 kbtrans_ascii_setup_repeat( 1797 struct kbtrans *upper, 1798 uint_t entrytype, 1799 kbtrans_key_t key) 1800 { 1801 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1802 1803 /* 1804 * Cancel any currently repeating keys. This will be a new 1805 * key to repeat. 1806 */ 1807 kbtrans_cancelrpt(upper); 1808 1809 /* 1810 * Set the value of the key to be repeated. 1811 */ 1812 lower->kbtrans_repeatkey = key; 1813 1814 /* 1815 * Start the timeout for repeating this key. kbtrans_rpt will 1816 * be called to repeat the key. 1817 */ 1818 upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq, 1819 kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay); 1820 } 1821 1822 /* 1823 * kbtrans_trans_event_keypressed: 1824 * This is the function if we are in TR_EVENT mode and a key 1825 * is pressed. This is where we will do any special processing that 1826 * is specific to EVENT key translation. 1827 */ 1828 static void 1829 kbtrans_trans_event_keypressed( 1830 struct kbtrans *upper, 1831 uint_t entrytype, 1832 kbtrans_key_t key, 1833 uint_t entry) 1834 { 1835 Firm_event fe; 1836 register char *cp; 1837 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1838 1839 /* 1840 * Based on the type of key, we may need to do some EVENT 1841 * specific post processing. 1842 */ 1843 switch (entrytype) { 1844 1845 case SHIFTKEYS: 1846 /* 1847 * Relying on ordinal correspondence between 1848 * vuid_event.h SHIFT_META-SHIFT_TOP & 1849 * kbd.h METABIT-SYSTEMBIT in order to 1850 * correctly translate entry into fe.id. 1851 */ 1852 fe.id = SHIFT_CAPSLOCK + (entry & 0x0F); 1853 fe.value = 1; 1854 kbtrans_keypressed(upper, key, &fe, fe.id); 1855 1856 return; 1857 1858 case BUCKYBITS: 1859 /* 1860 * Relying on ordinal correspondence between 1861 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL & 1862 * kbd.h CAPSLOCK-RIGHTCTRL in order to 1863 * correctly translate entry into fe.id. 1864 */ 1865 fe.id = SHIFT_META + (entry & 0x0F); 1866 fe.value = 1; 1867 kbtrans_keypressed(upper, key, &fe, fe.id); 1868 1869 return; 1870 1871 case FUNCKEYS: 1872 /* 1873 * Take advantage of the similar 1874 * ordering of kbd.h function keys and 1875 * vuid_event.h function keys to do a 1876 * simple translation to achieve a 1877 * mapping between the 2 different 1878 * address spaces. 1879 */ 1880 fe.id = KEY_LEFTFIRST + (entry & 0x003F); 1881 fe.value = 1; 1882 1883 /* 1884 * Assume "up" table only generates 1885 * shift changes. 1886 */ 1887 kbtrans_keypressed(upper, key, &fe, fe.id); 1888 1889 /* 1890 * Function key events can be expanded 1891 * by terminal emulator software to 1892 * produce the standard escape sequence 1893 * generated by the TR_ASCII case above 1894 * if a function key event is not used 1895 * by terminal emulator software 1896 * directly. 1897 */ 1898 return; 1899 1900 case STRING: 1901 /* 1902 * These are the multi byte keys (Home, Up, Down ...) 1903 */ 1904 cp = &lower->kbtrans_keystringtab[entry & 0x0F][0]; 1905 1906 /* 1907 * Copy the string from the keystringtable, and send it 1908 * upstream a character at a time. 1909 */ 1910 while (*cp != '\0') { 1911 1912 kbtrans_send_esc_event(*cp, upper); 1913 1914 cp++; 1915 } 1916 1917 return; 1918 1919 case PADKEYS: 1920 /* 1921 * Take advantage of the similar 1922 * ordering of kbd.h keypad keys and 1923 * vuid_event.h keypad keys to do a 1924 * simple translation to achieve a 1925 * mapping between the 2 different 1926 * address spaces. 1927 */ 1928 fe.id = VKEY_FIRSTPAD + (entry & 0x001F); 1929 fe.value = 1; 1930 1931 /* 1932 * Assume "up" table only generates 1933 * shift changes. 1934 */ 1935 kbtrans_keypressed(upper, key, &fe, fe.id); 1936 1937 /* 1938 * Keypad key events can be expanded 1939 * by terminal emulator software to 1940 * produce the standard ascii character 1941 * generated by the TR_ASCII case above 1942 * if a keypad key event is not used 1943 * by terminal emulator software 1944 * directly. 1945 */ 1946 return; 1947 1948 case FUNNY: 1949 /* 1950 * These are not events. 1951 */ 1952 switch (entry) { 1953 case IDLE: 1954 case RESET: 1955 case ERROR: 1956 /* 1957 * Something has happened. Mark all keys as released. 1958 */ 1959 kbtrans_streams_releaseall(upper); 1960 break; 1961 } 1962 1963 return; 1964 1965 case 0: /* normal character */ 1966 default: 1967 break; 1968 } 1969 1970 /* 1971 * Send the event upstream. 1972 */ 1973 fe.id = entry; 1974 1975 fe.value = 1; 1976 1977 kbtrans_queueevent(upper, &fe); 1978 } 1979 1980 /* 1981 * kbtrans_trans_event_keyreleased: 1982 * This is the function if we are in TR_EVENT mode and a key 1983 * is released. 1984 */ 1985 /* ARGSUSED */ 1986 static void 1987 kbtrans_trans_event_keyreleased(struct kbtrans *upper, kbtrans_key_t key) 1988 { 1989 /* 1990 * Mark the key as released and send an event upstream. 1991 */ 1992 kbtrans_keyreleased(upper, key); 1993 } 1994 1995 /* 1996 * kbtrans_trans_event_setup_repeat: 1997 * This is the function if we are in TR_EVENT mode and the 1998 * translation module has decided that a key needs to be repeated. 1999 * We will set a timeout to retranslate the repeat key. 2000 */ 2001 static void 2002 kbtrans_trans_event_setup_repeat( 2003 struct kbtrans *upper, 2004 uint_t entrytype, 2005 kbtrans_key_t key) 2006 { 2007 struct kbtrans_lower *lower = &upper->kbtrans_lower; 2008 2009 /* 2010 * Function keys and keypad keys do not repeat when we are in 2011 * EVENT mode. 2012 */ 2013 if (entrytype == FUNCKEYS || entrytype == PADKEYS) { 2014 2015 return; 2016 } 2017 2018 /* 2019 * Cancel any currently repeating keys. This will be a new 2020 * key to repeat. 2021 */ 2022 kbtrans_cancelrpt(upper); 2023 2024 /* 2025 * Set the value of the key to be repeated. 2026 */ 2027 lower->kbtrans_repeatkey = key; 2028 2029 /* 2030 * Start the timeout for repeating this key. kbtrans_rpt will 2031 * be called to repeat the key. 2032 */ 2033 upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq, 2034 kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay); 2035 } 2036 2037 /* 2038 * Administer the key tables. 2039 */ 2040 2041 /* 2042 * Old special codes. 2043 */ 2044 #define OLD_SHIFTKEYS 0x80 2045 #define OLD_BUCKYBITS 0x90 2046 #define OLD_FUNNY 0xA0 2047 #define OLD_FA_UMLAUT 0xA9 2048 #define OLD_FA_CFLEX 0xAA 2049 #define OLD_FA_TILDE 0xAB 2050 #define OLD_FA_CEDILLA 0xAC 2051 #define OLD_FA_ACUTE 0xAD 2052 #define OLD_FA_GRAVE 0xAE 2053 #define OLD_ISOCHAR 0xAF 2054 #define OLD_STRING 0xB0 2055 #define OLD_LEFTFUNC 0xC0 2056 #define OLD_RIGHTFUNC 0xD0 2057 #define OLD_TOPFUNC 0xE0 2058 #define OLD_BOTTOMFUNC 0xF0 2059 2060 /* 2061 * Map old special codes to new ones. 2062 * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F. 2063 */ 2064 static ushort_t special_old_to_new[] = { 2065 SHIFTKEYS, 2066 BUCKYBITS, 2067 FUNNY, 2068 STRING, 2069 LEFTFUNC, 2070 RIGHTFUNC, 2071 TOPFUNC, 2072 BOTTOMFUNC, 2073 }; 2074 2075 2076 /* 2077 * kbtrans_setkey: 2078 * Set individual keystation translation from old-style entry. 2079 */ 2080 static int 2081 kbtrans_setkey(struct kbtrans_lower *lower, struct kiockey *key, cred_t *cr) 2082 { 2083 int strtabindex, i; 2084 unsigned short *ke; 2085 register int tablemask; 2086 register ushort_t entry; 2087 register struct keyboard *kp; 2088 2089 kp = lower->kbtrans_keyboard; 2090 2091 if (key->kio_station >= kp->k_keymap_size) 2092 2093 return (EINVAL); 2094 2095 if (lower->kbtrans_keyboard == NULL) 2096 2097 return (EINVAL); 2098 2099 tablemask = key->kio_tablemask; 2100 2101 switch (tablemask) { 2102 case KIOCABORT1: 2103 case KIOCABORT1A: 2104 case KIOCABORT2: 2105 i = secpolicy_console(cr); 2106 if (i != 0) 2107 return (i); 2108 2109 switch (tablemask) { 2110 case KIOCABORT1: 2111 kp->k_abort1 = key->kio_station; 2112 break; 2113 case KIOCABORT1A: 2114 kp->k_abort1a = key->kio_station; 2115 break; 2116 case KIOCABORT2: 2117 kp->k_abort2 = key->kio_station; 2118 break; 2119 } 2120 return (0); 2121 } 2122 2123 if (tablemask & ALTGRAPHMASK) 2124 return (EINVAL); 2125 2126 ke = kbtrans_find_entry(lower, (uint_t)tablemask, key->kio_station); 2127 if (ke == NULL) 2128 return (EINVAL); 2129 2130 if (key->kio_entry >= (uchar_t)OLD_STRING && 2131 key->kio_entry <= (uchar_t)(OLD_STRING + 15)) { 2132 strtabindex = key->kio_entry - OLD_STRING; 2133 bcopy(key->kio_string, 2134 lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN); 2135 lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 2136 } 2137 2138 entry = key->kio_entry; 2139 2140 /* 2141 * There's nothing we need do with OLD_ISOCHAR. 2142 */ 2143 if (entry != OLD_ISOCHAR) { 2144 if (entry & 0x80) { 2145 if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE) 2146 entry = FA_CLASS + (entry & 0x0F) - 9; 2147 else 2148 entry = 2149 special_old_to_new[entry >> 4 & 0x07] 2150 + (entry & 0x0F); 2151 } 2152 } 2153 2154 *ke = entry; 2155 2156 return (0); 2157 } 2158 2159 2160 /* 2161 * Map new special codes to old ones. 2162 * Indexed by (new special code) >> 8; add (new special code) & 0xFF. 2163 */ 2164 static uchar_t special_new_to_old[] = { 2165 0, /* normal */ 2166 OLD_SHIFTKEYS, /* SHIFTKEYS */ 2167 OLD_BUCKYBITS, /* BUCKYBITS */ 2168 OLD_FUNNY, /* FUNNY */ 2169 OLD_FA_UMLAUT, /* FA_CLASS */ 2170 OLD_STRING, /* STRING */ 2171 OLD_LEFTFUNC, /* FUNCKEYS */ 2172 }; 2173 2174 2175 /* 2176 * kbtrans_getkey: 2177 * Get individual keystation translation as old-style entry. 2178 */ 2179 static int 2180 kbtrans_getkey(struct kbtrans_lower *lower, struct kiockey *key) 2181 { 2182 int strtabindex; 2183 unsigned short *ke; 2184 register ushort_t entry; 2185 struct keyboard *kp; 2186 2187 kp = lower->kbtrans_keyboard; 2188 2189 if (key->kio_station >= kp->k_keymap_size) 2190 return (EINVAL); 2191 2192 if (lower->kbtrans_keyboard == NULL) 2193 return (EINVAL); 2194 2195 switch (key->kio_tablemask) { 2196 case KIOCABORT1: 2197 key->kio_station = kp->k_abort1; 2198 return (0); 2199 case KIOCABORT1A: 2200 key->kio_station = kp->k_abort1a; 2201 return (0); 2202 case KIOCABORT2: 2203 key->kio_station = kp->k_abort2; 2204 return (0); 2205 } 2206 2207 ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask, 2208 key->kio_station); 2209 if (ke == NULL) 2210 return (EINVAL); 2211 2212 entry = *ke; 2213 2214 if (entry & 0xFF00) 2215 key->kio_entry = 2216 special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8] 2217 + (entry & 0x00FF); 2218 else { 2219 if (entry & 0x80) 2220 key->kio_entry = (ushort_t)OLD_ISOCHAR; /* you lose */ 2221 else 2222 key->kio_entry = (ushort_t)entry; 2223 } 2224 2225 if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) { 2226 strtabindex = entry - STRING; 2227 bcopy(lower->kbtrans_keystringtab[strtabindex], 2228 key->kio_string, KTAB_STRLEN); 2229 } 2230 return (0); 2231 } 2232 2233 2234 /* 2235 * kbtrans_skey: 2236 * Set individual keystation translation from new-style entry. 2237 */ 2238 static int 2239 kbtrans_skey(struct kbtrans_lower *lower, struct kiockeymap *key, cred_t *cr) 2240 { 2241 int strtabindex, i; 2242 unsigned short *ke; 2243 struct keyboard *kp; 2244 2245 kp = lower->kbtrans_keyboard; 2246 2247 if (key->kio_station >= kp->k_keymap_size) { 2248 return (EINVAL); 2249 2250 } 2251 2252 if (lower->kbtrans_keyboard == NULL) { 2253 return (EINVAL); 2254 } 2255 2256 switch (key->kio_tablemask) { 2257 case KIOCABORT1: 2258 case KIOCABORT1A: 2259 case KIOCABORT2: 2260 i = secpolicy_console(cr); 2261 if (i != 0) 2262 return (i); 2263 switch (key->kio_tablemask) { 2264 case KIOCABORT1: 2265 kp->k_abort1 = key->kio_station; 2266 break; 2267 case KIOCABORT1A: 2268 kp->k_abort1a = key->kio_station; 2269 break; 2270 case KIOCABORT2: 2271 kp->k_abort2 = key->kio_station; 2272 break; 2273 } 2274 return (0); 2275 } 2276 2277 ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask, 2278 key->kio_station); 2279 if (ke == NULL) 2280 return (EINVAL); 2281 2282 if (key->kio_entry >= STRING && 2283 key->kio_entry <= (ushort_t)(STRING + 15)) { 2284 strtabindex = key->kio_entry-STRING; 2285 bcopy(key->kio_string, 2286 lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN); 2287 lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 2288 } 2289 2290 *ke = key->kio_entry; 2291 2292 return (0); 2293 } 2294 2295 2296 /* 2297 * kbtrans_gkey: 2298 * Get individual keystation translation as new-style entry. 2299 */ 2300 static int 2301 kbtrans_gkey(struct kbtrans_lower *lower, struct kiockeymap *key) 2302 { 2303 int strtabindex; 2304 unsigned short *ke; 2305 struct keyboard *kp; 2306 2307 kp = lower->kbtrans_keyboard; 2308 2309 if (key->kio_station >= kp->k_keymap_size) 2310 return (EINVAL); 2311 2312 if (lower->kbtrans_keyboard == NULL) 2313 return (EINVAL); 2314 2315 switch (key->kio_tablemask) { 2316 case KIOCABORT1: 2317 key->kio_station = kp->k_abort1; 2318 return (0); 2319 case KIOCABORT1A: 2320 key->kio_station = kp->k_abort1a; 2321 return (0); 2322 case KIOCABORT2: 2323 key->kio_station = kp->k_abort2; 2324 return (0); 2325 } 2326 2327 ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask, 2328 key->kio_station); 2329 if (ke == NULL) 2330 return (EINVAL); 2331 2332 key->kio_entry = *ke; 2333 2334 if (key->kio_entry >= STRING && 2335 key->kio_entry <= (ushort_t)(STRING + 15)) { 2336 strtabindex = key->kio_entry-STRING; 2337 bcopy(lower->kbtrans_keystringtab[strtabindex], 2338 key->kio_string, KTAB_STRLEN); 2339 } 2340 return (0); 2341 } 2342