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