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