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