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