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 2007 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 467 if (key == (kbtrans_key_t)kp->k_newabort1 || 468 key == (kbtrans_key_t)kp->k_newabort1a) { 469 upper->kbtrans_streams_abort_state = 470 NEW_ABORT_ABORT1_RECEIVED; 471 upper->kbtrans_streams_new_abort1_key = key; 472 return; 473 } 474 475 break; 476 case ABORT_ABORT1_RECEIVED: 477 upper->kbtrans_streams_abort_state = ABORT_NORMAL; 478 if (state == KEY_PRESSED && 479 key == (kbtrans_key_t)kp->k_abort2) { 480 abort_sequence_enter((char *)NULL); 481 return; 482 } else { 483 kbtrans_processkey(lower, 484 upper->kbtrans_streams_callback, 485 upper->kbtrans_streams_abort1_key, 486 KEY_PRESSED); 487 } 488 break; 489 case NEW_ABORT_ABORT1_RECEIVED: 490 upper->kbtrans_streams_abort_state = ABORT_NORMAL; 491 if (state == KEY_PRESSED && 492 key == (kbtrans_key_t)kp->k_newabort2) { 493 abort_sequence_enter((char *)NULL); 494 return; 495 } else { 496 kbtrans_processkey(lower, 497 upper->kbtrans_streams_callback, 498 upper->kbtrans_streams_new_abort1_key, 499 KEY_PRESSED); 500 } 501 } 502 } 503 504 kbtrans_processkey(lower, upper->kbtrans_streams_callback, key, state); 505 } 506 507 /* 508 * kbtrans_streams_set_keyboard: 509 * At any time after calling kbtrans_streams_init, the hardware 510 * module should make this call to report the id of the keyboard 511 * attached. id is the keyboard type, typically KB_SUN4, 512 * KB_PC, or KB_USB. 513 */ 514 void 515 kbtrans_streams_set_keyboard( 516 struct kbtrans *upper, 517 int id, 518 struct keyboard *k) 519 { 520 upper->kbtrans_lower.kbtrans_keyboard = k; 521 upper->kbtrans_streams_id = id; 522 } 523 524 /* 525 * kbtrans_streams_has_reset: 526 * At any time between kbtrans_streams_init and kbtrans_streams_fini, 527 * the hardware module can call this routine to report that the 528 * keyboard has been reset, e.g. by being unplugged and reattached. 529 */ 530 /*ARGSUSED*/ 531 void 532 kbtrans_streams_has_reset(struct kbtrans *upper) 533 { 534 /* 535 * If this routine is implemented it should probably (a) 536 * simulate releases of all pressed keys and (b) call 537 * the hardware module to set the LEDs. 538 */ 539 } 540 541 /* 542 * kbtrans_streams_enable: 543 * This is the routine that is called back when the the stream is ready 544 * to take messages. 545 */ 546 void 547 kbtrans_streams_enable(struct kbtrans *upper) 548 { 549 /* Set the LED's */ 550 kbtrans_setled(upper); 551 } 552 553 /* 554 * kbtrans_streams_setled(): 555 * This is the routine that is called to only update the led state 556 * in kbtrans. 557 */ 558 void 559 kbtrans_streams_setled(struct kbtrans *upper, int led_state) 560 { 561 struct kbtrans_lower *lower; 562 563 lower = &upper->kbtrans_lower; 564 lower->kbtrans_led_state = (uchar_t)led_state; 565 566 if (lower->kbtrans_led_state & LED_CAPS_LOCK) 567 lower->kbtrans_togglemask |= CAPSMASK; 568 if (lower->kbtrans_led_state & LED_NUM_LOCK) 569 lower->kbtrans_togglemask |= NUMLOCKMASK; 570 571 #if defined(SCROLLMASK) 572 if (lower->kbtrans_led_state & LED_SCROLL_LOCK) 573 lower->kbtrans_togglemask |= SCROLLMASK; 574 #endif 575 576 lower->kbtrans_shiftmask = lower->kbtrans_togglemask; 577 578 } 579 580 /* 581 * kbtrans_streams_set_queue: 582 * Set the overlying queue, to support multiplexors. 583 */ 584 void 585 kbtrans_streams_set_queue(struct kbtrans *upper, queue_t *q) 586 { 587 588 upper->kbtrans_streams_readq = q; 589 } 590 591 /* 592 * kbtrans_streams_get_queue: 593 * Return the overlying queue. 594 */ 595 queue_t * 596 kbtrans_streams_get_queue(struct kbtrans *upper) 597 { 598 return (upper->kbtrans_streams_readq); 599 } 600 601 /* 602 * kbtrans_streams_untimeout 603 * Cancell all timeout 604 */ 605 void 606 kbtrans_streams_untimeout(struct kbtrans *upper) 607 { 608 /* clear all timeouts */ 609 if (upper->kbtrans_streams_bufcallid) { 610 qunbufcall(upper->kbtrans_streams_readq, 611 upper->kbtrans_streams_bufcallid); 612 upper->kbtrans_streams_bufcallid = 0; 613 } 614 if (upper->kbtrans_streams_rptid) { 615 (void) quntimeout(upper->kbtrans_streams_readq, 616 upper->kbtrans_streams_rptid); 617 upper->kbtrans_streams_rptid = 0; 618 } 619 } 620 621 /* 622 * kbtrans_reioctl: 623 * This function is set up as call-back function should an ioctl fail 624 * to allocate required resources. 625 */ 626 static void 627 kbtrans_reioctl(void *arg) 628 { 629 struct kbtrans *upper = (struct kbtrans *)arg; 630 mblk_t *mp; 631 632 upper->kbtrans_streams_bufcallid = 0; 633 634 if ((mp = upper->kbtrans_streams_iocpending) != NULL) { 635 /* not pending any more */ 636 upper->kbtrans_streams_iocpending = NULL; 637 (void) kbtrans_ioctl(upper, mp); 638 } 639 } 640 641 /* 642 * kbtrans_ioctl: 643 * process ioctls we recognize and own. Otherwise, pass it down. 644 */ 645 static enum kbtrans_message_response 646 kbtrans_ioctl(struct kbtrans *upper, register mblk_t *mp) 647 { 648 register struct iocblk *iocp; 649 register short new_translate; 650 register Vuid_addr_probe *addr_probe; 651 register short *addr_ptr; 652 size_t ioctlrespsize; 653 int err = 0; 654 struct kbtrans_lower *lower; 655 mblk_t *datap; 656 int translate; 657 658 static int kiocgetkey, kiocsetkey; 659 660 lower = &upper->kbtrans_lower; 661 662 iocp = (struct iocblk *)mp->b_rptr; 663 664 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, 665 "kbtrans_ioctl: ioc_cmd 0x%x - ", iocp->ioc_cmd)); 666 switch (iocp->ioc_cmd) { 667 668 case VUIDSFORMAT: 669 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSFORMAT\n")); 670 671 err = miocpullup(mp, sizeof (int)); 672 if (err != 0) 673 break; 674 new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ? 675 TR_ASCII : TR_EVENT; 676 677 if (new_translate == upper->kbtrans_streams_translate_mode) 678 break; 679 upper->kbtrans_streams_translate_mode = new_translate; 680 681 kbtrans_set_translation_callback(upper); 682 683 kbtrans_flush(upper); 684 break; 685 686 case KIOCTRANS: 687 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANS\n")); 688 err = miocpullup(mp, sizeof (int)); 689 if (err != 0) 690 break; 691 new_translate = *(int *)mp->b_cont->b_rptr; 692 if (new_translate == upper->kbtrans_streams_translate_mode) 693 break; 694 upper->kbtrans_streams_translate_mode = new_translate; 695 kbtrans_set_translation_callback(upper); 696 697 kbtrans_flush(upper); 698 break; 699 700 case KIOCSLED: 701 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSLED\n")); 702 703 err = miocpullup(mp, sizeof (uchar_t)); 704 if (err != 0) 705 break; 706 lower->kbtrans_led_state = *(uchar_t *)mp->b_cont->b_rptr; 707 708 kbtrans_setled(upper); 709 break; 710 711 case KIOCGLED: 712 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGLED\n")); 713 if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) { 714 ioctlrespsize = sizeof (int); 715 goto allocfailure; 716 } 717 718 *(uchar_t *)datap->b_wptr = lower->kbtrans_led_state; 719 datap->b_wptr += sizeof (uchar_t); 720 if (mp->b_cont) 721 freemsg(mp->b_cont); 722 mp->b_cont = datap; 723 iocp->ioc_count = sizeof (uchar_t); 724 break; 725 726 case VUIDGFORMAT: 727 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGFORMAT\n")); 728 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 729 ioctlrespsize = sizeof (int); 730 goto allocfailure; 731 } 732 *(int *)datap->b_wptr = 733 (upper->kbtrans_streams_translate_mode == TR_EVENT || 734 upper->kbtrans_streams_translate_mode == TR_UNTRANS_EVENT) ? 735 VUID_FIRM_EVENT: VUID_NATIVE; 736 datap->b_wptr += sizeof (int); 737 if (mp->b_cont) /* free msg to prevent memory leak */ 738 freemsg(mp->b_cont); 739 mp->b_cont = datap; 740 iocp->ioc_count = sizeof (int); 741 break; 742 743 case KIOCGTRANS: 744 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANS\n")); 745 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 746 ioctlrespsize = sizeof (int); 747 goto allocfailure; 748 } 749 *(int *)datap->b_wptr = upper->kbtrans_streams_translate_mode; 750 datap->b_wptr += sizeof (int); 751 if (mp->b_cont) /* free msg to prevent memory leak */ 752 freemsg(mp->b_cont); 753 mp->b_cont = datap; 754 iocp->ioc_count = sizeof (int); 755 break; 756 757 case VUIDSADDR: 758 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSADDR\n")); 759 760 err = miocpullup(mp, sizeof (Vuid_addr_probe)); 761 if (err != 0) 762 break; 763 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 764 switch (addr_probe->base) { 765 766 case ASCII_FIRST: 767 addr_ptr = &upper->kbtrans_streams_vuid_addr.ascii; 768 break; 769 770 case TOP_FIRST: 771 addr_ptr = &upper->kbtrans_streams_vuid_addr.top; 772 break; 773 774 case VKEY_FIRST: 775 addr_ptr = &upper->kbtrans_streams_vuid_addr.vkey; 776 break; 777 778 default: 779 err = ENODEV; 780 } 781 782 if ((err == 0) && (*addr_ptr != addr_probe->data.next)) { 783 *addr_ptr = addr_probe->data.next; 784 kbtrans_flush(upper); 785 } 786 break; 787 788 case VUIDGADDR: 789 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGADDR\n")); 790 791 err = miocpullup(mp, sizeof (Vuid_addr_probe)); 792 if (err != 0) 793 break; 794 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 795 switch (addr_probe->base) { 796 797 case ASCII_FIRST: 798 addr_probe->data.current = 799 upper->kbtrans_streams_vuid_addr.ascii; 800 break; 801 802 case TOP_FIRST: 803 addr_probe->data.current = 804 upper->kbtrans_streams_vuid_addr.top; 805 break; 806 807 case VKEY_FIRST: 808 addr_probe->data.current = 809 upper->kbtrans_streams_vuid_addr.vkey; 810 break; 811 812 default: 813 err = ENODEV; 814 } 815 break; 816 817 case KIOCTRANSABLE: 818 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANSABLE\n")); 819 820 err = miocpullup(mp, sizeof (int)); 821 if (err != 0) 822 break; 823 /* 824 * called during console setup in kbconfig() 825 * If set to false, means we are a serial keyboard, 826 * and we should pass all data up without modification. 827 */ 828 translate = *(int *)mp->b_cont->b_rptr; 829 if (upper->kbtrans_streams_translatable != translate) 830 upper->kbtrans_streams_translatable = translate; 831 832 if (translate != TR_CAN) 833 DPRINTF(PRINT_L4, PRINT_MASK_ALL, (upper, 834 "Cannot translate keyboard using tables.\n")); 835 break; 836 837 case KIOCGTRANSABLE: 838 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANSABLE\n")); 839 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 840 ioctlrespsize = sizeof (int); 841 goto allocfailure; 842 } 843 *(int *)datap->b_wptr = upper->kbtrans_streams_translatable; 844 datap->b_wptr += sizeof (int); 845 if (mp->b_cont) /* free msg to prevent memory leak */ 846 freemsg(mp->b_cont); 847 mp->b_cont = datap; 848 iocp->ioc_count = sizeof (int); 849 break; 850 851 case KIOCSCOMPAT: 852 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSCOMPAT\n")); 853 854 err = miocpullup(mp, sizeof (int)); 855 if (err != 0) 856 break; 857 lower->kbtrans_compat = *(int *)mp->b_cont->b_rptr; 858 break; 859 860 case KIOCGCOMPAT: 861 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGCOMPAT\n")); 862 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 863 ioctlrespsize = sizeof (int); 864 goto allocfailure; 865 } 866 *(int *)datap->b_wptr = lower->kbtrans_compat; 867 datap->b_wptr += sizeof (int); 868 if (mp->b_cont) /* free msg to prevent memory leak */ 869 freemsg(mp->b_cont); 870 mp->b_cont = datap; 871 iocp->ioc_count = sizeof (int); 872 break; 873 874 case KIOCSETKEY: 875 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSETKEY %d\n", 876 kiocsetkey++)); 877 err = miocpullup(mp, sizeof (struct kiockey)); 878 if (err != 0) 879 break; 880 err = kbtrans_setkey(&upper->kbtrans_lower, 881 (struct kiockey *)mp->b_cont->b_rptr, iocp->ioc_cr); 882 /* 883 * Since this only affects any subsequent key presses, 884 * don't flush soft state. One might want to 885 * toggle the keytable entries dynamically. 886 */ 887 break; 888 889 case KIOCGETKEY: 890 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGETKEY %d\n", 891 kiocgetkey++)); 892 err = miocpullup(mp, sizeof (struct kiockey)); 893 if (err != 0) 894 break; 895 err = kbtrans_getkey(&upper->kbtrans_lower, 896 (struct kiockey *)mp->b_cont->b_rptr); 897 break; 898 899 case KIOCSKEY: 900 err = miocpullup(mp, sizeof (struct kiockeymap)); 901 if (err != 0) 902 break; 903 err = kbtrans_skey(&upper->kbtrans_lower, 904 (struct kiockeymap *)mp->b_cont->b_rptr, iocp->ioc_cr); 905 /* 906 * Since this only affects any subsequent key presses, 907 * don't flush soft state. One might want to 908 * toggle the keytable entries dynamically. 909 */ 910 break; 911 912 case KIOCGKEY: 913 err = miocpullup(mp, sizeof (struct kiockeymap)); 914 if (err != 0) 915 break; 916 err = kbtrans_gkey(&upper->kbtrans_lower, 917 (struct kiockeymap *)mp->b_cont->b_rptr); 918 break; 919 920 case KIOCSDIRECT: 921 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSDIRECT\n")); 922 kbtrans_flush(upper); 923 break; 924 925 case KIOCGDIRECT: 926 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSGDIRECT\n")); 927 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 928 ioctlrespsize = sizeof (int); 929 goto allocfailure; 930 } 931 *(int *)datap->b_wptr = 1; /* always direct */ 932 datap->b_wptr += sizeof (int); 933 if (mp->b_cont) /* free msg to prevent memory leak */ 934 freemsg(mp->b_cont); 935 mp->b_cont = datap; 936 iocp->ioc_count = sizeof (int); 937 break; 938 939 case KIOCTYPE: 940 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTYPE\n")); 941 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 942 ioctlrespsize = sizeof (int); 943 goto allocfailure; 944 } 945 *(int *)datap->b_wptr = upper->kbtrans_streams_id; 946 datap->b_wptr += sizeof (int); 947 if (mp->b_cont) /* free msg to prevent memory leak */ 948 freemsg(mp->b_cont); 949 mp->b_cont = datap; 950 iocp->ioc_count = sizeof (int); 951 break; 952 953 case CONSSETABORTENABLE: 954 /* 955 * Peek as it goes by; must be a TRANSPARENT ioctl. 956 */ 957 if (iocp->ioc_count != TRANSPARENT) { 958 err = EINVAL; 959 break; 960 } 961 962 upper->kbtrans_streams_abortable = 963 (boolean_t)*(intptr_t *)mp->b_cont->b_rptr; 964 965 /* 966 * Let the hardware module see it too. 967 */ 968 return (KBTRANS_MESSAGE_NOT_HANDLED); 969 970 case KIOCGRPTDELAY: 971 /* 972 * Report the autorepeat delay, unit in millisecond 973 */ 974 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTDELAY\n")); 975 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 976 ioctlrespsize = sizeof (int); 977 goto allocfailure; 978 } 979 *(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_delay); 980 datap->b_wptr += sizeof (int); 981 982 /* free msg to prevent memory leak */ 983 if (mp->b_cont != NULL) 984 freemsg(mp->b_cont); 985 mp->b_cont = datap; 986 iocp->ioc_count = sizeof (int); 987 break; 988 989 case KIOCSRPTDELAY: 990 /* 991 * Set the autorepeat delay 992 */ 993 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTDELAY\n")); 994 err = miocpullup(mp, sizeof (int)); 995 996 if (err != 0) 997 break; 998 999 /* validate the input */ 1000 if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) { 1001 err = EINVAL; 1002 break; 1003 } 1004 kbtrans_repeat_delay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 1005 if (kbtrans_repeat_delay <= 0) 1006 kbtrans_repeat_delay = 1; 1007 break; 1008 1009 case KIOCGRPTRATE: 1010 /* 1011 * Report the autorepeat rate 1012 */ 1013 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTRATE\n")); 1014 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 1015 ioctlrespsize = sizeof (int); 1016 goto allocfailure; 1017 } 1018 *(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_rate); 1019 datap->b_wptr += sizeof (int); 1020 1021 /* free msg to prevent memory leak */ 1022 if (mp->b_cont != NULL) 1023 freemsg(mp->b_cont); 1024 mp->b_cont = datap; 1025 iocp->ioc_count = sizeof (int); 1026 break; 1027 1028 case KIOCSRPTRATE: 1029 /* 1030 * Set the autorepeat rate 1031 */ 1032 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTRATE\n")); 1033 err = miocpullup(mp, sizeof (int)); 1034 1035 if (err != 0) 1036 break; 1037 1038 /* validate the input */ 1039 if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) { 1040 err = EINVAL; 1041 break; 1042 } 1043 kbtrans_repeat_rate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 1044 if (kbtrans_repeat_rate <= 0) 1045 kbtrans_repeat_rate = 1; 1046 break; 1047 1048 default: 1049 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "unknown\n")); 1050 return (KBTRANS_MESSAGE_NOT_HANDLED); 1051 } /* end switch */ 1052 1053 if (err != 0) { 1054 iocp->ioc_rval = 0; 1055 iocp->ioc_error = err; 1056 mp->b_datap->db_type = M_IOCNAK; 1057 } else { 1058 iocp->ioc_rval = 0; 1059 iocp->ioc_error = 0; /* brain rot */ 1060 mp->b_datap->db_type = M_IOCACK; 1061 } 1062 putnext(upper->kbtrans_streams_readq, mp); 1063 1064 return (KBTRANS_MESSAGE_HANDLED); 1065 1066 allocfailure: 1067 /* 1068 * We needed to allocate something to handle this "ioctl", but 1069 * couldn't; save this "ioctl" and arrange to get called back when 1070 * it's more likely that we can get what we need. 1071 * If there's already one being saved, throw it out, since it 1072 * must have timed out. 1073 */ 1074 if (upper->kbtrans_streams_iocpending != NULL) 1075 freemsg(upper->kbtrans_streams_iocpending); 1076 upper->kbtrans_streams_iocpending = mp; 1077 if (upper->kbtrans_streams_bufcallid) { 1078 qunbufcall(upper->kbtrans_streams_readq, 1079 upper->kbtrans_streams_bufcallid); 1080 } 1081 upper->kbtrans_streams_bufcallid = 1082 qbufcall(upper->kbtrans_streams_readq, ioctlrespsize, BPRI_HI, 1083 kbtrans_reioctl, upper); 1084 /* 1085 * This is a white lie... we *will* handle it, eventually. 1086 */ 1087 return (KBTRANS_MESSAGE_HANDLED); 1088 } 1089 1090 /* 1091 * kbtrans_flush: 1092 * Flush data upstream 1093 */ 1094 static void 1095 kbtrans_flush(register struct kbtrans *upper) 1096 { 1097 register queue_t *q; 1098 1099 /* Flush pending data already sent upstream */ 1100 if ((q = upper->kbtrans_streams_readq) != NULL && q->q_next != NULL) 1101 (void) putnextctl1(q, M_FLUSH, FLUSHR); 1102 1103 /* Flush pending ups */ 1104 bzero(upper->kbtrans_streams_downs, upper->kbtrans_streams_downs_bytes); 1105 1106 kbtrans_cancelrpt(upper); 1107 } 1108 1109 /* 1110 * kbtrans_setled: 1111 * Update the keyboard LEDs to match the current keyboard state. 1112 */ 1113 static void 1114 kbtrans_setled(struct kbtrans *upper) 1115 { 1116 upper->kbtrans_streams_hw_callbacks->kbtrans_streams_setled( 1117 upper->kbtrans_streams_hw, 1118 upper->kbtrans_lower.kbtrans_led_state); 1119 } 1120 1121 /* 1122 * kbtrans_rpt: 1123 * If a key is held down, this function is set up to be called 1124 * after kbtrans_repeat_rate time elapses. 1125 */ 1126 static void 1127 kbtrans_rpt(void *arg) 1128 { 1129 struct kbtrans *upper = arg; 1130 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1131 1132 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, 1133 "kbtrans_rpt: repeat key %X\n", 1134 lower->kbtrans_repeatkey)); 1135 1136 upper->kbtrans_streams_rptid = 0; 1137 1138 /* 1139 * NB: polled code zaps kbtrans_repeatkey without cancelling 1140 * timeout. 1141 */ 1142 if (lower->kbtrans_repeatkey != 0) { 1143 kbtrans_keyreleased(upper, lower->kbtrans_repeatkey); 1144 1145 kbtrans_processkey(lower, 1146 upper->kbtrans_streams_callback, 1147 lower->kbtrans_repeatkey, 1148 KEY_PRESSED); 1149 1150 upper->kbtrans_streams_rptid = 1151 qtimeout(upper->kbtrans_streams_readq, kbtrans_rpt, 1152 (caddr_t)upper, kbtrans_repeat_rate); 1153 } 1154 } 1155 1156 /* 1157 * kbtrans_cancelrpt: 1158 * Cancel the repeating key 1159 */ 1160 static void 1161 kbtrans_cancelrpt(struct kbtrans *upper) 1162 { 1163 upper->kbtrans_lower.kbtrans_repeatkey = 0; 1164 1165 if (upper->kbtrans_streams_rptid != 0) { 1166 (void) quntimeout(upper->kbtrans_streams_readq, 1167 upper->kbtrans_streams_rptid); 1168 upper->kbtrans_streams_rptid = 0; 1169 } 1170 } 1171 1172 /* 1173 * kbtrans_send_esc_event: 1174 * Send character up stream. Used for the case of 1175 * sending strings upstream. 1176 */ 1177 static void 1178 kbtrans_send_esc_event(char c, register struct kbtrans *upper) 1179 { 1180 Firm_event fe; 1181 1182 fe.id = c; 1183 fe.value = 1; 1184 fe.pair_type = FE_PAIR_NONE; 1185 fe.pair = 0; 1186 /* 1187 * Pretend as if each cp pushed and released 1188 * Calling kbtrans_queueevent avoids addr translation 1189 * and pair base determination of kbtrans_keypressed. 1190 */ 1191 kbtrans_queueevent(upper, &fe); 1192 fe.value = 0; 1193 kbtrans_queueevent(upper, &fe); 1194 } 1195 1196 /* 1197 * kbtrans_strsetwithdecimal: 1198 * Used for expanding a function key to the ascii equivalent 1199 */ 1200 static char * 1201 kbtrans_strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs) 1202 { 1203 int hradix = 5; 1204 char *bp; 1205 int lowbit; 1206 char *tab = "0123456789abcdef"; 1207 1208 bp = buf + maxdigs; 1209 *(--bp) = '\0'; 1210 while (val) { 1211 lowbit = val & 1; 1212 val = (val >> 1); 1213 *(--bp) = tab[val % hradix * 2 + lowbit]; 1214 val /= hradix; 1215 } 1216 return (bp); 1217 } 1218 1219 /* 1220 * kbtrans_keypressed: 1221 * Modify Firm event to be sent up the stream 1222 */ 1223 static void 1224 kbtrans_keypressed(struct kbtrans *upper, uchar_t key_station, 1225 Firm_event *fe, ushort_t base) 1226 { 1227 1228 register short id_addr; 1229 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1230 1231 /* Set pair values */ 1232 if (fe->id < (ushort_t)VKEY_FIRST) { 1233 /* 1234 * If CTRLed, find the ID that would have been used had it 1235 * not been CTRLed. 1236 */ 1237 if (lower->kbtrans_shiftmask & (CTRLMASK | CTLSMASK)) { 1238 unsigned short *ke; 1239 unsigned int mask; 1240 1241 mask = lower->kbtrans_shiftmask & 1242 ~(CTRLMASK | CTLSMASK | UPMASK); 1243 1244 ke = kbtrans_find_entry(lower, mask, key_station); 1245 if (ke == NULL) 1246 return; 1247 1248 base = *ke; 1249 } 1250 if (base != fe->id) { 1251 fe->pair_type = FE_PAIR_SET; 1252 fe->pair = (uchar_t)base; 1253 1254 goto send; 1255 } 1256 } 1257 fe->pair_type = FE_PAIR_NONE; 1258 fe->pair = 0; 1259 1260 send: 1261 /* Adjust event id address for multiple keyboard/workstation support */ 1262 switch (vuid_id_addr(fe->id)) { 1263 case ASCII_FIRST: 1264 id_addr = upper->kbtrans_streams_vuid_addr.ascii; 1265 break; 1266 case TOP_FIRST: 1267 id_addr = upper->kbtrans_streams_vuid_addr.top; 1268 break; 1269 case VKEY_FIRST: 1270 id_addr = upper->kbtrans_streams_vuid_addr.vkey; 1271 break; 1272 default: 1273 id_addr = vuid_id_addr(fe->id); 1274 break; 1275 } 1276 fe->id = vuid_id_offset(fe->id) | id_addr; 1277 1278 kbtrans_queuepress(upper, key_station, fe); 1279 } 1280 1281 /* 1282 * kbtrans_queuepress: 1283 * Add keypress to the "downs" table 1284 */ 1285 static void 1286 kbtrans_queuepress(struct kbtrans *upper, 1287 uchar_t key_station, Firm_event *fe) 1288 { 1289 register struct key_event *ke, *ke_free; 1290 register int i; 1291 1292 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "kbtrans_queuepress:" 1293 " key=%d", key_station)); 1294 1295 ke_free = 0; 1296 1297 /* Scan table of down key stations */ 1298 1299 for (i = 0, ke = upper->kbtrans_streams_downs; 1300 i < upper->kbtrans_streams_num_downs_entries; i++, ke++) { 1301 1302 /* Keycode already down? */ 1303 if (ke->key_station == key_station) { 1304 1305 DPRINTF(PRINT_L0, PRINT_MASK_ALL, 1306 (NULL, "kbtrans: Double " 1307 "entry in downs table (%d,%d)!\n", 1308 key_station, i)); 1309 1310 goto add_event; 1311 } 1312 1313 if (ke->key_station == 0) 1314 ke_free = ke; 1315 } 1316 1317 if (ke_free) { 1318 ke = ke_free; 1319 goto add_event; 1320 } 1321 1322 ke = upper->kbtrans_streams_downs; 1323 1324 add_event: 1325 ke->key_station = key_station; 1326 ke->event = *fe; 1327 kbtrans_queueevent(upper, fe); 1328 } 1329 1330 /* 1331 * kbtrans_keyreleased: 1332 * Remove entry from the downs table 1333 */ 1334 static void 1335 kbtrans_keyreleased(register struct kbtrans *upper, uchar_t key_station) 1336 { 1337 register struct key_event *ke; 1338 register int i; 1339 1340 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "RELEASE key=%d\n", 1341 key_station)); 1342 1343 if (upper->kbtrans_streams_translate_mode != TR_EVENT && 1344 upper->kbtrans_streams_translate_mode != TR_UNTRANS_EVENT) { 1345 1346 return; 1347 } 1348 1349 /* Scan table of down key stations */ 1350 for (i = 0, ke = upper->kbtrans_streams_downs; 1351 i < upper->kbtrans_streams_num_downs_entries; 1352 i++, ke++) { 1353 /* Found? */ 1354 if (ke->key_station == key_station) { 1355 ke->key_station = 0; 1356 ke->event.value = 0; 1357 kbtrans_queueevent(upper, &ke->event); 1358 } 1359 } 1360 1361 /* 1362 * Ignore if couldn't find because may be called twice 1363 * for the same key station in the case of the kbtrans_rpt 1364 * routine being called unnecessarily. 1365 */ 1366 } 1367 1368 1369 /* 1370 * kbtrans_putcode: 1371 * Pass a keycode up the stream, if you can, otherwise throw it away. 1372 */ 1373 static void 1374 kbtrans_putcode(register struct kbtrans *upper, uint_t code) 1375 { 1376 register mblk_t *bp; 1377 1378 /* 1379 * If we can't send it up, then we just drop it. 1380 */ 1381 if (!canputnext(upper->kbtrans_streams_readq)) { 1382 1383 return; 1384 } 1385 1386 /* 1387 * Allocate a messsage block to send up. 1388 */ 1389 if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) { 1390 1391 cmn_err(CE_WARN, "kbtrans_putcode: Can't allocate block\ 1392 for keycode."); 1393 1394 return; 1395 } 1396 1397 /* 1398 * We will strip out any high order information here. 1399 */ 1400 /* NOTE the implicit cast here */ 1401 *bp->b_wptr++ = (uchar_t)code; 1402 1403 /* 1404 * Send the message up. 1405 */ 1406 (void) putnext(upper->kbtrans_streams_readq, bp); 1407 } 1408 1409 1410 /* 1411 * kbtrans_putbuf: 1412 * Pass generated keycode sequence to upstream, if possible. 1413 */ 1414 static void 1415 kbtrans_putbuf(char *buf, queue_t *q) 1416 { 1417 register mblk_t *bp; 1418 1419 if (!canputnext(q)) { 1420 cmn_err(CE_WARN, "kbtrans_putbuf: Can't put block for keycode"); 1421 } else { 1422 if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) { 1423 cmn_err(CE_WARN, "kbtrans_putbuf: " 1424 "Can't allocate block for keycode"); 1425 } else { 1426 while (*buf) { 1427 *bp->b_wptr++ = *buf; 1428 buf++; 1429 } 1430 putnext(q, bp); 1431 } 1432 } 1433 } 1434 1435 /* 1436 * kbtrans_queueevent: 1437 * Pass a VUID "firm event" up the stream, if you can. 1438 */ 1439 static void 1440 kbtrans_queueevent(struct kbtrans *upper, Firm_event *fe) 1441 { 1442 register queue_t *q; 1443 register mblk_t *bp; 1444 1445 if ((q = upper->kbtrans_streams_readq) == NULL) 1446 1447 return; 1448 1449 if (!canputnext(q)) { 1450 if (kbtrans_overflow_msg) { 1451 DPRINTF(PRINT_L2, PRINT_MASK_ALL, (NULL, 1452 "kbtrans: Buffer flushed when overflowed.")); 1453 } 1454 1455 kbtrans_flush(upper); 1456 upper->kbtrans_overflow_cnt++; 1457 } else { 1458 if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) { 1459 cmn_err(CE_WARN, "kbtrans_queueevent: Can't allocate \ 1460 block for event."); 1461 } else { 1462 uniqtime32(&fe->time); 1463 *(Firm_event *)bp->b_wptr = *fe; 1464 bp->b_wptr += sizeof (Firm_event); 1465 (void) putnext(q, bp); 1466 1467 1468 } 1469 } 1470 } 1471 1472 /* 1473 * kbtrans_set_translation_callback: 1474 * This code sets the translation_callback pointer based on the 1475 * translation mode. 1476 */ 1477 static void 1478 kbtrans_set_translation_callback(register struct kbtrans *upper) 1479 { 1480 switch (upper->kbtrans_streams_translate_mode) { 1481 1482 default: 1483 case TR_ASCII: 1484 upper->kbtrans_streams_callback = &ascii_callback; 1485 1486 break; 1487 1488 case TR_EVENT: 1489 upper->kbtrans_streams_callback = &trans_event_callback; 1490 1491 break; 1492 1493 case TR_UNTRANS_EVENT: 1494 upper->kbtrans_streams_callback = &untrans_event_callback; 1495 1496 break; 1497 } 1498 } 1499 1500 /* 1501 * kbtrans_untrans_keypressed_raw: 1502 * This is the callback we get if we are in TR_UNTRANS_EVENT and a 1503 * key is pressed. This code will just send the scancode up the 1504 * stream. 1505 */ 1506 static void 1507 kbtrans_untrans_keypressed_raw(struct kbtrans *upper, kbtrans_key_t key) 1508 { 1509 Firm_event fe; 1510 1511 bzero(&fe, sizeof (fe)); 1512 1513 /* 1514 * fill in the event 1515 */ 1516 fe.id = (unsigned short)key; 1517 fe.value = 1; 1518 1519 /* 1520 * Send the event upstream. 1521 */ 1522 kbtrans_queuepress(upper, key, &fe); 1523 } 1524 1525 /* 1526 * kbtrans_untrans_keyreleased_raw: 1527 * This is the callback we get if we are in TR_UNTRANS_EVENT mode 1528 * and a key is released. This code will just send the scancode up 1529 * the stream. 1530 */ 1531 static void 1532 kbtrans_untrans_keyreleased_raw(struct kbtrans *upper, kbtrans_key_t key) 1533 { 1534 /* 1535 * Deal with a key released event. 1536 */ 1537 kbtrans_keyreleased(upper, key); 1538 } 1539 1540 /* 1541 * kbtrans_ascii_keypressed: 1542 * This is the code if we are in TR_ASCII mode and a key 1543 * is pressed. This is where we will do any special processing that 1544 * is specific to ASCII key translation. 1545 */ 1546 /* ARGSUSED */ 1547 static void 1548 kbtrans_ascii_keypressed( 1549 struct kbtrans *upper, 1550 uint_t entrytype, 1551 kbtrans_key_t key, 1552 uint_t entry) 1553 { 1554 register char *cp; 1555 register char *bufp; 1556 char buf[14]; 1557 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1558 1559 /* 1560 * Based on the type of key, we may need to do some ASCII 1561 * specific post processing. 1562 */ 1563 switch (entrytype) { 1564 1565 case BUCKYBITS: 1566 case SHIFTKEYS: 1567 case FUNNY: 1568 /* 1569 * There is no ascii equivalent. We will ignore these 1570 * keys 1571 */ 1572 return; 1573 1574 case FUNCKEYS: 1575 /* 1576 * We need to expand this key to get the ascii 1577 * equivalent. These are the function keys (F1, F2 ...) 1578 */ 1579 bufp = buf; 1580 cp = kbtrans_strsetwithdecimal(bufp + 2, 1581 (uint_t)((entry & 0x003F) + 192), 1582 sizeof (buf) - 5); 1583 *bufp++ = '\033'; /* Escape */ 1584 *bufp++ = '['; 1585 while (*cp != '\0') 1586 *bufp++ = *cp++; 1587 *bufp++ = 'z'; 1588 *bufp = '\0'; 1589 1590 /* 1591 * Send the result upstream. 1592 */ 1593 kbtrans_putbuf(buf, upper->kbtrans_streams_readq); 1594 1595 return; 1596 1597 case STRING: 1598 /* 1599 * These are the multi byte keys (Home, Up, Down ...) 1600 */ 1601 cp = &lower->kbtrans_keystringtab[entry & 0x0F][0]; 1602 1603 /* 1604 * Copy the string from the keystringtable, and send it 1605 * upstream a character at a time. 1606 */ 1607 while (*cp != '\0') { 1608 1609 kbtrans_putcode(upper, (uchar_t)*cp); 1610 1611 cp++; 1612 } 1613 1614 return; 1615 1616 case PADKEYS: 1617 /* 1618 * These are the keys on the keypad. Look up the 1619 * answer in the kb_numlock_table and send it upstream. 1620 */ 1621 kbtrans_putcode(upper, 1622 lower->kbtrans_numlock_table[entry&0x1F]); 1623 1624 return; 1625 1626 case 0: /* normal character */ 1627 default: 1628 break; 1629 } 1630 1631 /* 1632 * Send the byte upstream. 1633 */ 1634 kbtrans_putcode(upper, entry); 1635 1636 } 1637 1638 /* 1639 * kbtrans_ascii_keyreleased: 1640 * This is the function if we are in TR_ASCII mode and a key 1641 * is released. ASCII doesn't have the concept of released keys, 1642 * or make/break codes. So there is nothing for us to do. 1643 */ 1644 /* ARGSUSED */ 1645 static void 1646 kbtrans_ascii_keyreleased(struct kbtrans *upper, kbtrans_key_t key) 1647 { 1648 /* Nothing to do ... for now */ 1649 } 1650 1651 /* 1652 * kbtrans_ascii_setup_repeat: 1653 * This is the function if we are in TR_ASCII mode and the 1654 * translation module has decided that a key needs to be repeated. 1655 */ 1656 /* ARGSUSED */ 1657 static void 1658 kbtrans_ascii_setup_repeat( 1659 struct kbtrans *upper, 1660 uint_t entrytype, 1661 kbtrans_key_t key) 1662 { 1663 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1664 1665 /* 1666 * Cancel any currently repeating keys. This will be a new 1667 * key to repeat. 1668 */ 1669 kbtrans_cancelrpt(upper); 1670 1671 /* 1672 * Set the value of the key to be repeated. 1673 */ 1674 lower->kbtrans_repeatkey = key; 1675 1676 /* 1677 * Start the timeout for repeating this key. kbtrans_rpt will 1678 * be called to repeat the key. 1679 */ 1680 upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq, 1681 kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay); 1682 } 1683 1684 /* 1685 * kbtrans_trans_event_keypressed: 1686 * This is the function if we are in TR_EVENT mode and a key 1687 * is pressed. This is where we will do any special processing that 1688 * is specific to EVENT key translation. 1689 */ 1690 static void 1691 kbtrans_trans_event_keypressed( 1692 struct kbtrans *upper, 1693 uint_t entrytype, 1694 kbtrans_key_t key, 1695 uint_t entry) 1696 { 1697 Firm_event fe; 1698 register char *cp; 1699 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1700 1701 /* 1702 * Based on the type of key, we may need to do some EVENT 1703 * specific post processing. 1704 */ 1705 switch (entrytype) { 1706 1707 case SHIFTKEYS: 1708 /* 1709 * Relying on ordinal correspondence between 1710 * vuid_event.h SHIFT_META-SHIFT_TOP & 1711 * kbd.h METABIT-SYSTEMBIT in order to 1712 * correctly translate entry into fe.id. 1713 */ 1714 fe.id = SHIFT_CAPSLOCK + (entry & 0x0F); 1715 fe.value = 1; 1716 kbtrans_keypressed(upper, key, &fe, fe.id); 1717 1718 return; 1719 1720 case BUCKYBITS: 1721 /* 1722 * Relying on ordinal correspondence between 1723 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL & 1724 * kbd.h CAPSLOCK-RIGHTCTRL in order to 1725 * correctly translate entry into fe.id. 1726 */ 1727 fe.id = SHIFT_META + (entry & 0x0F); 1728 fe.value = 1; 1729 kbtrans_keypressed(upper, key, &fe, fe.id); 1730 1731 return; 1732 1733 case FUNCKEYS: 1734 /* 1735 * Take advantage of the similar 1736 * ordering of kbd.h function keys and 1737 * vuid_event.h function keys to do a 1738 * simple translation to achieve a 1739 * mapping between the 2 different 1740 * address spaces. 1741 */ 1742 fe.id = KEY_LEFTFIRST + (entry & 0x003F); 1743 fe.value = 1; 1744 1745 /* 1746 * Assume "up" table only generates 1747 * shift changes. 1748 */ 1749 kbtrans_keypressed(upper, key, &fe, fe.id); 1750 1751 /* 1752 * Function key events can be expanded 1753 * by terminal emulator software to 1754 * produce the standard escape sequence 1755 * generated by the TR_ASCII case above 1756 * if a function key event is not used 1757 * by terminal emulator software 1758 * directly. 1759 */ 1760 return; 1761 1762 case STRING: 1763 /* 1764 * These are the multi byte keys (Home, Up, Down ...) 1765 */ 1766 cp = &lower->kbtrans_keystringtab[entry & 0x0F][0]; 1767 1768 /* 1769 * Copy the string from the keystringtable, and send it 1770 * upstream a character at a time. 1771 */ 1772 while (*cp != '\0') { 1773 1774 kbtrans_send_esc_event(*cp, upper); 1775 1776 cp++; 1777 } 1778 1779 return; 1780 1781 case PADKEYS: 1782 /* 1783 * Take advantage of the similar 1784 * ordering of kbd.h keypad keys and 1785 * vuid_event.h keypad keys to do a 1786 * simple translation to achieve a 1787 * mapping between the 2 different 1788 * address spaces. 1789 */ 1790 fe.id = VKEY_FIRSTPAD + (entry & 0x001F); 1791 fe.value = 1; 1792 1793 /* 1794 * Assume "up" table only generates 1795 * shift changes. 1796 */ 1797 kbtrans_keypressed(upper, key, &fe, fe.id); 1798 1799 /* 1800 * Keypad key events can be expanded 1801 * by terminal emulator software to 1802 * produce the standard ascii character 1803 * generated by the TR_ASCII case above 1804 * if a keypad key event is not used 1805 * by terminal emulator software 1806 * directly. 1807 */ 1808 return; 1809 1810 case FUNNY: 1811 /* 1812 * These are not events. 1813 */ 1814 switch (entry) { 1815 case IDLE: 1816 case RESET: 1817 case ERROR: 1818 /* 1819 * Something has happened. Mark all keys as released. 1820 */ 1821 kbtrans_streams_releaseall(upper); 1822 break; 1823 } 1824 1825 return; 1826 1827 case 0: /* normal character */ 1828 default: 1829 break; 1830 } 1831 1832 /* 1833 * Send the event upstream. 1834 */ 1835 fe.id = entry; 1836 1837 fe.value = 1; 1838 1839 kbtrans_queueevent(upper, &fe); 1840 } 1841 1842 /* 1843 * kbtrans_trans_event_keyreleased: 1844 * This is the function if we are in TR_EVENT mode and a key 1845 * is released. 1846 */ 1847 /* ARGSUSED */ 1848 static void 1849 kbtrans_trans_event_keyreleased(struct kbtrans *upper, kbtrans_key_t key) 1850 { 1851 /* 1852 * Mark the key as released and send an event upstream. 1853 */ 1854 kbtrans_keyreleased(upper, key); 1855 } 1856 1857 /* 1858 * kbtrans_trans_event_setup_repeat: 1859 * This is the function if we are in TR_EVENT mode and the 1860 * translation module has decided that a key needs to be repeated. 1861 * We will set a timeout to retranslate the repeat key. 1862 */ 1863 static void 1864 kbtrans_trans_event_setup_repeat( 1865 struct kbtrans *upper, 1866 uint_t entrytype, 1867 kbtrans_key_t key) 1868 { 1869 struct kbtrans_lower *lower = &upper->kbtrans_lower; 1870 1871 /* 1872 * Function keys and keypad keys do not repeat when we are in 1873 * EVENT mode. 1874 */ 1875 if (entrytype == FUNCKEYS || entrytype == PADKEYS) { 1876 1877 return; 1878 } 1879 1880 /* 1881 * Cancel any currently repeating keys. This will be a new 1882 * key to repeat. 1883 */ 1884 kbtrans_cancelrpt(upper); 1885 1886 /* 1887 * Set the value of the key to be repeated. 1888 */ 1889 lower->kbtrans_repeatkey = key; 1890 1891 /* 1892 * Start the timeout for repeating this key. kbtrans_rpt will 1893 * be called to repeat the key. 1894 */ 1895 upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq, 1896 kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay); 1897 } 1898 1899 /* 1900 * Administer the key tables. 1901 */ 1902 1903 /* 1904 * Old special codes. 1905 */ 1906 #define OLD_SHIFTKEYS 0x80 1907 #define OLD_BUCKYBITS 0x90 1908 #define OLD_FUNNY 0xA0 1909 #define OLD_FA_UMLAUT 0xA9 1910 #define OLD_FA_CFLEX 0xAA 1911 #define OLD_FA_TILDE 0xAB 1912 #define OLD_FA_CEDILLA 0xAC 1913 #define OLD_FA_ACUTE 0xAD 1914 #define OLD_FA_GRAVE 0xAE 1915 #define OLD_ISOCHAR 0xAF 1916 #define OLD_STRING 0xB0 1917 #define OLD_LEFTFUNC 0xC0 1918 #define OLD_RIGHTFUNC 0xD0 1919 #define OLD_TOPFUNC 0xE0 1920 #define OLD_BOTTOMFUNC 0xF0 1921 1922 /* 1923 * Map old special codes to new ones. 1924 * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F. 1925 */ 1926 static ushort_t special_old_to_new[] = { 1927 SHIFTKEYS, 1928 BUCKYBITS, 1929 FUNNY, 1930 STRING, 1931 LEFTFUNC, 1932 RIGHTFUNC, 1933 TOPFUNC, 1934 BOTTOMFUNC, 1935 }; 1936 1937 1938 /* 1939 * kbtrans_setkey: 1940 * Set individual keystation translation from old-style entry. 1941 */ 1942 static int 1943 kbtrans_setkey(struct kbtrans_lower *lower, struct kiockey *key, cred_t *cr) 1944 { 1945 int strtabindex, i; 1946 unsigned short *ke; 1947 register int tablemask; 1948 register ushort_t entry; 1949 register struct keyboard *kp; 1950 1951 kp = lower->kbtrans_keyboard; 1952 1953 if (key->kio_station >= kp->k_keymap_size) 1954 1955 return (EINVAL); 1956 1957 if (lower->kbtrans_keyboard == NULL) 1958 1959 return (EINVAL); 1960 1961 tablemask = key->kio_tablemask; 1962 1963 switch (tablemask) { 1964 case KIOCABORT1: 1965 case KIOCABORT1A: 1966 case KIOCABORT2: 1967 i = secpolicy_console(cr); 1968 if (i != 0) 1969 return (i); 1970 1971 switch (tablemask) { 1972 case KIOCABORT1: 1973 kp->k_abort1 = key->kio_station; 1974 break; 1975 case KIOCABORT1A: 1976 kp->k_abort1a = key->kio_station; 1977 break; 1978 case KIOCABORT2: 1979 kp->k_abort2 = key->kio_station; 1980 break; 1981 } 1982 return (0); 1983 } 1984 1985 if (tablemask & ALTGRAPHMASK) 1986 return (EINVAL); 1987 1988 ke = kbtrans_find_entry(lower, (uint_t)tablemask, key->kio_station); 1989 if (ke == NULL) 1990 return (EINVAL); 1991 1992 if (key->kio_entry >= (uchar_t)OLD_STRING && 1993 key->kio_entry <= (uchar_t)(OLD_STRING + 15)) { 1994 strtabindex = key->kio_entry - OLD_STRING; 1995 bcopy(key->kio_string, 1996 lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN); 1997 lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 1998 } 1999 2000 entry = key->kio_entry; 2001 2002 /* 2003 * There's nothing we need do with OLD_ISOCHAR. 2004 */ 2005 if (entry != OLD_ISOCHAR) { 2006 if (entry & 0x80) { 2007 if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE) 2008 entry = FA_CLASS + (entry & 0x0F) - 9; 2009 else 2010 entry = 2011 special_old_to_new[entry >> 4 & 0x07] 2012 + (entry & 0x0F); 2013 } 2014 } 2015 2016 *ke = entry; 2017 2018 return (0); 2019 } 2020 2021 2022 /* 2023 * Map new special codes to old ones. 2024 * Indexed by (new special code) >> 8; add (new special code) & 0xFF. 2025 */ 2026 static uchar_t special_new_to_old[] = { 2027 0, /* normal */ 2028 OLD_SHIFTKEYS, /* SHIFTKEYS */ 2029 OLD_BUCKYBITS, /* BUCKYBITS */ 2030 OLD_FUNNY, /* FUNNY */ 2031 OLD_FA_UMLAUT, /* FA_CLASS */ 2032 OLD_STRING, /* STRING */ 2033 OLD_LEFTFUNC, /* FUNCKEYS */ 2034 }; 2035 2036 2037 /* 2038 * kbtrans_getkey: 2039 * Get individual keystation translation as old-style entry. 2040 */ 2041 static int 2042 kbtrans_getkey(struct kbtrans_lower *lower, struct kiockey *key) 2043 { 2044 int strtabindex; 2045 unsigned short *ke; 2046 register ushort_t entry; 2047 struct keyboard *kp; 2048 2049 kp = lower->kbtrans_keyboard; 2050 2051 if (key->kio_station >= kp->k_keymap_size) 2052 return (EINVAL); 2053 2054 if (lower->kbtrans_keyboard == NULL) 2055 return (EINVAL); 2056 2057 switch (key->kio_tablemask) { 2058 case KIOCABORT1: 2059 key->kio_station = kp->k_abort1; 2060 return (0); 2061 case KIOCABORT1A: 2062 key->kio_station = kp->k_abort1a; 2063 return (0); 2064 case KIOCABORT2: 2065 key->kio_station = kp->k_abort2; 2066 return (0); 2067 } 2068 2069 ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask, 2070 key->kio_station); 2071 if (ke == NULL) 2072 return (EINVAL); 2073 2074 entry = *ke; 2075 2076 if (entry & 0xFF00) 2077 key->kio_entry = 2078 special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8] 2079 + (entry & 0x00FF); 2080 else { 2081 if (entry & 0x80) 2082 key->kio_entry = (ushort_t)OLD_ISOCHAR; /* you lose */ 2083 else 2084 key->kio_entry = (ushort_t)entry; 2085 } 2086 2087 if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) { 2088 strtabindex = entry - STRING; 2089 bcopy(lower->kbtrans_keystringtab[strtabindex], 2090 key->kio_string, KTAB_STRLEN); 2091 } 2092 return (0); 2093 } 2094 2095 2096 /* 2097 * kbtrans_skey: 2098 * Set individual keystation translation from new-style entry. 2099 */ 2100 static int 2101 kbtrans_skey(struct kbtrans_lower *lower, struct kiockeymap *key, cred_t *cr) 2102 { 2103 int strtabindex, i; 2104 unsigned short *ke; 2105 struct keyboard *kp; 2106 2107 kp = lower->kbtrans_keyboard; 2108 2109 if (key->kio_station >= kp->k_keymap_size) { 2110 return (EINVAL); 2111 2112 } 2113 2114 if (lower->kbtrans_keyboard == NULL) { 2115 return (EINVAL); 2116 } 2117 2118 switch (key->kio_tablemask) { 2119 case KIOCABORT1: 2120 case KIOCABORT1A: 2121 case KIOCABORT2: 2122 i = secpolicy_console(cr); 2123 if (i != 0) 2124 return (i); 2125 switch (key->kio_tablemask) { 2126 case KIOCABORT1: 2127 kp->k_abort1 = key->kio_station; 2128 break; 2129 case KIOCABORT1A: 2130 kp->k_abort1a = key->kio_station; 2131 break; 2132 case KIOCABORT2: 2133 kp->k_abort2 = key->kio_station; 2134 break; 2135 } 2136 return (0); 2137 } 2138 2139 ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask, 2140 key->kio_station); 2141 if (ke == NULL) 2142 return (EINVAL); 2143 2144 if (key->kio_entry >= STRING && 2145 key->kio_entry <= (ushort_t)(STRING + 15)) { 2146 strtabindex = key->kio_entry-STRING; 2147 bcopy(key->kio_string, 2148 lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN); 2149 lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 2150 } 2151 2152 *ke = key->kio_entry; 2153 2154 return (0); 2155 } 2156 2157 2158 /* 2159 * kbtrans_gkey: 2160 * Get individual keystation translation as new-style entry. 2161 */ 2162 static int 2163 kbtrans_gkey(struct kbtrans_lower *lower, struct kiockeymap *key) 2164 { 2165 int strtabindex; 2166 unsigned short *ke; 2167 struct keyboard *kp; 2168 2169 kp = lower->kbtrans_keyboard; 2170 2171 if (key->kio_station >= kp->k_keymap_size) 2172 return (EINVAL); 2173 2174 if (lower->kbtrans_keyboard == NULL) 2175 return (EINVAL); 2176 2177 switch (key->kio_tablemask) { 2178 case KIOCABORT1: 2179 key->kio_station = kp->k_abort1; 2180 return (0); 2181 case KIOCABORT1A: 2182 key->kio_station = kp->k_abort1a; 2183 return (0); 2184 case KIOCABORT2: 2185 key->kio_station = kp->k_abort2; 2186 return (0); 2187 } 2188 2189 ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask, 2190 key->kio_station); 2191 if (ke == NULL) 2192 return (EINVAL); 2193 2194 key->kio_entry = *ke; 2195 2196 if (key->kio_entry >= STRING && 2197 key->kio_entry <= (ushort_t)(STRING + 15)) { 2198 strtabindex = key->kio_entry-STRING; 2199 bcopy(lower->kbtrans_keystringtab[strtabindex], 2200 key->kio_string, KTAB_STRLEN); 2201 } 2202 return (0); 2203 } 2204