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