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