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