1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate /* SunOS-4.0 1.60 */ 29*0Sstevel@tonic-gate /* From: SunOS4.0 sundev/kbd.c */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate /* 32*0Sstevel@tonic-gate * Keyboard input streams module - handles conversion of up/down codes to 33*0Sstevel@tonic-gate * ASCII or event format. 34*0Sstevel@tonic-gate */ 35*0Sstevel@tonic-gate #include <sys/types.h> 36*0Sstevel@tonic-gate #include <sys/param.h> 37*0Sstevel@tonic-gate #include <sys/sysmacros.h> 38*0Sstevel@tonic-gate #include <sys/signal.h> 39*0Sstevel@tonic-gate #include <sys/termios.h> 40*0Sstevel@tonic-gate #include <sys/termio.h> 41*0Sstevel@tonic-gate #include <sys/stream.h> 42*0Sstevel@tonic-gate #include <sys/stropts.h> 43*0Sstevel@tonic-gate #include <sys/strsun.h> 44*0Sstevel@tonic-gate #include <sys/kmem.h> 45*0Sstevel@tonic-gate #include <sys/file.h> 46*0Sstevel@tonic-gate #include <sys/uio.h> 47*0Sstevel@tonic-gate #include <sys/errno.h> 48*0Sstevel@tonic-gate #include <sys/time.h> 49*0Sstevel@tonic-gate #include <sys/consdev.h> 50*0Sstevel@tonic-gate #include <sys/kbd.h> 51*0Sstevel@tonic-gate #include <sys/kbio.h> 52*0Sstevel@tonic-gate #include <sys/kbdreg.h> 53*0Sstevel@tonic-gate #include <sys/vuid_event.h> 54*0Sstevel@tonic-gate #include <sys/debug.h> 55*0Sstevel@tonic-gate #include <sys/ddi.h> 56*0Sstevel@tonic-gate #include <sys/sunddi.h> 57*0Sstevel@tonic-gate #include <sys/policy.h> 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate #include <sys/modctl.h> 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate static struct streamtab kbd_info; 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate static struct fmodsw fsw = { 64*0Sstevel@tonic-gate "kb", 65*0Sstevel@tonic-gate &kbd_info, 66*0Sstevel@tonic-gate D_MP | D_MTPERMOD 67*0Sstevel@tonic-gate }; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* 70*0Sstevel@tonic-gate * Module linkage information for the kernel. 71*0Sstevel@tonic-gate */ 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate static struct modlstrmod modlstrmod = { 74*0Sstevel@tonic-gate &mod_strmodops, "streams module for keyboard", &fsw 75*0Sstevel@tonic-gate }; 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 78*0Sstevel@tonic-gate MODREV_1, (void *)&modlstrmod, NULL 79*0Sstevel@tonic-gate }; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate int 82*0Sstevel@tonic-gate _init(void) 83*0Sstevel@tonic-gate { 84*0Sstevel@tonic-gate return (mod_install(&modlinkage)); 85*0Sstevel@tonic-gate } 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate int 88*0Sstevel@tonic-gate _fini(void) 89*0Sstevel@tonic-gate { 90*0Sstevel@tonic-gate return (mod_remove(&modlinkage)); 91*0Sstevel@tonic-gate } 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate int 94*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 95*0Sstevel@tonic-gate { 96*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate /* 100*0Sstevel@tonic-gate * For now these are shared. 101*0Sstevel@tonic-gate * These data structures are static (defined in keytables.c) thus 102*0Sstevel@tonic-gate * there is no need to perform any locking. 103*0Sstevel@tonic-gate */ 104*0Sstevel@tonic-gate extern struct keyboards keytables[]; 105*0Sstevel@tonic-gate extern char keystringtab[16][KTAB_STRLEN]; 106*0Sstevel@tonic-gate extern struct compose_sequence_t kb_compose_table[]; 107*0Sstevel@tonic-gate extern signed char kb_compose_map[]; 108*0Sstevel@tonic-gate extern struct fltaccent_sequence_t kb_fltaccent_table[]; 109*0Sstevel@tonic-gate extern uchar_t kb_numlock_table[]; 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate /* 112*0Sstevel@tonic-gate * This value corresponds approximately to max 10 fingers 113*0Sstevel@tonic-gate */ 114*0Sstevel@tonic-gate static int kbd_downs_size = 15; 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate typedef struct key_event { 117*0Sstevel@tonic-gate uchar_t key_station; /* Physical key station associated with event */ 118*0Sstevel@tonic-gate Firm_event event; /* Event that sent out on down */ 119*0Sstevel@tonic-gate } Key_event; 120*0Sstevel@tonic-gate struct kbddata { 121*0Sstevel@tonic-gate queue_t *kbdd_readq; 122*0Sstevel@tonic-gate queue_t *kbdd_writeq; 123*0Sstevel@tonic-gate mblk_t *kbdd_iocpending; /* "ioctl" awaiting buffer */ 124*0Sstevel@tonic-gate mblk_t *kbdd_replypending; /* "ioctl" reply awaiting result */ 125*0Sstevel@tonic-gate int kbdd_flags; /* random flags */ 126*0Sstevel@tonic-gate bufcall_id_t kbdd_bufcallid; /* bufcall id */ 127*0Sstevel@tonic-gate timeout_id_t kbdd_rptid; /* timeout id for kbdrpt() */ 128*0Sstevel@tonic-gate timeout_id_t kbdd_layoutid; /* timeout id for kbdlayout() */ 129*0Sstevel@tonic-gate int kbdd_iocid; /* ID of "ioctl" being waited for */ 130*0Sstevel@tonic-gate int kbdd_iocerror; /* error return from "ioctl" */ 131*0Sstevel@tonic-gate struct keyboardstate kbdd_state; 132*0Sstevel@tonic-gate /* 133*0Sstevel@tonic-gate * State of keyboard & keyboard 134*0Sstevel@tonic-gate * specific settings, e.g., tables 135*0Sstevel@tonic-gate */ 136*0Sstevel@tonic-gate int kbdd_translate; /* Translate keycodes? */ 137*0Sstevel@tonic-gate int kbdd_translatable; /* Keyboard is translatable? */ 138*0Sstevel@tonic-gate int kbdd_compat; /* Generating pre-4.1 events? */ 139*0Sstevel@tonic-gate short kbdd_ascii_addr; /* Vuid_id_addr for ascii events */ 140*0Sstevel@tonic-gate short kbdd_top_addr; /* Vuid_id_addr for top events */ 141*0Sstevel@tonic-gate short kbdd_vkey_addr; /* Vuid_id_addr for vkey events */ 142*0Sstevel@tonic-gate struct key_event *kbdd_downs; 143*0Sstevel@tonic-gate /* 144*0Sstevel@tonic-gate * Table of key stations currently down 145*0Sstevel@tonic-gate * that have firm events that need 146*0Sstevel@tonic-gate * to be matched with up transitions 147*0Sstevel@tonic-gate * when kbdd_translate is TR_*EVENT 148*0Sstevel@tonic-gate */ 149*0Sstevel@tonic-gate int kbdd_downs_entries; /* # of possible entries in kbdd_downs */ 150*0Sstevel@tonic-gate uint_t kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */ 151*0Sstevel@tonic-gate ushort_t compose_key; /* first compose key */ 152*0Sstevel@tonic-gate ushort_t fltaccent_entry; /* floating accent keymap entry */ 153*0Sstevel@tonic-gate char led_state; /* current state of LEDs */ 154*0Sstevel@tonic-gate }; 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate #define KBD_OPEN 0x00000001 /* keyboard is open for business */ 157*0Sstevel@tonic-gate #define KBD_IOCWAIT 0x00000002 /* "open" waiting for "ioctl" to finish */ 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate #define NO_HARD_RESET 0 /* don't do hard reset */ 160*0Sstevel@tonic-gate #define HARD_RESET 1 /* do hard reset */ 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate /* 164*0Sstevel@tonic-gate * Constants setup during the first open of a kbd (so that they can be patched 165*0Sstevel@tonic-gate * for debugging purposes). 166*0Sstevel@tonic-gate */ 167*0Sstevel@tonic-gate static int kbd_repeatrate; 168*0Sstevel@tonic-gate static int kbd_repeatdelay; 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate static int kbd_overflow_cnt; /* Number of times kbd overflowed input q */ 171*0Sstevel@tonic-gate static int kbd_overflow_msg = 1; /* Whether to print message on q overflow */ 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate #ifdef KBD_DEBUG 174*0Sstevel@tonic-gate int kbd_debug = 0; 175*0Sstevel@tonic-gate int kbd_ra_debug = 0; 176*0Sstevel@tonic-gate int kbd_raw_debug = 0; 177*0Sstevel@tonic-gate int kbd_rpt_debug = 0; 178*0Sstevel@tonic-gate int kbd_input_debug = 0; 179*0Sstevel@tonic-gate #endif /* KBD_DEBUG */ 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate static int kbdopen(queue_t *, dev_t *, int, int, cred_t *); 182*0Sstevel@tonic-gate static int kbdclose(queue_t *, int, cred_t *); 183*0Sstevel@tonic-gate static void kbdwput(queue_t *, mblk_t *); 184*0Sstevel@tonic-gate static void kbdrput(queue_t *, mblk_t *); 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate static struct module_info kbdmiinfo = { 187*0Sstevel@tonic-gate 0, 188*0Sstevel@tonic-gate "kb", 189*0Sstevel@tonic-gate 0, 190*0Sstevel@tonic-gate INFPSZ, 191*0Sstevel@tonic-gate 2048, 192*0Sstevel@tonic-gate 128 193*0Sstevel@tonic-gate }; 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate static struct qinit kbdrinit = { 196*0Sstevel@tonic-gate (int (*)())kbdrput, 197*0Sstevel@tonic-gate (int (*)())NULL, 198*0Sstevel@tonic-gate kbdopen, 199*0Sstevel@tonic-gate kbdclose, 200*0Sstevel@tonic-gate (int (*)())NULL, 201*0Sstevel@tonic-gate &kbdmiinfo 202*0Sstevel@tonic-gate }; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate static struct module_info kbdmoinfo = { 205*0Sstevel@tonic-gate 0, 206*0Sstevel@tonic-gate "kb", 207*0Sstevel@tonic-gate 0, 208*0Sstevel@tonic-gate INFPSZ, 209*0Sstevel@tonic-gate 2048, 210*0Sstevel@tonic-gate 128 211*0Sstevel@tonic-gate }; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate static struct qinit kbdwinit = { 214*0Sstevel@tonic-gate (int (*)())kbdwput, 215*0Sstevel@tonic-gate (int (*)())NULL, 216*0Sstevel@tonic-gate kbdopen, 217*0Sstevel@tonic-gate kbdclose, 218*0Sstevel@tonic-gate (int (*)())NULL, 219*0Sstevel@tonic-gate &kbdmoinfo 220*0Sstevel@tonic-gate }; 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate static struct streamtab kbd_info = { 223*0Sstevel@tonic-gate &kbdrinit, 224*0Sstevel@tonic-gate &kbdwinit, 225*0Sstevel@tonic-gate NULL, 226*0Sstevel@tonic-gate NULL, 227*0Sstevel@tonic-gate }; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate static void kbdreioctl(void *); 230*0Sstevel@tonic-gate static void kbdioctl(queue_t *, mblk_t *); 231*0Sstevel@tonic-gate static void kbdflush(struct kbddata *); 232*0Sstevel@tonic-gate static void kbduse(struct kbddata *, unsigned); 233*0Sstevel@tonic-gate static void kbdsetled(struct kbddata *); 234*0Sstevel@tonic-gate static void kbdcmd(queue_t *, char); 235*0Sstevel@tonic-gate static void kbdreset(struct kbddata *, uint_t); 236*0Sstevel@tonic-gate static int kbdsetkey(struct kbddata *, struct kiockey *, cred_t *); 237*0Sstevel@tonic-gate static int kbdgetkey(struct kbddata *, struct kiockey *); 238*0Sstevel@tonic-gate static int kbdskey(struct kbddata *, struct kiockeymap *, cred_t *); 239*0Sstevel@tonic-gate static int kbdgkey(struct kbddata *, struct kiockeymap *); 240*0Sstevel@tonic-gate static void kbdlayouttimeout(void *); 241*0Sstevel@tonic-gate static void kbdinput(struct kbddata *, unsigned); 242*0Sstevel@tonic-gate static void kbdid(struct kbddata *, int); 243*0Sstevel@tonic-gate static struct keymap *settable(struct kbddata *, uint_t); 244*0Sstevel@tonic-gate static void kbdrpt(void *); 245*0Sstevel@tonic-gate static void kbdcancelrpt(struct kbddata *); 246*0Sstevel@tonic-gate static void kbdtranslate(struct kbddata *, unsigned, queue_t *); 247*0Sstevel@tonic-gate static int kbd_do_compose(ushort_t, ushort_t, ushort_t *); 248*0Sstevel@tonic-gate static void kbd_send_esc_event(char, struct kbddata *); 249*0Sstevel@tonic-gate char *strsetwithdecimal(char *, uint_t, uint_t); 250*0Sstevel@tonic-gate static void kbdkeypressed(struct kbddata *, uchar_t, Firm_event *, 251*0Sstevel@tonic-gate ushort_t); 252*0Sstevel@tonic-gate static void kbdqueuepress(struct kbddata *, uchar_t, Firm_event *); 253*0Sstevel@tonic-gate static void kbdkeyreleased(struct kbddata *, uchar_t); 254*0Sstevel@tonic-gate static void kbdreleaseall(struct kbddata *); 255*0Sstevel@tonic-gate static void kbdputcode(uint_t, queue_t *); 256*0Sstevel@tonic-gate static void kbdputbuf(char *, queue_t *); 257*0Sstevel@tonic-gate static void kbdqueueevent(struct kbddata *, Firm_event *); 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate /* 260*0Sstevel@tonic-gate * Dummy qbufcall callback routine used by open and close. 261*0Sstevel@tonic-gate * The framework will wake up qwait_sig when we return from 262*0Sstevel@tonic-gate * this routine (as part of leaving the perimeters.) 263*0Sstevel@tonic-gate * (The framework enters the perimeters before calling the qbufcall() callback 264*0Sstevel@tonic-gate * and leaves the perimeters after the callback routine has executed. The 265*0Sstevel@tonic-gate * framework performs an implicit wakeup of any thread in qwait/qwait_sig 266*0Sstevel@tonic-gate * when it leaves the perimeter. See qwait(9E).) 267*0Sstevel@tonic-gate */ 268*0Sstevel@tonic-gate /* ARGSUSED */ 269*0Sstevel@tonic-gate static void dummy_callback(void *arg) 270*0Sstevel@tonic-gate {} 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate /* 274*0Sstevel@tonic-gate * Open a keyboard. 275*0Sstevel@tonic-gate * Ttyopen sets line characteristics 276*0Sstevel@tonic-gate */ 277*0Sstevel@tonic-gate /* ARGSUSED */ 278*0Sstevel@tonic-gate static int 279*0Sstevel@tonic-gate kbdopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) 280*0Sstevel@tonic-gate { 281*0Sstevel@tonic-gate register int error; 282*0Sstevel@tonic-gate register struct kbddata *kbdd; 283*0Sstevel@tonic-gate mblk_t *mp; 284*0Sstevel@tonic-gate mblk_t *datap; 285*0Sstevel@tonic-gate register struct iocblk *iocb; 286*0Sstevel@tonic-gate register struct termios *cb; 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate /* Set these up only once so that they could be changed from adb */ 289*0Sstevel@tonic-gate if (!kbd_repeatrate) { 290*0Sstevel@tonic-gate kbd_repeatrate = (hz+29)/30; 291*0Sstevel@tonic-gate kbd_repeatdelay = hz/2; 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate if (q->q_ptr != NULL) 295*0Sstevel@tonic-gate return (0); /* already attached */ 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate /* 298*0Sstevel@tonic-gate * Only allow open requests to succeed for privileged users. This 299*0Sstevel@tonic-gate * necessary to prevent users from pushing the "kb" module again 300*0Sstevel@tonic-gate * on the stream associated with /dev/kbd. 301*0Sstevel@tonic-gate */ 302*0Sstevel@tonic-gate if (secpolicy_console(crp) != 0) { 303*0Sstevel@tonic-gate return (EPERM); 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate switch (sflag) { 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate case MODOPEN: 310*0Sstevel@tonic-gate break; 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate case CLONEOPEN: 313*0Sstevel@tonic-gate return (EINVAL); /* No Bozos! */ 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate /* allocate keyboard */ 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate kbdd = kmem_zalloc(sizeof (struct kbddata), KM_SLEEP); 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* 322*0Sstevel@tonic-gate * Set up queue pointers, so that the "put" procedure will accept 323*0Sstevel@tonic-gate * the reply to the "ioctl" message we send down. 324*0Sstevel@tonic-gate */ 325*0Sstevel@tonic-gate q->q_ptr = kbdd; 326*0Sstevel@tonic-gate WR(q)->q_ptr = kbdd; 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate qprocson(q); 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate /* 331*0Sstevel@tonic-gate * Setup tty modes. 332*0Sstevel@tonic-gate */ 333*0Sstevel@tonic-gate while ((mp = mkiocb(TCSETSF)) == NULL) { 334*0Sstevel@tonic-gate timeout_id_t id = qbufcall(q, sizeof (struct iocblk), BPRI_HI, 335*0Sstevel@tonic-gate dummy_callback, NULL); 336*0Sstevel@tonic-gate if (!qwait_sig(q)) { 337*0Sstevel@tonic-gate qunbufcall(q, id); 338*0Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 339*0Sstevel@tonic-gate qprocsoff(q); 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate return (EINTR); 342*0Sstevel@tonic-gate } 343*0Sstevel@tonic-gate } 344*0Sstevel@tonic-gate while ((datap = allocb(sizeof (struct termios), BPRI_HI)) == 345*0Sstevel@tonic-gate NULL) { 346*0Sstevel@tonic-gate timeout_id_t id = qbufcall(q, sizeof (struct termios), BPRI_HI, 347*0Sstevel@tonic-gate dummy_callback, NULL); 348*0Sstevel@tonic-gate if (!qwait_sig(q)) { 349*0Sstevel@tonic-gate qunbufcall(q, id); 350*0Sstevel@tonic-gate freemsg(mp); 351*0Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 352*0Sstevel@tonic-gate qprocsoff(q); 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate return (EINTR); 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate } 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate iocb = (struct iocblk *)mp->b_rptr; 359*0Sstevel@tonic-gate iocb->ioc_count = sizeof (struct termios); 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate cb = (struct termios *)datap->b_rptr; 362*0Sstevel@tonic-gate cb->c_iflag = 0; 363*0Sstevel@tonic-gate cb->c_oflag = 0; 364*0Sstevel@tonic-gate cb->c_cflag = CREAD|CS8|B1200; 365*0Sstevel@tonic-gate cb->c_lflag = 0; 366*0Sstevel@tonic-gate bzero(cb->c_cc, NCCS); 367*0Sstevel@tonic-gate datap->b_wptr += sizeof (struct termios); 368*0Sstevel@tonic-gate mp->b_cont = datap; 369*0Sstevel@tonic-gate kbdd->kbdd_flags |= KBD_IOCWAIT; /* indicate that we're */ 370*0Sstevel@tonic-gate kbdd->kbdd_iocid = iocb->ioc_id; /* waiting for this response */ 371*0Sstevel@tonic-gate putnext(WR(q), mp); 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate /* 374*0Sstevel@tonic-gate * Now wait for it. Let our read queue put routine wake us up 375*0Sstevel@tonic-gate * when it arrives. 376*0Sstevel@tonic-gate */ 377*0Sstevel@tonic-gate while (kbdd->kbdd_flags & KBD_IOCWAIT) { 378*0Sstevel@tonic-gate if (!qwait_sig(q)) { 379*0Sstevel@tonic-gate error = EINTR; 380*0Sstevel@tonic-gate goto error; 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate if ((error = kbdd->kbdd_iocerror) != 0) 384*0Sstevel@tonic-gate goto error; 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate /* 387*0Sstevel@tonic-gate * Set up private data. 388*0Sstevel@tonic-gate */ 389*0Sstevel@tonic-gate kbdd->kbdd_readq = q; 390*0Sstevel@tonic-gate kbdd->kbdd_writeq = WR(q); 391*0Sstevel@tonic-gate kbdd->kbdd_iocpending = NULL; 392*0Sstevel@tonic-gate kbdd->kbdd_translatable = TR_CAN; 393*0Sstevel@tonic-gate kbdd->kbdd_translate = TR_ASCII; 394*0Sstevel@tonic-gate kbdd->kbdd_compat = 1; 395*0Sstevel@tonic-gate kbdd->kbdd_ascii_addr = ASCII_FIRST; 396*0Sstevel@tonic-gate kbdd->kbdd_top_addr = TOP_FIRST; 397*0Sstevel@tonic-gate kbdd->kbdd_vkey_addr = VKEY_FIRST; 398*0Sstevel@tonic-gate /* Allocate dynamic memory for downs table */ 399*0Sstevel@tonic-gate kbdd->kbdd_downs_entries = kbd_downs_size; 400*0Sstevel@tonic-gate kbdd->kbdd_downs_bytes = kbd_downs_size * sizeof (Key_event); 401*0Sstevel@tonic-gate kbdd->kbdd_downs = kmem_alloc(kbdd->kbdd_downs_bytes, KM_SLEEP); 402*0Sstevel@tonic-gate kbdd->kbdd_flags = KBD_OPEN; 403*0Sstevel@tonic-gate kbdd->led_state = 0; 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate /* 406*0Sstevel@tonic-gate * Reset kbd. 407*0Sstevel@tonic-gate */ 408*0Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate return (0); 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate error: 413*0Sstevel@tonic-gate qprocsoff(q); 414*0Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 415*0Sstevel@tonic-gate return (error); 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate /* 419*0Sstevel@tonic-gate * Close a keyboard. 420*0Sstevel@tonic-gate */ 421*0Sstevel@tonic-gate /* ARGSUSED1 */ 422*0Sstevel@tonic-gate static int 423*0Sstevel@tonic-gate kbdclose(register queue_t *q, int flag, cred_t *crp) 424*0Sstevel@tonic-gate { 425*0Sstevel@tonic-gate register struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 426*0Sstevel@tonic-gate register mblk_t *mp; 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate qprocsoff(q); 429*0Sstevel@tonic-gate /* 430*0Sstevel@tonic-gate * Since we're about to destroy our private data, turn off 431*0Sstevel@tonic-gate * our open flag first, so we don't accept any more input 432*0Sstevel@tonic-gate * and try to use that data. 433*0Sstevel@tonic-gate */ 434*0Sstevel@tonic-gate kbdd->kbdd_flags = 0; 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) { 437*0Sstevel@tonic-gate /* 438*0Sstevel@tonic-gate * There was a KIOCLAYOUT pending; presumably, it timed out. 439*0Sstevel@tonic-gate * Throw the reply away. 440*0Sstevel@tonic-gate */ 441*0Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 442*0Sstevel@tonic-gate freemsg(mp); 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate /* clear all timeouts */ 446*0Sstevel@tonic-gate if (kbdd->kbdd_bufcallid) 447*0Sstevel@tonic-gate qunbufcall(q, kbdd->kbdd_bufcallid); 448*0Sstevel@tonic-gate if (kbdd->kbdd_rptid) 449*0Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_rptid); 450*0Sstevel@tonic-gate if (kbdd->kbdd_layoutid) 451*0Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_layoutid); 452*0Sstevel@tonic-gate kmem_free(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes); 453*0Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 454*0Sstevel@tonic-gate return (0); 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate /* 458*0Sstevel@tonic-gate * Line discipline output queue put procedure: handles M_IOCTL 459*0Sstevel@tonic-gate * messages. 460*0Sstevel@tonic-gate */ 461*0Sstevel@tonic-gate static void 462*0Sstevel@tonic-gate kbdwput(register queue_t *q, register mblk_t *mp) 463*0Sstevel@tonic-gate { 464*0Sstevel@tonic-gate /* 465*0Sstevel@tonic-gate * Process M_FLUSH, and some M_IOCTL, messages here; pass 466*0Sstevel@tonic-gate * everything else down. 467*0Sstevel@tonic-gate */ 468*0Sstevel@tonic-gate switch (mp->b_datap->db_type) { 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate case M_FLUSH: 471*0Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 472*0Sstevel@tonic-gate flushq(q, FLUSHDATA); 473*0Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 474*0Sstevel@tonic-gate flushq(RD(q), FLUSHDATA); 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate default: 477*0Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */ 478*0Sstevel@tonic-gate break; 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate case M_IOCTL: 481*0Sstevel@tonic-gate kbdioctl(q, mp); 482*0Sstevel@tonic-gate break; 483*0Sstevel@tonic-gate } 484*0Sstevel@tonic-gate } 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate static void 488*0Sstevel@tonic-gate kbdreioctl(void *kbdd_addr) 489*0Sstevel@tonic-gate { 490*0Sstevel@tonic-gate struct kbddata *kbdd = kbdd_addr; 491*0Sstevel@tonic-gate queue_t *q; 492*0Sstevel@tonic-gate mblk_t *mp; 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate kbdd->kbdd_bufcallid = 0; 495*0Sstevel@tonic-gate q = kbdd->kbdd_writeq; 496*0Sstevel@tonic-gate if ((mp = kbdd->kbdd_iocpending) != NULL) { 497*0Sstevel@tonic-gate kbdd->kbdd_iocpending = NULL; /* not pending any more */ 498*0Sstevel@tonic-gate kbdioctl(q, mp); 499*0Sstevel@tonic-gate } 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate static void 503*0Sstevel@tonic-gate kbdioctl(register queue_t *q, register mblk_t *mp) 504*0Sstevel@tonic-gate { 505*0Sstevel@tonic-gate register struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 506*0Sstevel@tonic-gate register struct iocblk *iocp; 507*0Sstevel@tonic-gate register short new_translate; 508*0Sstevel@tonic-gate register Vuid_addr_probe *addr_probe; 509*0Sstevel@tonic-gate register short *addr_ptr; 510*0Sstevel@tonic-gate mblk_t *datap; 511*0Sstevel@tonic-gate size_t ioctlrespsize; 512*0Sstevel@tonic-gate int err = 0; 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate switch (iocp->ioc_cmd) { 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate case VUIDSFORMAT: 519*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 520*0Sstevel@tonic-gate if (err != 0) 521*0Sstevel@tonic-gate break; 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ? 524*0Sstevel@tonic-gate TR_ASCII : TR_EVENT; 525*0Sstevel@tonic-gate if (new_translate == kbdd->kbdd_translate) 526*0Sstevel@tonic-gate break; 527*0Sstevel@tonic-gate kbdd->kbdd_translate = new_translate; 528*0Sstevel@tonic-gate goto output_format_change; 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate case KIOCTRANS: 531*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 532*0Sstevel@tonic-gate if (err != 0) 533*0Sstevel@tonic-gate break; 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate new_translate = *(int *)mp->b_cont->b_rptr; 536*0Sstevel@tonic-gate if (new_translate == kbdd->kbdd_translate) 537*0Sstevel@tonic-gate break; 538*0Sstevel@tonic-gate kbdd->kbdd_translate = new_translate; 539*0Sstevel@tonic-gate goto output_format_change; 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate case KIOCCMD: 542*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 543*0Sstevel@tonic-gate if (err != 0) 544*0Sstevel@tonic-gate break; 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate kbdcmd(q, (char)(*(int *)mp->b_cont->b_rptr)); 547*0Sstevel@tonic-gate break; 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate case KIOCSLED: 550*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (uchar_t)); 551*0Sstevel@tonic-gate if (err != 0) 552*0Sstevel@tonic-gate break; 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate kbdd->led_state = *(uchar_t *)mp->b_cont->b_rptr; 555*0Sstevel@tonic-gate kbdsetled(kbdd); 556*0Sstevel@tonic-gate break; 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate case KIOCGLED: 559*0Sstevel@tonic-gate if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) { 560*0Sstevel@tonic-gate ioctlrespsize = sizeof (int); 561*0Sstevel@tonic-gate goto allocfailure; 562*0Sstevel@tonic-gate } 563*0Sstevel@tonic-gate *(uchar_t *)datap->b_wptr = kbdd->led_state; 564*0Sstevel@tonic-gate datap->b_wptr += sizeof (uchar_t); 565*0Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 566*0Sstevel@tonic-gate freemsg(mp->b_cont); 567*0Sstevel@tonic-gate mp->b_cont = datap; 568*0Sstevel@tonic-gate iocp->ioc_count = sizeof (uchar_t); 569*0Sstevel@tonic-gate break; 570*0Sstevel@tonic-gate 571*0Sstevel@tonic-gate case VUIDGFORMAT: 572*0Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 573*0Sstevel@tonic-gate ioctlrespsize = sizeof (int); 574*0Sstevel@tonic-gate goto allocfailure; 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate *(int *)datap->b_wptr = 577*0Sstevel@tonic-gate (kbdd->kbdd_translate == TR_EVENT || 578*0Sstevel@tonic-gate kbdd->kbdd_translate == TR_UNTRANS_EVENT) ? 579*0Sstevel@tonic-gate VUID_FIRM_EVENT: VUID_NATIVE; 580*0Sstevel@tonic-gate datap->b_wptr += sizeof (int); 581*0Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 582*0Sstevel@tonic-gate freemsg(mp->b_cont); 583*0Sstevel@tonic-gate mp->b_cont = datap; 584*0Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 585*0Sstevel@tonic-gate break; 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate case KIOCGTRANS: 588*0Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 589*0Sstevel@tonic-gate ioctlrespsize = sizeof (int); 590*0Sstevel@tonic-gate goto allocfailure; 591*0Sstevel@tonic-gate } 592*0Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_translate; 593*0Sstevel@tonic-gate datap->b_wptr += sizeof (int); 594*0Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 595*0Sstevel@tonic-gate freemsg(mp->b_cont); 596*0Sstevel@tonic-gate mp->b_cont = datap; 597*0Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 598*0Sstevel@tonic-gate break; 599*0Sstevel@tonic-gate 600*0Sstevel@tonic-gate case VUIDSADDR: 601*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe)); 602*0Sstevel@tonic-gate if (err != 0) 603*0Sstevel@tonic-gate break; 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 606*0Sstevel@tonic-gate switch (addr_probe->base) { 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate case ASCII_FIRST: 609*0Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_ascii_addr; 610*0Sstevel@tonic-gate break; 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate case TOP_FIRST: 613*0Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_top_addr; 614*0Sstevel@tonic-gate break; 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate case VKEY_FIRST: 617*0Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_vkey_addr; 618*0Sstevel@tonic-gate break; 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate default: 621*0Sstevel@tonic-gate err = ENODEV; 622*0Sstevel@tonic-gate } 623*0Sstevel@tonic-gate if ((err == 0) && (*addr_ptr != addr_probe->data.next)) { 624*0Sstevel@tonic-gate *addr_ptr = addr_probe->data.next; 625*0Sstevel@tonic-gate goto output_format_change; 626*0Sstevel@tonic-gate } 627*0Sstevel@tonic-gate break; 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate case VUIDGADDR: 630*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe)); 631*0Sstevel@tonic-gate if (err != 0) 632*0Sstevel@tonic-gate break; 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 635*0Sstevel@tonic-gate switch (addr_probe->base) { 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate case ASCII_FIRST: 638*0Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_ascii_addr; 639*0Sstevel@tonic-gate break; 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate case TOP_FIRST: 642*0Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_top_addr; 643*0Sstevel@tonic-gate break; 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate case VKEY_FIRST: 646*0Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_vkey_addr; 647*0Sstevel@tonic-gate break; 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate default: 650*0Sstevel@tonic-gate err = ENODEV; 651*0Sstevel@tonic-gate } 652*0Sstevel@tonic-gate break; 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate case KIOCTRANSABLE: 655*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 656*0Sstevel@tonic-gate if (err != 0) 657*0Sstevel@tonic-gate break; 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate if (kbdd->kbdd_translatable != *(int *)mp->b_cont->b_rptr) { 660*0Sstevel@tonic-gate kbdd->kbdd_translatable = *(int *)mp->b_cont->b_rptr; 661*0Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 662*0Sstevel@tonic-gate goto output_format_change; 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate break; 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate case KIOCGTRANSABLE: 667*0Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 668*0Sstevel@tonic-gate ioctlrespsize = sizeof (int); 669*0Sstevel@tonic-gate goto allocfailure; 670*0Sstevel@tonic-gate } 671*0Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_translatable; 672*0Sstevel@tonic-gate datap->b_wptr += sizeof (int); 673*0Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 674*0Sstevel@tonic-gate freemsg(mp->b_cont); 675*0Sstevel@tonic-gate mp->b_cont = datap; 676*0Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 677*0Sstevel@tonic-gate break; 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate case KIOCSCOMPAT: 680*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 681*0Sstevel@tonic-gate if (err != 0) 682*0Sstevel@tonic-gate break; 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate kbdd->kbdd_compat = *(int *)mp->b_cont->b_rptr; 685*0Sstevel@tonic-gate break; 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate case KIOCGCOMPAT: 688*0Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 689*0Sstevel@tonic-gate ioctlrespsize = sizeof (int); 690*0Sstevel@tonic-gate goto allocfailure; 691*0Sstevel@tonic-gate } 692*0Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_compat; 693*0Sstevel@tonic-gate datap->b_wptr += sizeof (int); 694*0Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 695*0Sstevel@tonic-gate freemsg(mp->b_cont); 696*0Sstevel@tonic-gate mp->b_cont = datap; 697*0Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 698*0Sstevel@tonic-gate break; 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate case KIOCSETKEY: 701*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockey)); 702*0Sstevel@tonic-gate if (err != 0) 703*0Sstevel@tonic-gate break; 704*0Sstevel@tonic-gate 705*0Sstevel@tonic-gate err = kbdsetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr, 706*0Sstevel@tonic-gate iocp->ioc_cr); 707*0Sstevel@tonic-gate /* 708*0Sstevel@tonic-gate * Since this only affects any subsequent key presses, 709*0Sstevel@tonic-gate * don't goto output_format_change. One might want to 710*0Sstevel@tonic-gate * toggle the keytable entries dynamically. 711*0Sstevel@tonic-gate */ 712*0Sstevel@tonic-gate break; 713*0Sstevel@tonic-gate 714*0Sstevel@tonic-gate case KIOCGETKEY: 715*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockey)); 716*0Sstevel@tonic-gate if (err != 0) 717*0Sstevel@tonic-gate break; 718*0Sstevel@tonic-gate 719*0Sstevel@tonic-gate err = kbdgetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr); 720*0Sstevel@tonic-gate break; 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate case KIOCSKEY: 723*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockeymap)); 724*0Sstevel@tonic-gate if (err != 0) 725*0Sstevel@tonic-gate break; 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate err = kbdskey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr, 728*0Sstevel@tonic-gate iocp->ioc_cr); 729*0Sstevel@tonic-gate /* 730*0Sstevel@tonic-gate * Since this only affects any subsequent key presses, 731*0Sstevel@tonic-gate * don't goto output_format_change. One might want to 732*0Sstevel@tonic-gate * toggle the keytable entries dynamically. 733*0Sstevel@tonic-gate */ 734*0Sstevel@tonic-gate break; 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate case KIOCGKEY: 737*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockeymap)); 738*0Sstevel@tonic-gate if (err != 0) 739*0Sstevel@tonic-gate break; 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate err = kbdgkey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr); 742*0Sstevel@tonic-gate break; 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate case KIOCSDIRECT: 745*0Sstevel@tonic-gate goto output_format_change; 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate case KIOCGDIRECT: 748*0Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 749*0Sstevel@tonic-gate ioctlrespsize = sizeof (int); 750*0Sstevel@tonic-gate goto allocfailure; 751*0Sstevel@tonic-gate } 752*0Sstevel@tonic-gate *(int *)datap->b_wptr = 1; /* always direct */ 753*0Sstevel@tonic-gate datap->b_wptr += sizeof (int); 754*0Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 755*0Sstevel@tonic-gate freemsg(mp->b_cont); 756*0Sstevel@tonic-gate mp->b_cont = datap; 757*0Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 758*0Sstevel@tonic-gate break; 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate case KIOCTYPE: 761*0Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 762*0Sstevel@tonic-gate ioctlrespsize = sizeof (int); 763*0Sstevel@tonic-gate goto allocfailure; 764*0Sstevel@tonic-gate } 765*0Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_state.k_id; 766*0Sstevel@tonic-gate datap->b_wptr += sizeof (int); 767*0Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 768*0Sstevel@tonic-gate freemsg(mp->b_cont); 769*0Sstevel@tonic-gate mp->b_cont = datap; 770*0Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 771*0Sstevel@tonic-gate break; 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate case KIOCLAYOUT: 774*0Sstevel@tonic-gate if ((datap = kbdd->kbdd_replypending) != NULL) { 775*0Sstevel@tonic-gate /* 776*0Sstevel@tonic-gate * There was an earlier KIOCLAYOUT pending; presumably, 777*0Sstevel@tonic-gate * it timed out. Throw the reply away. 778*0Sstevel@tonic-gate */ 779*0Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 780*0Sstevel@tonic-gate freemsg(datap); 781*0Sstevel@tonic-gate } 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate if (kbdd->kbdd_state.k_id == KB_SUN4 || 784*0Sstevel@tonic-gate kbdd->kbdd_state.k_id == KB_PC) { 785*0Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 786*0Sstevel@tonic-gate ioctlrespsize = sizeof (int); 787*0Sstevel@tonic-gate goto allocfailure; 788*0Sstevel@tonic-gate } 789*0Sstevel@tonic-gate iocp->ioc_rval = 0; 790*0Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */ 791*0Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 792*0Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 793*0Sstevel@tonic-gate freemsg(mp->b_cont); 794*0Sstevel@tonic-gate mp->b_cont = datap; 795*0Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 796*0Sstevel@tonic-gate kbdd->kbdd_replypending = mp; 797*0Sstevel@tonic-gate kbdcmd(q, (char)KBD_CMD_GETLAYOUT); 798*0Sstevel@tonic-gate if (kbdd->kbdd_layoutid) 799*0Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_layoutid); 800*0Sstevel@tonic-gate kbdd->kbdd_layoutid = qtimeout(q, kbdlayouttimeout, 801*0Sstevel@tonic-gate kbdd, hz / 5); 802*0Sstevel@tonic-gate return; /* wait for reply from keyboard */ 803*0Sstevel@tonic-gate } else { 804*0Sstevel@tonic-gate /* 805*0Sstevel@tonic-gate * Not a Type 4 keyboard; return an immediate error. 806*0Sstevel@tonic-gate */ 807*0Sstevel@tonic-gate err = EINVAL; 808*0Sstevel@tonic-gate break; 809*0Sstevel@tonic-gate } 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate case KIOCGRPTDELAY: 812*0Sstevel@tonic-gate /* 813*0Sstevel@tonic-gate * Report the autorepeat delay, unit in millisecond 814*0Sstevel@tonic-gate */ 815*0Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 816*0Sstevel@tonic-gate ioctlrespsize = sizeof (int); 817*0Sstevel@tonic-gate goto allocfailure; 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatdelay); 820*0Sstevel@tonic-gate datap->b_wptr += sizeof (int); 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate /* free msg to prevent memory leak */ 823*0Sstevel@tonic-gate if (mp->b_cont != NULL) 824*0Sstevel@tonic-gate freemsg(mp->b_cont); 825*0Sstevel@tonic-gate mp->b_cont = datap; 826*0Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 827*0Sstevel@tonic-gate break; 828*0Sstevel@tonic-gate 829*0Sstevel@tonic-gate case KIOCSRPTDELAY: 830*0Sstevel@tonic-gate /* 831*0Sstevel@tonic-gate * Set the autorepeat delay 832*0Sstevel@tonic-gate */ 833*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate if (err != 0) 836*0Sstevel@tonic-gate break; 837*0Sstevel@tonic-gate 838*0Sstevel@tonic-gate /* validate the input */ 839*0Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) { 840*0Sstevel@tonic-gate err = EINVAL; 841*0Sstevel@tonic-gate break; 842*0Sstevel@tonic-gate } 843*0Sstevel@tonic-gate kbd_repeatdelay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 844*0Sstevel@tonic-gate if (kbd_repeatdelay <= 0) 845*0Sstevel@tonic-gate kbd_repeatdelay = 1; 846*0Sstevel@tonic-gate break; 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate case KIOCGRPTRATE: 849*0Sstevel@tonic-gate /* 850*0Sstevel@tonic-gate * Report the autorepeat rate 851*0Sstevel@tonic-gate */ 852*0Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 853*0Sstevel@tonic-gate ioctlrespsize = sizeof (int); 854*0Sstevel@tonic-gate goto allocfailure; 855*0Sstevel@tonic-gate } 856*0Sstevel@tonic-gate *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatrate); 857*0Sstevel@tonic-gate datap->b_wptr += sizeof (int); 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate /* free msg to prevent memory leak */ 860*0Sstevel@tonic-gate if (mp->b_cont != NULL) 861*0Sstevel@tonic-gate freemsg(mp->b_cont); 862*0Sstevel@tonic-gate mp->b_cont = datap; 863*0Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 864*0Sstevel@tonic-gate break; 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate case KIOCSRPTRATE: 867*0Sstevel@tonic-gate /* 868*0Sstevel@tonic-gate * Set the autorepeat rate 869*0Sstevel@tonic-gate */ 870*0Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 871*0Sstevel@tonic-gate 872*0Sstevel@tonic-gate if (err != 0) 873*0Sstevel@tonic-gate break; 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate /* validate the input */ 876*0Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) { 877*0Sstevel@tonic-gate err = EINVAL; 878*0Sstevel@tonic-gate break; 879*0Sstevel@tonic-gate } 880*0Sstevel@tonic-gate kbd_repeatrate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 881*0Sstevel@tonic-gate if (kbd_repeatrate <= 0) 882*0Sstevel@tonic-gate kbd_repeatrate = 1; 883*0Sstevel@tonic-gate break; 884*0Sstevel@tonic-gate 885*0Sstevel@tonic-gate default: 886*0Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */ 887*0Sstevel@tonic-gate return; 888*0Sstevel@tonic-gate } 889*0Sstevel@tonic-gate goto done; 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate output_format_change: 892*0Sstevel@tonic-gate kbdflush(kbdd); 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate done: 895*0Sstevel@tonic-gate if (err != 0) { 896*0Sstevel@tonic-gate iocp->ioc_rval = 0; 897*0Sstevel@tonic-gate iocp->ioc_error = err; 898*0Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK; 899*0Sstevel@tonic-gate } else { 900*0Sstevel@tonic-gate iocp->ioc_rval = 0; 901*0Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */ 902*0Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 903*0Sstevel@tonic-gate } 904*0Sstevel@tonic-gate qreply(q, mp); 905*0Sstevel@tonic-gate return; 906*0Sstevel@tonic-gate 907*0Sstevel@tonic-gate allocfailure: 908*0Sstevel@tonic-gate /* 909*0Sstevel@tonic-gate * We needed to allocate something to handle this "ioctl", but 910*0Sstevel@tonic-gate * couldn't; save this "ioctl" and arrange to get called back when 911*0Sstevel@tonic-gate * it's more likely that we can get what we need. 912*0Sstevel@tonic-gate * If there's already one being saved, throw it out, since it 913*0Sstevel@tonic-gate * must have timed out. 914*0Sstevel@tonic-gate */ 915*0Sstevel@tonic-gate if (kbdd->kbdd_iocpending != NULL) 916*0Sstevel@tonic-gate freemsg(kbdd->kbdd_iocpending); 917*0Sstevel@tonic-gate kbdd->kbdd_iocpending = mp; 918*0Sstevel@tonic-gate if (kbdd->kbdd_bufcallid) 919*0Sstevel@tonic-gate qunbufcall(q, kbdd->kbdd_bufcallid); 920*0Sstevel@tonic-gate kbdd->kbdd_bufcallid = qbufcall(q, ioctlrespsize, BPRI_HI, 921*0Sstevel@tonic-gate kbdreioctl, kbdd); 922*0Sstevel@tonic-gate } 923*0Sstevel@tonic-gate 924*0Sstevel@tonic-gate static void 925*0Sstevel@tonic-gate kbdflush(register struct kbddata *kbdd) 926*0Sstevel@tonic-gate { 927*0Sstevel@tonic-gate register queue_t *q; 928*0Sstevel@tonic-gate 929*0Sstevel@tonic-gate /* Flush pending data already sent upstream */ 930*0Sstevel@tonic-gate if ((q = kbdd->kbdd_readq) != NULL && q->q_next != NULL) 931*0Sstevel@tonic-gate (void) putnextctl1(q, M_FLUSH, FLUSHR); 932*0Sstevel@tonic-gate /* Flush pending ups */ 933*0Sstevel@tonic-gate bzero(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes); 934*0Sstevel@tonic-gate kbdcancelrpt(kbdd); 935*0Sstevel@tonic-gate } 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate /* 938*0Sstevel@tonic-gate * Pass keycode upstream, either translated or untranslated. 939*0Sstevel@tonic-gate */ 940*0Sstevel@tonic-gate static void 941*0Sstevel@tonic-gate kbduse(register struct kbddata *kbdd, unsigned keycode) 942*0Sstevel@tonic-gate { 943*0Sstevel@tonic-gate register queue_t *readq; 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate #ifdef KBD_DEBUG 946*0Sstevel@tonic-gate if (kbd_input_debug) printf("KBD USE key=%d\n", keycode); 947*0Sstevel@tonic-gate #endif 948*0Sstevel@tonic-gate 949*0Sstevel@tonic-gate if ((readq = kbdd->kbdd_readq) == NULL) 950*0Sstevel@tonic-gate return; 951*0Sstevel@tonic-gate if (!kbdd->kbdd_translatable || 952*0Sstevel@tonic-gate kbdd->kbdd_translate == TR_NONE) 953*0Sstevel@tonic-gate kbdputcode(keycode, readq); 954*0Sstevel@tonic-gate else 955*0Sstevel@tonic-gate kbdtranslate(kbdd, keycode, readq); 956*0Sstevel@tonic-gate } 957*0Sstevel@tonic-gate 958*0Sstevel@tonic-gate /* 959*0Sstevel@tonic-gate * kbdclick is used to remember the current click value of the 960*0Sstevel@tonic-gate * Sun-3 keyboard. This brain damaged keyboard will reset the 961*0Sstevel@tonic-gate * clicking to the "default" value after a reset command and 962*0Sstevel@tonic-gate * there is no way to read out the current click value. We 963*0Sstevel@tonic-gate * cannot send a click command immediately after the reset 964*0Sstevel@tonic-gate * command or the keyboard gets screwed up. So we wait until 965*0Sstevel@tonic-gate * we get the ID byte before we send back the click command. 966*0Sstevel@tonic-gate * Unfortunately, this means that there is a small window 967*0Sstevel@tonic-gate * where the keyboard can click when it really shouldn't be. 968*0Sstevel@tonic-gate * A value of -1 means that kbdclick has not been initialized yet. 969*0Sstevel@tonic-gate */ 970*0Sstevel@tonic-gate static int kbdclick = -1; 971*0Sstevel@tonic-gate 972*0Sstevel@tonic-gate /* 973*0Sstevel@tonic-gate * Send command byte to keyboard, if you can. 974*0Sstevel@tonic-gate */ 975*0Sstevel@tonic-gate static void 976*0Sstevel@tonic-gate kbdcmd(register queue_t *q, char cmd) 977*0Sstevel@tonic-gate { 978*0Sstevel@tonic-gate register mblk_t *bp; 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate if (canput(q)) { 981*0Sstevel@tonic-gate if ((bp = allocb(1, BPRI_MED)) == NULL) 982*0Sstevel@tonic-gate cmn_err(CE_WARN, 983*0Sstevel@tonic-gate "kbdcmd: Can't allocate block for command"); 984*0Sstevel@tonic-gate else { 985*0Sstevel@tonic-gate *bp->b_wptr++ = cmd; 986*0Sstevel@tonic-gate putnext(q, bp); 987*0Sstevel@tonic-gate if (cmd == KBD_CMD_NOCLICK) 988*0Sstevel@tonic-gate kbdclick = 0; 989*0Sstevel@tonic-gate else if (cmd == KBD_CMD_CLICK) 990*0Sstevel@tonic-gate kbdclick = 1; 991*0Sstevel@tonic-gate } 992*0Sstevel@tonic-gate } 993*0Sstevel@tonic-gate } 994*0Sstevel@tonic-gate 995*0Sstevel@tonic-gate /* 996*0Sstevel@tonic-gate * Update the keyboard LEDs to match the current keyboard state. 997*0Sstevel@tonic-gate * Do this only on Type 4 keyboards; other keyboards don't support the 998*0Sstevel@tonic-gate * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs). 999*0Sstevel@tonic-gate */ 1000*0Sstevel@tonic-gate static void 1001*0Sstevel@tonic-gate kbdsetled(register struct kbddata *kbdd) 1002*0Sstevel@tonic-gate { 1003*0Sstevel@tonic-gate if (kbdd->kbdd_state.k_id == KB_SUN4 || 1004*0Sstevel@tonic-gate kbdd->kbdd_state.k_id == KB_PC) { 1005*0Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_SETLED); 1006*0Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, kbdd->led_state); 1007*0Sstevel@tonic-gate } 1008*0Sstevel@tonic-gate } 1009*0Sstevel@tonic-gate 1010*0Sstevel@tonic-gate /* 1011*0Sstevel@tonic-gate * Reset the keyboard 1012*0Sstevel@tonic-gate */ 1013*0Sstevel@tonic-gate static void 1014*0Sstevel@tonic-gate kbdreset(register struct kbddata *kbdd, uint_t hard_reset) 1015*0Sstevel@tonic-gate { 1016*0Sstevel@tonic-gate register struct keyboardstate *k; 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate k = &kbdd->kbdd_state; 1019*0Sstevel@tonic-gate if (kbdd->kbdd_translatable) { 1020*0Sstevel@tonic-gate k->k_idstate = KID_NONE; 1021*0Sstevel@tonic-gate k->k_id = -1; 1022*0Sstevel@tonic-gate k->k_state = NORMAL; 1023*0Sstevel@tonic-gate if (hard_reset) 1024*0Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_RESET); 1025*0Sstevel@tonic-gate } else { 1026*0Sstevel@tonic-gate bzero(k, sizeof (struct keyboardstate)); 1027*0Sstevel@tonic-gate k->k_id = KB_ASCII; 1028*0Sstevel@tonic-gate k->k_idstate = KID_OK; 1029*0Sstevel@tonic-gate } 1030*0Sstevel@tonic-gate } 1031*0Sstevel@tonic-gate 1032*0Sstevel@tonic-gate /* 1033*0Sstevel@tonic-gate * Old special codes. 1034*0Sstevel@tonic-gate */ 1035*0Sstevel@tonic-gate #define OLD_SHIFTKEYS 0x80 1036*0Sstevel@tonic-gate #define OLD_BUCKYBITS 0x90 1037*0Sstevel@tonic-gate #define OLD_FUNNY 0xA0 1038*0Sstevel@tonic-gate #define OLD_FA_UMLAUT 0xA9 1039*0Sstevel@tonic-gate #define OLD_FA_CFLEX 0xAA 1040*0Sstevel@tonic-gate #define OLD_FA_TILDE 0xAB 1041*0Sstevel@tonic-gate #define OLD_FA_CEDILLA 0xAC 1042*0Sstevel@tonic-gate #define OLD_FA_ACUTE 0xAD 1043*0Sstevel@tonic-gate #define OLD_FA_GRAVE 0xAE 1044*0Sstevel@tonic-gate #define OLD_ISOCHAR 0xAF 1045*0Sstevel@tonic-gate #define OLD_STRING 0xB0 1046*0Sstevel@tonic-gate #define OLD_LEFTFUNC 0xC0 1047*0Sstevel@tonic-gate #define OLD_RIGHTFUNC 0xD0 1048*0Sstevel@tonic-gate #define OLD_TOPFUNC 0xE0 1049*0Sstevel@tonic-gate #define OLD_BOTTOMFUNC 0xF0 1050*0Sstevel@tonic-gate 1051*0Sstevel@tonic-gate /* 1052*0Sstevel@tonic-gate * Map old special codes to new ones. 1053*0Sstevel@tonic-gate * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F. 1054*0Sstevel@tonic-gate */ 1055*0Sstevel@tonic-gate static ushort_t special_old_to_new[] = { 1056*0Sstevel@tonic-gate SHIFTKEYS, 1057*0Sstevel@tonic-gate BUCKYBITS, 1058*0Sstevel@tonic-gate FUNNY, 1059*0Sstevel@tonic-gate STRING, 1060*0Sstevel@tonic-gate LEFTFUNC, 1061*0Sstevel@tonic-gate RIGHTFUNC, 1062*0Sstevel@tonic-gate TOPFUNC, 1063*0Sstevel@tonic-gate BOTTOMFUNC, 1064*0Sstevel@tonic-gate }; 1065*0Sstevel@tonic-gate 1066*0Sstevel@tonic-gate /* 1067*0Sstevel@tonic-gate * Set individual keystation translation from old-style entry. 1068*0Sstevel@tonic-gate * TODO: Have each keyboard own own translation tables. 1069*0Sstevel@tonic-gate */ 1070*0Sstevel@tonic-gate static int 1071*0Sstevel@tonic-gate kbdsetkey(register struct kbddata *kbdd, struct kiockey *key, cred_t *cr) 1072*0Sstevel@tonic-gate { 1073*0Sstevel@tonic-gate int strtabindex, i; 1074*0Sstevel@tonic-gate struct keymap *km; 1075*0Sstevel@tonic-gate register int tablemask; 1076*0Sstevel@tonic-gate register ushort_t entry; 1077*0Sstevel@tonic-gate 1078*0Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 1079*0Sstevel@tonic-gate return (EINVAL); 1080*0Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 1081*0Sstevel@tonic-gate return (EINVAL); 1082*0Sstevel@tonic-gate tablemask = key->kio_tablemask; 1083*0Sstevel@tonic-gate if (tablemask == KIOCABORT1) { 1084*0Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 1085*0Sstevel@tonic-gate return (EPERM); 1086*0Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station; 1087*0Sstevel@tonic-gate return (0); 1088*0Sstevel@tonic-gate } 1089*0Sstevel@tonic-gate if (tablemask == KIOCABORT2) { 1090*0Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 1091*0Sstevel@tonic-gate return (EPERM); 1092*0Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station; 1093*0Sstevel@tonic-gate return (0); 1094*0Sstevel@tonic-gate } 1095*0Sstevel@tonic-gate if ((tablemask & ALTGRAPHMASK) || 1096*0Sstevel@tonic-gate (km = settable(kbdd, (uint_t)tablemask)) == NULL) 1097*0Sstevel@tonic-gate return (EINVAL); 1098*0Sstevel@tonic-gate if (key->kio_entry >= (uchar_t)OLD_STRING && 1099*0Sstevel@tonic-gate key->kio_entry <= (uchar_t)(OLD_STRING + 15)) { 1100*0Sstevel@tonic-gate strtabindex = key->kio_entry - OLD_STRING; 1101*0Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 1102*0Sstevel@tonic-gate keystringtab[strtabindex][i] = key->kio_string[i]; 1103*0Sstevel@tonic-gate keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 1104*0Sstevel@tonic-gate } 1105*0Sstevel@tonic-gate entry = key->kio_entry; 1106*0Sstevel@tonic-gate /* 1107*0Sstevel@tonic-gate * There's nothing we need do with OLD_ISOCHAR. 1108*0Sstevel@tonic-gate */ 1109*0Sstevel@tonic-gate if (entry != OLD_ISOCHAR) { 1110*0Sstevel@tonic-gate if (entry & 0x80) { 1111*0Sstevel@tonic-gate if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE) 1112*0Sstevel@tonic-gate entry = FA_CLASS + (entry & 0x0F) - 9; 1113*0Sstevel@tonic-gate else 1114*0Sstevel@tonic-gate entry = 1115*0Sstevel@tonic-gate special_old_to_new[entry >> 4 & 0x07] 1116*0Sstevel@tonic-gate + (entry & 0x0F); 1117*0Sstevel@tonic-gate } 1118*0Sstevel@tonic-gate } 1119*0Sstevel@tonic-gate km->keymap[key->kio_station] = entry; 1120*0Sstevel@tonic-gate return (0); 1121*0Sstevel@tonic-gate } 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate /* 1124*0Sstevel@tonic-gate * Map new special codes to old ones. 1125*0Sstevel@tonic-gate * Indexed by (new special code) >> 8; add (new special code) & 0xFF. 1126*0Sstevel@tonic-gate */ 1127*0Sstevel@tonic-gate static uchar_t special_new_to_old[] = { 1128*0Sstevel@tonic-gate 0, /* normal */ 1129*0Sstevel@tonic-gate OLD_SHIFTKEYS, /* SHIFTKEYS */ 1130*0Sstevel@tonic-gate OLD_BUCKYBITS, /* BUCKYBITS */ 1131*0Sstevel@tonic-gate OLD_FUNNY, /* FUNNY */ 1132*0Sstevel@tonic-gate OLD_FA_UMLAUT, /* FA_CLASS */ 1133*0Sstevel@tonic-gate OLD_STRING, /* STRING */ 1134*0Sstevel@tonic-gate OLD_LEFTFUNC, /* FUNCKEYS */ 1135*0Sstevel@tonic-gate }; 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate /* 1138*0Sstevel@tonic-gate * Get individual keystation translation as old-style entry. 1139*0Sstevel@tonic-gate */ 1140*0Sstevel@tonic-gate static int 1141*0Sstevel@tonic-gate kbdgetkey(register struct kbddata *kbdd, struct kiockey *key) 1142*0Sstevel@tonic-gate { 1143*0Sstevel@tonic-gate int strtabindex, i; 1144*0Sstevel@tonic-gate struct keymap *km; 1145*0Sstevel@tonic-gate register ushort_t entry; 1146*0Sstevel@tonic-gate 1147*0Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 1148*0Sstevel@tonic-gate return (EINVAL); 1149*0Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 1150*0Sstevel@tonic-gate return (EINVAL); 1151*0Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) { 1152*0Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1; 1153*0Sstevel@tonic-gate return (0); 1154*0Sstevel@tonic-gate } 1155*0Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) { 1156*0Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2; 1157*0Sstevel@tonic-gate return (0); 1158*0Sstevel@tonic-gate } 1159*0Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 1160*0Sstevel@tonic-gate return (EINVAL); 1161*0Sstevel@tonic-gate entry = km->keymap[key->kio_station]; 1162*0Sstevel@tonic-gate if (entry & 0xFF00) 1163*0Sstevel@tonic-gate key->kio_entry = 1164*0Sstevel@tonic-gate special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8] 1165*0Sstevel@tonic-gate + (entry & 0x00FF); 1166*0Sstevel@tonic-gate else { 1167*0Sstevel@tonic-gate if (entry & 0x80) 1168*0Sstevel@tonic-gate key->kio_entry = (ushort_t)OLD_ISOCHAR; /* you lose */ 1169*0Sstevel@tonic-gate else 1170*0Sstevel@tonic-gate key->kio_entry = (ushort_t)entry; 1171*0Sstevel@tonic-gate } 1172*0Sstevel@tonic-gate if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) { 1173*0Sstevel@tonic-gate strtabindex = entry - STRING; 1174*0Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 1175*0Sstevel@tonic-gate key->kio_string[i] = keystringtab[strtabindex][i]; 1176*0Sstevel@tonic-gate } 1177*0Sstevel@tonic-gate return (0); 1178*0Sstevel@tonic-gate } 1179*0Sstevel@tonic-gate 1180*0Sstevel@tonic-gate /* 1181*0Sstevel@tonic-gate * Set individual keystation translation from new-style entry. 1182*0Sstevel@tonic-gate * TODO: Have each keyboard own own translation tables. 1183*0Sstevel@tonic-gate */ 1184*0Sstevel@tonic-gate static int 1185*0Sstevel@tonic-gate kbdskey(register struct kbddata *kbdd, struct kiockeymap *key, cred_t *cr) 1186*0Sstevel@tonic-gate { 1187*0Sstevel@tonic-gate int strtabindex, i; 1188*0Sstevel@tonic-gate struct keymap *km; 1189*0Sstevel@tonic-gate 1190*0Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 1191*0Sstevel@tonic-gate return (EINVAL); 1192*0Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 1193*0Sstevel@tonic-gate return (EINVAL); 1194*0Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) { 1195*0Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 1196*0Sstevel@tonic-gate return (EPERM); 1197*0Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station; 1198*0Sstevel@tonic-gate return (0); 1199*0Sstevel@tonic-gate } 1200*0Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) { 1201*0Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 1202*0Sstevel@tonic-gate return (EPERM); 1203*0Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station; 1204*0Sstevel@tonic-gate return (0); 1205*0Sstevel@tonic-gate } 1206*0Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 1207*0Sstevel@tonic-gate return (EINVAL); 1208*0Sstevel@tonic-gate if (key->kio_entry >= STRING && 1209*0Sstevel@tonic-gate key->kio_entry <= (ushort_t)(STRING + 15)) { 1210*0Sstevel@tonic-gate strtabindex = key->kio_entry-STRING; 1211*0Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 1212*0Sstevel@tonic-gate keystringtab[strtabindex][i] = key->kio_string[i]; 1213*0Sstevel@tonic-gate keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 1214*0Sstevel@tonic-gate } 1215*0Sstevel@tonic-gate km->keymap[key->kio_station] = key->kio_entry; 1216*0Sstevel@tonic-gate return (0); 1217*0Sstevel@tonic-gate } 1218*0Sstevel@tonic-gate 1219*0Sstevel@tonic-gate /* 1220*0Sstevel@tonic-gate * Get individual keystation translation as new-style entry. 1221*0Sstevel@tonic-gate */ 1222*0Sstevel@tonic-gate static int 1223*0Sstevel@tonic-gate kbdgkey(register struct kbddata *kbdd, struct kiockeymap *key) 1224*0Sstevel@tonic-gate { 1225*0Sstevel@tonic-gate int strtabindex, i; 1226*0Sstevel@tonic-gate struct keymap *km; 1227*0Sstevel@tonic-gate 1228*0Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 1229*0Sstevel@tonic-gate return (EINVAL); 1230*0Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 1231*0Sstevel@tonic-gate return (EINVAL); 1232*0Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) { 1233*0Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1; 1234*0Sstevel@tonic-gate return (0); 1235*0Sstevel@tonic-gate } 1236*0Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) { 1237*0Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2; 1238*0Sstevel@tonic-gate return (0); 1239*0Sstevel@tonic-gate } 1240*0Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 1241*0Sstevel@tonic-gate return (EINVAL); 1242*0Sstevel@tonic-gate key->kio_entry = km->keymap[key->kio_station]; 1243*0Sstevel@tonic-gate if (key->kio_entry >= STRING && 1244*0Sstevel@tonic-gate key->kio_entry <= (ushort_t)(STRING + 15)) { 1245*0Sstevel@tonic-gate strtabindex = key->kio_entry-STRING; 1246*0Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 1247*0Sstevel@tonic-gate key->kio_string[i] = keystringtab[strtabindex][i]; 1248*0Sstevel@tonic-gate } 1249*0Sstevel@tonic-gate return (0); 1250*0Sstevel@tonic-gate } 1251*0Sstevel@tonic-gate 1252*0Sstevel@tonic-gate static void 1253*0Sstevel@tonic-gate kbdlayouttimeout(void *arg) 1254*0Sstevel@tonic-gate { 1255*0Sstevel@tonic-gate struct kbddata *kbdd = arg; 1256*0Sstevel@tonic-gate mblk_t *mp; 1257*0Sstevel@tonic-gate 1258*0Sstevel@tonic-gate kbdd->kbdd_layoutid = 0; 1259*0Sstevel@tonic-gate 1260*0Sstevel@tonic-gate /* 1261*0Sstevel@tonic-gate * Timed out waiting for reply to "get keyboard layout" command. 1262*0Sstevel@tonic-gate * Return an ETIME error. 1263*0Sstevel@tonic-gate */ 1264*0Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) { 1265*0Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 1266*0Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK; 1267*0Sstevel@tonic-gate ((struct iocblk *)mp->b_rptr)->ioc_error = ETIME; 1268*0Sstevel@tonic-gate putnext(kbdd->kbdd_readq, mp); 1269*0Sstevel@tonic-gate } 1270*0Sstevel@tonic-gate } 1271*0Sstevel@tonic-gate 1272*0Sstevel@tonic-gate /* 1273*0Sstevel@tonic-gate * Put procedure for input from driver end of stream (read queue). 1274*0Sstevel@tonic-gate */ 1275*0Sstevel@tonic-gate static void 1276*0Sstevel@tonic-gate kbdrput(register queue_t *q, register mblk_t *mp) 1277*0Sstevel@tonic-gate { 1278*0Sstevel@tonic-gate struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 1279*0Sstevel@tonic-gate register mblk_t *bp; 1280*0Sstevel@tonic-gate register uchar_t *readp; 1281*0Sstevel@tonic-gate struct iocblk *iocp; 1282*0Sstevel@tonic-gate 1283*0Sstevel@tonic-gate if (kbdd == 0) { 1284*0Sstevel@tonic-gate freemsg(mp); /* nobody's listening */ 1285*0Sstevel@tonic-gate return; 1286*0Sstevel@tonic-gate } 1287*0Sstevel@tonic-gate 1288*0Sstevel@tonic-gate switch (mp->b_datap->db_type) { 1289*0Sstevel@tonic-gate 1290*0Sstevel@tonic-gate case M_FLUSH: 1291*0Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 1292*0Sstevel@tonic-gate flushq(WR(q), FLUSHDATA); 1293*0Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 1294*0Sstevel@tonic-gate flushq(q, FLUSHDATA); 1295*0Sstevel@tonic-gate 1296*0Sstevel@tonic-gate default: 1297*0Sstevel@tonic-gate putnext(q, mp); 1298*0Sstevel@tonic-gate return; 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate case M_BREAK: 1301*0Sstevel@tonic-gate /* 1302*0Sstevel@tonic-gate * Will get M_BREAK only if this is not the system 1303*0Sstevel@tonic-gate * keyboard, otherwise serial port will eat break 1304*0Sstevel@tonic-gate * and call kmdb/OBP, without passing anything up. 1305*0Sstevel@tonic-gate */ 1306*0Sstevel@tonic-gate freemsg(mp); 1307*0Sstevel@tonic-gate return; 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gate case M_IOCACK: 1310*0Sstevel@tonic-gate case M_IOCNAK: 1311*0Sstevel@tonic-gate /* 1312*0Sstevel@tonic-gate * If we are doing an "ioctl" ourselves, check if this 1313*0Sstevel@tonic-gate * is the reply to that code. If so, wake up the 1314*0Sstevel@tonic-gate * "open" routine, and toss the reply, otherwise just 1315*0Sstevel@tonic-gate * pass it up. 1316*0Sstevel@tonic-gate */ 1317*0Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 1318*0Sstevel@tonic-gate if (!(kbdd->kbdd_flags & KBD_IOCWAIT) || 1319*0Sstevel@tonic-gate iocp->ioc_id != kbdd->kbdd_iocid) { 1320*0Sstevel@tonic-gate /* 1321*0Sstevel@tonic-gate * This isn't the reply we're looking for. Move along. 1322*0Sstevel@tonic-gate */ 1323*0Sstevel@tonic-gate if (kbdd->kbdd_flags & KBD_OPEN) 1324*0Sstevel@tonic-gate putnext(q, mp); 1325*0Sstevel@tonic-gate else 1326*0Sstevel@tonic-gate freemsg(mp); /* not ready to listen */ 1327*0Sstevel@tonic-gate } else { 1328*0Sstevel@tonic-gate kbdd->kbdd_flags &= ~KBD_IOCWAIT; 1329*0Sstevel@tonic-gate kbdd->kbdd_iocerror = iocp->ioc_error; 1330*0Sstevel@tonic-gate freemsg(mp); 1331*0Sstevel@tonic-gate } 1332*0Sstevel@tonic-gate return; 1333*0Sstevel@tonic-gate 1334*0Sstevel@tonic-gate case M_DATA: 1335*0Sstevel@tonic-gate if (!(kbdd->kbdd_flags & KBD_OPEN)) { 1336*0Sstevel@tonic-gate freemsg(mp); /* not read to listen */ 1337*0Sstevel@tonic-gate return; 1338*0Sstevel@tonic-gate } 1339*0Sstevel@tonic-gate break; 1340*0Sstevel@tonic-gate } 1341*0Sstevel@tonic-gate 1342*0Sstevel@tonic-gate /* 1343*0Sstevel@tonic-gate * A data message, consisting of bytes from the keyboard. 1344*0Sstevel@tonic-gate * Ram them through our state machine. 1345*0Sstevel@tonic-gate */ 1346*0Sstevel@tonic-gate bp = mp; 1347*0Sstevel@tonic-gate 1348*0Sstevel@tonic-gate do { 1349*0Sstevel@tonic-gate readp = bp->b_rptr; 1350*0Sstevel@tonic-gate while (readp < bp->b_wptr) 1351*0Sstevel@tonic-gate kbdinput(kbdd, *readp++); 1352*0Sstevel@tonic-gate bp->b_rptr = readp; 1353*0Sstevel@tonic-gate } while ((bp = bp->b_cont) != NULL); /* next block, if any */ 1354*0Sstevel@tonic-gate 1355*0Sstevel@tonic-gate freemsg(mp); 1356*0Sstevel@tonic-gate } 1357*0Sstevel@tonic-gate 1358*0Sstevel@tonic-gate /* 1359*0Sstevel@tonic-gate * A keypress was received. Process it through the state machine 1360*0Sstevel@tonic-gate * to check for aborts. 1361*0Sstevel@tonic-gate */ 1362*0Sstevel@tonic-gate static void 1363*0Sstevel@tonic-gate kbdinput(register struct kbddata *kbdd, register unsigned key) 1364*0Sstevel@tonic-gate { 1365*0Sstevel@tonic-gate register struct keyboardstate *k; 1366*0Sstevel@tonic-gate register mblk_t *mp; 1367*0Sstevel@tonic-gate 1368*0Sstevel@tonic-gate k = &kbdd->kbdd_state; 1369*0Sstevel@tonic-gate #ifdef KBD_DEBUG 1370*0Sstevel@tonic-gate if (kbd_input_debug) 1371*0Sstevel@tonic-gate printf("kbdinput key %x\n", key); 1372*0Sstevel@tonic-gate #endif 1373*0Sstevel@tonic-gate 1374*0Sstevel@tonic-gate switch (k->k_idstate) { 1375*0Sstevel@tonic-gate 1376*0Sstevel@tonic-gate case KID_NONE: 1377*0Sstevel@tonic-gate if (key == RESETKEY) { 1378*0Sstevel@tonic-gate k->k_idstate = KID_GOT_PREFACE; 1379*0Sstevel@tonic-gate } else { 1380*0Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 1381*0Sstevel@tonic-gate /* allows hot plug of kbd after booting without kbd */ 1382*0Sstevel@tonic-gate } 1383*0Sstevel@tonic-gate return; 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate case KID_GOT_PREFACE: 1386*0Sstevel@tonic-gate kbdid(kbdd, (int)key); 1387*0Sstevel@tonic-gate 1388*0Sstevel@tonic-gate /* 1389*0Sstevel@tonic-gate * We just did a reset command to a Type 3 or Type 4 1390*0Sstevel@tonic-gate * keyboard which sets the click back to the default 1391*0Sstevel@tonic-gate * (which is currently ON!). We use the kbdclick 1392*0Sstevel@tonic-gate * variable to see if the keyboard should be turned on 1393*0Sstevel@tonic-gate * or off. If it has not been set, then we use the 1394*0Sstevel@tonic-gate * keyboard-click? property. 1395*0Sstevel@tonic-gate */ 1396*0Sstevel@tonic-gate switch (kbdclick) { 1397*0Sstevel@tonic-gate case 0: 1398*0Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK); 1399*0Sstevel@tonic-gate break; 1400*0Sstevel@tonic-gate case 1: 1401*0Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_CLICK); 1402*0Sstevel@tonic-gate break; 1403*0Sstevel@tonic-gate case -1: 1404*0Sstevel@tonic-gate default: 1405*0Sstevel@tonic-gate { 1406*0Sstevel@tonic-gate char wrkbuf[8]; 1407*0Sstevel@tonic-gate int len; 1408*0Sstevel@tonic-gate 1409*0Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK); 1410*0Sstevel@tonic-gate 1411*0Sstevel@tonic-gate bzero(wrkbuf, 8); 1412*0Sstevel@tonic-gate len = 7; 1413*0Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_ANY, 1414*0Sstevel@tonic-gate ddi_root_node(), 0, "keyboard-click?", 1415*0Sstevel@tonic-gate (caddr_t)wrkbuf, &len) == 1416*0Sstevel@tonic-gate DDI_PROP_SUCCESS && 1417*0Sstevel@tonic-gate len > 0 && len < 8) { 1418*0Sstevel@tonic-gate if (strcmp(wrkbuf, "true") == 0) { 1419*0Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, 1420*0Sstevel@tonic-gate KBD_CMD_CLICK); 1421*0Sstevel@tonic-gate } 1422*0Sstevel@tonic-gate } 1423*0Sstevel@tonic-gate } 1424*0Sstevel@tonic-gate break; 1425*0Sstevel@tonic-gate } 1426*0Sstevel@tonic-gate /* 1427*0Sstevel@tonic-gate * A keyboard reset clears the LEDs. 1428*0Sstevel@tonic-gate * Restore the LEDs from the last value we set 1429*0Sstevel@tonic-gate * them to. 1430*0Sstevel@tonic-gate */ 1431*0Sstevel@tonic-gate kbdsetled(kbdd); 1432*0Sstevel@tonic-gate return; 1433*0Sstevel@tonic-gate 1434*0Sstevel@tonic-gate case KID_OK: 1435*0Sstevel@tonic-gate switch (key) { 1436*0Sstevel@tonic-gate 1437*0Sstevel@tonic-gate #if defined(KBD_PRESSED_PREFIX) 1438*0Sstevel@tonic-gate case KBD_PRESSED_PREFIX: 1439*0Sstevel@tonic-gate k->k_idstate = KID_GOT_PRESSED; 1440*0Sstevel@tonic-gate return; 1441*0Sstevel@tonic-gate #endif 1442*0Sstevel@tonic-gate 1443*0Sstevel@tonic-gate #if defined(KBD_RELEASED_PREFIX) 1444*0Sstevel@tonic-gate case KBD_RELEASED_PREFIX: 1445*0Sstevel@tonic-gate k->k_idstate = KID_GOT_RELEASED; 1446*0Sstevel@tonic-gate return; 1447*0Sstevel@tonic-gate #endif 1448*0Sstevel@tonic-gate 1449*0Sstevel@tonic-gate case 0: 1450*0Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 1451*0Sstevel@tonic-gate return; 1452*0Sstevel@tonic-gate 1453*0Sstevel@tonic-gate /* 1454*0Sstevel@tonic-gate * we want to check for ID only if we are in 1455*0Sstevel@tonic-gate * translatable mode. 1456*0Sstevel@tonic-gate */ 1457*0Sstevel@tonic-gate case RESETKEY: 1458*0Sstevel@tonic-gate kbdreset(kbdd, NO_HARD_RESET); 1459*0Sstevel@tonic-gate if (k->k_idstate == KID_NONE) { 1460*0Sstevel@tonic-gate k->k_idstate = KID_GOT_PREFACE; 1461*0Sstevel@tonic-gate } 1462*0Sstevel@tonic-gate return; 1463*0Sstevel@tonic-gate 1464*0Sstevel@tonic-gate case LAYOUTKEY: 1465*0Sstevel@tonic-gate k->k_idstate = KID_GOT_LAYOUT; 1466*0Sstevel@tonic-gate return; 1467*0Sstevel@tonic-gate } 1468*0Sstevel@tonic-gate break; 1469*0Sstevel@tonic-gate 1470*0Sstevel@tonic-gate #if defined(KBD_PRESSED_PREFIX) 1471*0Sstevel@tonic-gate case KID_GOT_PRESSED: 1472*0Sstevel@tonic-gate key = BUILDKEY(key, PRESSED); 1473*0Sstevel@tonic-gate k->k_idstate = KID_OK; 1474*0Sstevel@tonic-gate break; 1475*0Sstevel@tonic-gate #endif 1476*0Sstevel@tonic-gate #if defined(KBD_RELEASED_PREFIX) 1477*0Sstevel@tonic-gate case KID_GOT_RELEASED: 1478*0Sstevel@tonic-gate key = BUILDKEY(key, RELEASED); 1479*0Sstevel@tonic-gate k->k_idstate = KID_OK; 1480*0Sstevel@tonic-gate break; 1481*0Sstevel@tonic-gate #endif 1482*0Sstevel@tonic-gate 1483*0Sstevel@tonic-gate case KID_GOT_LAYOUT: 1484*0Sstevel@tonic-gate if (kbdd->kbdd_layoutid) 1485*0Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, 1486*0Sstevel@tonic-gate kbdd->kbdd_layoutid); 1487*0Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) { 1488*0Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 1489*0Sstevel@tonic-gate *(int *)mp->b_cont->b_wptr = key; 1490*0Sstevel@tonic-gate mp->b_cont->b_wptr += sizeof (int); 1491*0Sstevel@tonic-gate putnext(kbdd->kbdd_readq, mp); 1492*0Sstevel@tonic-gate } 1493*0Sstevel@tonic-gate k->k_idstate = KID_OK; 1494*0Sstevel@tonic-gate return; 1495*0Sstevel@tonic-gate } 1496*0Sstevel@tonic-gate 1497*0Sstevel@tonic-gate switch (k->k_state) { 1498*0Sstevel@tonic-gate 1499*0Sstevel@tonic-gate #if defined(__sparc) 1500*0Sstevel@tonic-gate normalstate: 1501*0Sstevel@tonic-gate k->k_state = NORMAL; 1502*0Sstevel@tonic-gate /* FALLTHRU */ 1503*0Sstevel@tonic-gate #endif 1504*0Sstevel@tonic-gate case NORMAL: 1505*0Sstevel@tonic-gate #if defined(__sparc) 1506*0Sstevel@tonic-gate if (k->k_curkeyboard) { 1507*0Sstevel@tonic-gate if (key == k->k_curkeyboard->k_abort1) { 1508*0Sstevel@tonic-gate k->k_state = ABORT1; 1509*0Sstevel@tonic-gate break; 1510*0Sstevel@tonic-gate } 1511*0Sstevel@tonic-gate } 1512*0Sstevel@tonic-gate #endif 1513*0Sstevel@tonic-gate kbduse(kbdd, key); 1514*0Sstevel@tonic-gate break; 1515*0Sstevel@tonic-gate 1516*0Sstevel@tonic-gate #if defined(__sparc) 1517*0Sstevel@tonic-gate case ABORT1: 1518*0Sstevel@tonic-gate if (k->k_curkeyboard) { 1519*0Sstevel@tonic-gate /* 1520*0Sstevel@tonic-gate * Only recognize this as an abort sequence if 1521*0Sstevel@tonic-gate * the "hardware" console is set to be this device. 1522*0Sstevel@tonic-gate */ 1523*0Sstevel@tonic-gate if (key == k->k_curkeyboard->k_abort2 && 1524*0Sstevel@tonic-gate rconsvp == wsconsvp) { 1525*0Sstevel@tonic-gate DELAY(100000); 1526*0Sstevel@tonic-gate abort_sequence_enter((char *)NULL); 1527*0Sstevel@tonic-gate k->k_state = NORMAL; 1528*0Sstevel@tonic-gate kbduse(kbdd, IDLEKEY); /* fake */ 1529*0Sstevel@tonic-gate return; 1530*0Sstevel@tonic-gate } else { 1531*0Sstevel@tonic-gate kbduse(kbdd, k->k_curkeyboard->k_abort1); 1532*0Sstevel@tonic-gate goto normalstate; 1533*0Sstevel@tonic-gate } 1534*0Sstevel@tonic-gate } 1535*0Sstevel@tonic-gate break; 1536*0Sstevel@tonic-gate #endif 1537*0Sstevel@tonic-gate 1538*0Sstevel@tonic-gate case COMPOSE1: 1539*0Sstevel@tonic-gate case COMPOSE2: 1540*0Sstevel@tonic-gate case FLTACCENT: 1541*0Sstevel@tonic-gate if (key != IDLEKEY) 1542*0Sstevel@tonic-gate kbduse(kbdd, key); 1543*0Sstevel@tonic-gate break; 1544*0Sstevel@tonic-gate } 1545*0Sstevel@tonic-gate } 1546*0Sstevel@tonic-gate 1547*0Sstevel@tonic-gate static void 1548*0Sstevel@tonic-gate kbdid(register struct kbddata *kbdd, int id) 1549*0Sstevel@tonic-gate { 1550*0Sstevel@tonic-gate register struct keyboardstate *k; 1551*0Sstevel@tonic-gate int i; 1552*0Sstevel@tonic-gate 1553*0Sstevel@tonic-gate k = &kbdd->kbdd_state; 1554*0Sstevel@tonic-gate 1555*0Sstevel@tonic-gate k->k_idstate = KID_OK; 1556*0Sstevel@tonic-gate k->k_shiftmask = 0; 1557*0Sstevel@tonic-gate k->k_buckybits = 0; 1558*0Sstevel@tonic-gate 1559*0Sstevel@tonic-gate /* 1560*0Sstevel@tonic-gate * Reset k_rptkey to IDLEKEY. We need to cancel 1561*0Sstevel@tonic-gate * the autorepeat feature, if any. 1562*0Sstevel@tonic-gate */ 1563*0Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) { 1564*0Sstevel@tonic-gate if (kbdd->kbdd_rptid) 1565*0Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid); 1566*0Sstevel@tonic-gate kbdd->kbdd_rptid = 0; 1567*0Sstevel@tonic-gate k->k_rptkey = IDLEKEY; 1568*0Sstevel@tonic-gate } 1569*0Sstevel@tonic-gate 1570*0Sstevel@tonic-gate k->k_curkeyboard = NULL; 1571*0Sstevel@tonic-gate for (i = 0; keytables[i].table; i++) { 1572*0Sstevel@tonic-gate if (keytables[i].id == id) { 1573*0Sstevel@tonic-gate k->k_id = id; 1574*0Sstevel@tonic-gate k->k_curkeyboard = keytables[i].table; 1575*0Sstevel@tonic-gate break; 1576*0Sstevel@tonic-gate } 1577*0Sstevel@tonic-gate } 1578*0Sstevel@tonic-gate if (!k->k_curkeyboard) { 1579*0Sstevel@tonic-gate k->k_id = keytables[0].id; 1580*0Sstevel@tonic-gate k->k_curkeyboard = keytables[0].table; 1581*0Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Unknown keyboard type, " 1582*0Sstevel@tonic-gate "Type %d assumed", k->k_id); 1583*0Sstevel@tonic-gate } 1584*0Sstevel@tonic-gate } 1585*0Sstevel@tonic-gate 1586*0Sstevel@tonic-gate /* 1587*0Sstevel@tonic-gate * This routine determines which table we should look in to decode 1588*0Sstevel@tonic-gate * the current keycode. 1589*0Sstevel@tonic-gate */ 1590*0Sstevel@tonic-gate static struct keymap * 1591*0Sstevel@tonic-gate settable(register struct kbddata *kbdd, register uint_t mask) 1592*0Sstevel@tonic-gate { 1593*0Sstevel@tonic-gate register struct keyboard *kp; 1594*0Sstevel@tonic-gate 1595*0Sstevel@tonic-gate kp = kbdd->kbdd_state.k_curkeyboard; 1596*0Sstevel@tonic-gate if (kp == NULL) 1597*0Sstevel@tonic-gate return (NULL); 1598*0Sstevel@tonic-gate if (mask & UPMASK) 1599*0Sstevel@tonic-gate return (kp->k_up); 1600*0Sstevel@tonic-gate if (mask & NUMLOCKMASK) 1601*0Sstevel@tonic-gate return (kp->k_numlock); 1602*0Sstevel@tonic-gate if (mask & CTRLMASK) 1603*0Sstevel@tonic-gate return (kp->k_control); 1604*0Sstevel@tonic-gate if (mask & ALTGRAPHMASK) 1605*0Sstevel@tonic-gate return (kp->k_altgraph); 1606*0Sstevel@tonic-gate if (mask & SHIFTMASK) 1607*0Sstevel@tonic-gate return (kp->k_shifted); 1608*0Sstevel@tonic-gate if (mask & CAPSMASK) 1609*0Sstevel@tonic-gate return (kp->k_caps); 1610*0Sstevel@tonic-gate return (kp->k_normal); 1611*0Sstevel@tonic-gate } 1612*0Sstevel@tonic-gate 1613*0Sstevel@tonic-gate static void 1614*0Sstevel@tonic-gate kbdrpt(void *arg) 1615*0Sstevel@tonic-gate { 1616*0Sstevel@tonic-gate struct kbddata *kbdd = arg; 1617*0Sstevel@tonic-gate struct keyboardstate *k; 1618*0Sstevel@tonic-gate 1619*0Sstevel@tonic-gate k = &kbdd->kbdd_state; 1620*0Sstevel@tonic-gate #ifdef KBD_DEBUG 1621*0Sstevel@tonic-gate if (kbd_rpt_debug) 1622*0Sstevel@tonic-gate printf("kbdrpt key %x\n", k->k_rptkey); 1623*0Sstevel@tonic-gate #endif 1624*0Sstevel@tonic-gate kbdd->kbdd_rptid = 0; 1625*0Sstevel@tonic-gate 1626*0Sstevel@tonic-gate kbdkeyreleased(kbdd, KEYOF(k->k_rptkey)); 1627*0Sstevel@tonic-gate kbduse(kbdd, k->k_rptkey); 1628*0Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) { 1629*0Sstevel@tonic-gate kbdd->kbdd_rptid = qtimeout(kbdd->kbdd_readq, kbdrpt, 1630*0Sstevel@tonic-gate kbdd, kbd_repeatrate); 1631*0Sstevel@tonic-gate } 1632*0Sstevel@tonic-gate } 1633*0Sstevel@tonic-gate 1634*0Sstevel@tonic-gate static void 1635*0Sstevel@tonic-gate kbdcancelrpt(register struct kbddata *kbdd) 1636*0Sstevel@tonic-gate { 1637*0Sstevel@tonic-gate register struct keyboardstate *k; 1638*0Sstevel@tonic-gate 1639*0Sstevel@tonic-gate k = &kbdd->kbdd_state; 1640*0Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) { 1641*0Sstevel@tonic-gate if (kbdd->kbdd_rptid) 1642*0Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid); 1643*0Sstevel@tonic-gate kbdd->kbdd_rptid = 0; 1644*0Sstevel@tonic-gate k->k_rptkey = IDLEKEY; 1645*0Sstevel@tonic-gate } 1646*0Sstevel@tonic-gate ASSERT(kbdd->kbdd_rptid == 0); 1647*0Sstevel@tonic-gate } 1648*0Sstevel@tonic-gate 1649*0Sstevel@tonic-gate static void 1650*0Sstevel@tonic-gate kbdtranslate(struct kbddata *kbdd, unsigned keycode, queue_t *q) 1651*0Sstevel@tonic-gate { 1652*0Sstevel@tonic-gate register uchar_t key; 1653*0Sstevel@tonic-gate register unsigned newstate; 1654*0Sstevel@tonic-gate unsigned shiftmask; 1655*0Sstevel@tonic-gate register ushort_t entry, entrytype; 1656*0Sstevel@tonic-gate register char *cp, *bufp; 1657*0Sstevel@tonic-gate register struct keyboardstate *k; 1658*0Sstevel@tonic-gate ushort_t result_iso; 1659*0Sstevel@tonic-gate struct keymap *km; 1660*0Sstevel@tonic-gate Firm_event fe; 1661*0Sstevel@tonic-gate int i, ret_val; 1662*0Sstevel@tonic-gate char buf[14]; 1663*0Sstevel@tonic-gate 1664*0Sstevel@tonic-gate k = &kbdd->kbdd_state; 1665*0Sstevel@tonic-gate newstate = STATEOF(keycode); 1666*0Sstevel@tonic-gate key = KEYOF(keycode); 1667*0Sstevel@tonic-gate 1668*0Sstevel@tonic-gate #ifdef KBD_DEBUG 1669*0Sstevel@tonic-gate if (kbd_input_debug) { 1670*0Sstevel@tonic-gate printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n", 1671*0Sstevel@tonic-gate keycode, newstate, key); 1672*0Sstevel@tonic-gate } 1673*0Sstevel@tonic-gate #endif 1674*0Sstevel@tonic-gate 1675*0Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_UNTRANS_EVENT) { 1676*0Sstevel@tonic-gate if (newstate == PRESSED) { 1677*0Sstevel@tonic-gate bzero(&fe, sizeof (fe)); 1678*0Sstevel@tonic-gate fe.id = key; 1679*0Sstevel@tonic-gate fe.value = 1; 1680*0Sstevel@tonic-gate kbdqueuepress(kbdd, key, &fe); 1681*0Sstevel@tonic-gate } else { 1682*0Sstevel@tonic-gate kbdkeyreleased(kbdd, key); 1683*0Sstevel@tonic-gate } 1684*0Sstevel@tonic-gate return; 1685*0Sstevel@tonic-gate } 1686*0Sstevel@tonic-gate 1687*0Sstevel@tonic-gate shiftmask = k->k_shiftmask; 1688*0Sstevel@tonic-gate if (newstate == RELEASED) 1689*0Sstevel@tonic-gate shiftmask |= UPMASK; 1690*0Sstevel@tonic-gate 1691*0Sstevel@tonic-gate km = settable(kbdd, shiftmask); 1692*0Sstevel@tonic-gate if (km == NULL) { /* gross error */ 1693*0Sstevel@tonic-gate kbdcancelrpt(kbdd); 1694*0Sstevel@tonic-gate return; 1695*0Sstevel@tonic-gate } 1696*0Sstevel@tonic-gate 1697*0Sstevel@tonic-gate if (key >= KEYMAP_SIZE) 1698*0Sstevel@tonic-gate return; 1699*0Sstevel@tonic-gate entry = km->keymap[key]; 1700*0Sstevel@tonic-gate 1701*0Sstevel@tonic-gate if (entry == NONL) { 1702*0Sstevel@tonic-gate /* 1703*0Sstevel@tonic-gate * NONL appears only in the Num Lock table, and indicates that 1704*0Sstevel@tonic-gate * this key is not affected by Num Lock. This means we should 1705*0Sstevel@tonic-gate * ask for the table we would have gotten had Num Lock not been 1706*0Sstevel@tonic-gate * down, and translate using that table. 1707*0Sstevel@tonic-gate */ 1708*0Sstevel@tonic-gate km = settable(kbdd, shiftmask & ~NUMLOCKMASK); 1709*0Sstevel@tonic-gate if (km == NULL) { /* gross error */ 1710*0Sstevel@tonic-gate kbdcancelrpt(kbdd); 1711*0Sstevel@tonic-gate return; 1712*0Sstevel@tonic-gate } 1713*0Sstevel@tonic-gate entry = km->keymap[key]; 1714*0Sstevel@tonic-gate } 1715*0Sstevel@tonic-gate entrytype = (ushort_t)(entry & 0xFF00) >> 8; 1716*0Sstevel@tonic-gate 1717*0Sstevel@tonic-gate if (entrytype == (SHIFTKEYS >> 8)) { 1718*0Sstevel@tonic-gate /* 1719*0Sstevel@tonic-gate * Handle the state of toggle shifts specially. 1720*0Sstevel@tonic-gate * Ups should be ignored, and downs should be mapped to ups if 1721*0Sstevel@tonic-gate * that shift is currently on. 1722*0Sstevel@tonic-gate */ 1723*0Sstevel@tonic-gate if ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts) { 1724*0Sstevel@tonic-gate if ((1 << (entry & 0x0F)) & k->k_togglemask) { 1725*0Sstevel@tonic-gate newstate = RELEASED; /* toggling off */ 1726*0Sstevel@tonic-gate } else { 1727*0Sstevel@tonic-gate newstate = PRESSED; /* toggling on */ 1728*0Sstevel@tonic-gate } 1729*0Sstevel@tonic-gate } 1730*0Sstevel@tonic-gate } else { 1731*0Sstevel@tonic-gate /* 1732*0Sstevel@tonic-gate * Handle Compose and floating accent key sequences 1733*0Sstevel@tonic-gate */ 1734*0Sstevel@tonic-gate if (k->k_state == COMPOSE1) { 1735*0Sstevel@tonic-gate if (newstate == RELEASED) 1736*0Sstevel@tonic-gate return; 1737*0Sstevel@tonic-gate if (entry < ASCII_SET_SIZE) { 1738*0Sstevel@tonic-gate if (kb_compose_map[entry] >= 0) { 1739*0Sstevel@tonic-gate kbdd->compose_key = entry; 1740*0Sstevel@tonic-gate k->k_state = COMPOSE2; 1741*0Sstevel@tonic-gate return; 1742*0Sstevel@tonic-gate } 1743*0Sstevel@tonic-gate } 1744*0Sstevel@tonic-gate k->k_state = NORMAL; 1745*0Sstevel@tonic-gate kbdd->led_state &= ~LED_COMPOSE; 1746*0Sstevel@tonic-gate kbdsetled(kbdd); 1747*0Sstevel@tonic-gate return; 1748*0Sstevel@tonic-gate } else if (k->k_state == COMPOSE2) { 1749*0Sstevel@tonic-gate if (newstate == RELEASED) 1750*0Sstevel@tonic-gate return; 1751*0Sstevel@tonic-gate k->k_state = NORMAL; /* next state is "normal" */ 1752*0Sstevel@tonic-gate kbdd->led_state &= ~LED_COMPOSE; 1753*0Sstevel@tonic-gate kbdsetled(kbdd); 1754*0Sstevel@tonic-gate if (entry < ASCII_SET_SIZE) { 1755*0Sstevel@tonic-gate if (kb_compose_map[entry] >= 0) { 1756*0Sstevel@tonic-gate if (kbdd->compose_key <= entry) { 1757*0Sstevel@tonic-gate ret_val = kbd_do_compose( 1758*0Sstevel@tonic-gate kbdd->compose_key, 1759*0Sstevel@tonic-gate entry, 1760*0Sstevel@tonic-gate &result_iso); 1761*0Sstevel@tonic-gate } else { 1762*0Sstevel@tonic-gate ret_val = kbd_do_compose( 1763*0Sstevel@tonic-gate entry, 1764*0Sstevel@tonic-gate kbdd->compose_key, 1765*0Sstevel@tonic-gate &result_iso); 1766*0Sstevel@tonic-gate } 1767*0Sstevel@tonic-gate if (ret_val == 1) { 1768*0Sstevel@tonic-gate if (kbdd->kbdd_translate == 1769*0Sstevel@tonic-gate TR_EVENT) { 1770*0Sstevel@tonic-gate fe.id = 1771*0Sstevel@tonic-gate (kbdd->kbdd_compat ? 1772*0Sstevel@tonic-gate ISO_FIRST : EUC_FIRST) 1773*0Sstevel@tonic-gate + result_iso; 1774*0Sstevel@tonic-gate fe.value = 1; 1775*0Sstevel@tonic-gate kbdqueueevent( 1776*0Sstevel@tonic-gate kbdd, 1777*0Sstevel@tonic-gate &fe); 1778*0Sstevel@tonic-gate } else if ( 1779*0Sstevel@tonic-gate kbdd->kbdd_translate == 1780*0Sstevel@tonic-gate TR_ASCII) 1781*0Sstevel@tonic-gate kbdputcode( 1782*0Sstevel@tonic-gate result_iso, 1783*0Sstevel@tonic-gate q); 1784*0Sstevel@tonic-gate } 1785*0Sstevel@tonic-gate } 1786*0Sstevel@tonic-gate } 1787*0Sstevel@tonic-gate return; 1788*0Sstevel@tonic-gate } else if (k->k_state == FLTACCENT) { 1789*0Sstevel@tonic-gate if (newstate == RELEASED) 1790*0Sstevel@tonic-gate return; 1791*0Sstevel@tonic-gate k->k_state = NORMAL; /* next state is "normal" */ 1792*0Sstevel@tonic-gate for (i = 0; 1793*0Sstevel@tonic-gate (kb_fltaccent_table[i].fa_entry 1794*0Sstevel@tonic-gate != kbdd->fltaccent_entry) || 1795*0Sstevel@tonic-gate (kb_fltaccent_table[i].ascii != entry); 1796*0Sstevel@tonic-gate i++) { 1797*0Sstevel@tonic-gate if (kb_fltaccent_table[i].fa_entry == 0) 1798*0Sstevel@tonic-gate /* Invalid second key: ignore key */ 1799*0Sstevel@tonic-gate return; 1800*0Sstevel@tonic-gate } 1801*0Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT) { 1802*0Sstevel@tonic-gate fe.id = (kbdd->kbdd_compat ? 1803*0Sstevel@tonic-gate ISO_FIRST : EUC_FIRST) 1804*0Sstevel@tonic-gate + kb_fltaccent_table[i].iso; 1805*0Sstevel@tonic-gate fe.value = 1; 1806*0Sstevel@tonic-gate kbdqueueevent(kbdd, &fe); 1807*0Sstevel@tonic-gate } else if (kbdd->kbdd_translate == TR_ASCII) 1808*0Sstevel@tonic-gate kbdputcode(kb_fltaccent_table[i].iso, q); 1809*0Sstevel@tonic-gate return; 1810*0Sstevel@tonic-gate } 1811*0Sstevel@tonic-gate } 1812*0Sstevel@tonic-gate 1813*0Sstevel@tonic-gate /* 1814*0Sstevel@tonic-gate * If the key is going down, and it's not one of the keys that doesn't 1815*0Sstevel@tonic-gate * auto-repeat, set up the auto-repeat timeout. 1816*0Sstevel@tonic-gate * 1817*0Sstevel@tonic-gate * The keys that don't auto-repeat are the Compose key, 1818*0Sstevel@tonic-gate * the shift keys, the "bucky bit" keys, the "floating accent" keys, 1819*0Sstevel@tonic-gate * and the function keys when in TR_EVENT mode. 1820*0Sstevel@tonic-gate */ 1821*0Sstevel@tonic-gate if (newstate == PRESSED && entrytype != (SHIFTKEYS >> 8) && 1822*0Sstevel@tonic-gate entrytype != (BUCKYBITS >> 8) && entrytype != (FUNNY >> 8) && 1823*0Sstevel@tonic-gate entrytype != (FA_CLASS >> 8) && 1824*0Sstevel@tonic-gate !((entrytype == (FUNCKEYS >> 8) || entrytype == (PADKEYS >> 8)) && 1825*0Sstevel@tonic-gate kbdd->kbdd_translate == TR_EVENT)) { 1826*0Sstevel@tonic-gate if (k->k_rptkey != keycode) { 1827*0Sstevel@tonic-gate kbdcancelrpt(kbdd); 1828*0Sstevel@tonic-gate kbdd->kbdd_rptid = qtimeout(q, kbdrpt, kbdd, 1829*0Sstevel@tonic-gate kbd_repeatdelay); 1830*0Sstevel@tonic-gate k->k_rptkey = keycode; 1831*0Sstevel@tonic-gate } 1832*0Sstevel@tonic-gate } else if (key == KEYOF(k->k_rptkey)) /* key going up */ 1833*0Sstevel@tonic-gate kbdcancelrpt(kbdd); 1834*0Sstevel@tonic-gate if ((newstate == RELEASED) && (kbdd->kbdd_translate == TR_EVENT)) 1835*0Sstevel@tonic-gate kbdkeyreleased(kbdd, key); 1836*0Sstevel@tonic-gate 1837*0Sstevel@tonic-gate /* 1838*0Sstevel@tonic-gate * We assume here that keys other than shift keys and bucky keys have 1839*0Sstevel@tonic-gate * entries in the "up" table that cause nothing to be done, and thus we 1840*0Sstevel@tonic-gate * don't have to check for newstate == RELEASED. 1841*0Sstevel@tonic-gate */ 1842*0Sstevel@tonic-gate switch (entrytype) { 1843*0Sstevel@tonic-gate 1844*0Sstevel@tonic-gate case 0x0: /* regular key */ 1845*0Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 1846*0Sstevel@tonic-gate 1847*0Sstevel@tonic-gate case TR_EVENT: 1848*0Sstevel@tonic-gate fe.id = entry | k->k_buckybits; 1849*0Sstevel@tonic-gate fe.value = 1; 1850*0Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, entry); 1851*0Sstevel@tonic-gate break; 1852*0Sstevel@tonic-gate 1853*0Sstevel@tonic-gate case TR_ASCII: 1854*0Sstevel@tonic-gate kbdputcode(entry | k->k_buckybits, q); 1855*0Sstevel@tonic-gate break; 1856*0Sstevel@tonic-gate } 1857*0Sstevel@tonic-gate break; 1858*0Sstevel@tonic-gate 1859*0Sstevel@tonic-gate case SHIFTKEYS >> 8: { 1860*0Sstevel@tonic-gate uint_t shiftbit = 1 << (entry & 0x0F); 1861*0Sstevel@tonic-gate 1862*0Sstevel@tonic-gate /* Modify toggle state (see toggle processing above) */ 1863*0Sstevel@tonic-gate if (shiftbit & k->k_curkeyboard->k_toggleshifts) { 1864*0Sstevel@tonic-gate if (newstate == RELEASED) { 1865*0Sstevel@tonic-gate if (shiftbit == CAPSMASK) { 1866*0Sstevel@tonic-gate kbdd->led_state &= ~LED_CAPS_LOCK; 1867*0Sstevel@tonic-gate kbdsetled(kbdd); 1868*0Sstevel@tonic-gate } else if (shiftbit == NUMLOCKMASK) { 1869*0Sstevel@tonic-gate kbdd->led_state &= ~LED_NUM_LOCK; 1870*0Sstevel@tonic-gate kbdsetled(kbdd); 1871*0Sstevel@tonic-gate } 1872*0Sstevel@tonic-gate k->k_togglemask &= ~shiftbit; 1873*0Sstevel@tonic-gate } else { 1874*0Sstevel@tonic-gate if (shiftbit == CAPSMASK) { 1875*0Sstevel@tonic-gate kbdd->led_state |= LED_CAPS_LOCK; 1876*0Sstevel@tonic-gate kbdsetled(kbdd); 1877*0Sstevel@tonic-gate } else if (shiftbit == NUMLOCKMASK) { 1878*0Sstevel@tonic-gate kbdd->led_state |= LED_NUM_LOCK; 1879*0Sstevel@tonic-gate kbdsetled(kbdd); 1880*0Sstevel@tonic-gate } 1881*0Sstevel@tonic-gate k->k_togglemask |= shiftbit; 1882*0Sstevel@tonic-gate } 1883*0Sstevel@tonic-gate } 1884*0Sstevel@tonic-gate 1885*0Sstevel@tonic-gate if (newstate == RELEASED) 1886*0Sstevel@tonic-gate k->k_shiftmask &= ~shiftbit; 1887*0Sstevel@tonic-gate else 1888*0Sstevel@tonic-gate k->k_shiftmask |= shiftbit; 1889*0Sstevel@tonic-gate 1890*0Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) { 1891*0Sstevel@tonic-gate /* 1892*0Sstevel@tonic-gate * Relying on ordinal correspondence between 1893*0Sstevel@tonic-gate * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL & 1894*0Sstevel@tonic-gate * kbd.h CAPSLOCK-RIGHTCTRL in order to 1895*0Sstevel@tonic-gate * correctly translate entry into fe.id. 1896*0Sstevel@tonic-gate */ 1897*0Sstevel@tonic-gate fe.id = SHIFT_CAPSLOCK + (entry & 0x0F); 1898*0Sstevel@tonic-gate fe.value = 1; 1899*0Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 1900*0Sstevel@tonic-gate } 1901*0Sstevel@tonic-gate break; 1902*0Sstevel@tonic-gate } 1903*0Sstevel@tonic-gate 1904*0Sstevel@tonic-gate case BUCKYBITS >> 8: 1905*0Sstevel@tonic-gate k->k_buckybits ^= 1 << (7 + (entry & 0x0F)); 1906*0Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) { 1907*0Sstevel@tonic-gate /* 1908*0Sstevel@tonic-gate * Relying on ordinal correspondence between 1909*0Sstevel@tonic-gate * vuid_event.h SHIFT_META-SHIFT_TOP & 1910*0Sstevel@tonic-gate * kbd.h METABIT-SYSTEMBIT in order to 1911*0Sstevel@tonic-gate * correctly translate entry into fe.id. 1912*0Sstevel@tonic-gate */ 1913*0Sstevel@tonic-gate fe.id = SHIFT_META + (entry & 0x0F); 1914*0Sstevel@tonic-gate fe.value = 1; 1915*0Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 1916*0Sstevel@tonic-gate } 1917*0Sstevel@tonic-gate break; 1918*0Sstevel@tonic-gate 1919*0Sstevel@tonic-gate case FUNNY >> 8: 1920*0Sstevel@tonic-gate switch (entry) { 1921*0Sstevel@tonic-gate case NOP: 1922*0Sstevel@tonic-gate break; 1923*0Sstevel@tonic-gate 1924*0Sstevel@tonic-gate case IDLE: 1925*0Sstevel@tonic-gate /* Fall thru into RESET code */ 1926*0Sstevel@tonic-gate /* FALLTHRU */ 1927*0Sstevel@tonic-gate case RESET: 1928*0Sstevel@tonic-gate gotreset: 1929*0Sstevel@tonic-gate k->k_shiftmask &= k->k_curkeyboard->k_idleshifts; 1930*0Sstevel@tonic-gate k->k_shiftmask |= k->k_togglemask; 1931*0Sstevel@tonic-gate k->k_buckybits &= k->k_curkeyboard->k_idlebuckys; 1932*0Sstevel@tonic-gate kbdcancelrpt(kbdd); 1933*0Sstevel@tonic-gate kbdreleaseall(kbdd); 1934*0Sstevel@tonic-gate break; 1935*0Sstevel@tonic-gate 1936*0Sstevel@tonic-gate case ERROR: 1937*0Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Error detected"); 1938*0Sstevel@tonic-gate goto gotreset; 1939*0Sstevel@tonic-gate 1940*0Sstevel@tonic-gate case COMPOSE: 1941*0Sstevel@tonic-gate k->k_state = COMPOSE1; 1942*0Sstevel@tonic-gate kbdd->led_state |= LED_COMPOSE; 1943*0Sstevel@tonic-gate kbdsetled(kbdd); 1944*0Sstevel@tonic-gate break; 1945*0Sstevel@tonic-gate /* 1946*0Sstevel@tonic-gate * Remember when adding new entries that, 1947*0Sstevel@tonic-gate * if they should NOT auto-repeat, 1948*0Sstevel@tonic-gate * they should be put into the IF statement 1949*0Sstevel@tonic-gate * just above this switch block. 1950*0Sstevel@tonic-gate */ 1951*0Sstevel@tonic-gate default: 1952*0Sstevel@tonic-gate goto badentry; 1953*0Sstevel@tonic-gate } 1954*0Sstevel@tonic-gate break; 1955*0Sstevel@tonic-gate 1956*0Sstevel@tonic-gate case FA_CLASS >> 8: 1957*0Sstevel@tonic-gate if (k->k_state == NORMAL) { 1958*0Sstevel@tonic-gate kbdd->fltaccent_entry = entry; 1959*0Sstevel@tonic-gate k->k_state = FLTACCENT; 1960*0Sstevel@tonic-gate } 1961*0Sstevel@tonic-gate return; 1962*0Sstevel@tonic-gate 1963*0Sstevel@tonic-gate case STRING >> 8: 1964*0Sstevel@tonic-gate cp = &keystringtab[entry & 0x0F][0]; 1965*0Sstevel@tonic-gate while (*cp != '\0') { 1966*0Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 1967*0Sstevel@tonic-gate 1968*0Sstevel@tonic-gate case TR_EVENT: 1969*0Sstevel@tonic-gate kbd_send_esc_event(*cp, kbdd); 1970*0Sstevel@tonic-gate break; 1971*0Sstevel@tonic-gate 1972*0Sstevel@tonic-gate case TR_ASCII: 1973*0Sstevel@tonic-gate kbdputcode((uchar_t)*cp, q); 1974*0Sstevel@tonic-gate break; 1975*0Sstevel@tonic-gate } 1976*0Sstevel@tonic-gate cp++; 1977*0Sstevel@tonic-gate } 1978*0Sstevel@tonic-gate break; 1979*0Sstevel@tonic-gate 1980*0Sstevel@tonic-gate case FUNCKEYS >> 8: 1981*0Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 1982*0Sstevel@tonic-gate 1983*0Sstevel@tonic-gate case TR_ASCII: 1984*0Sstevel@tonic-gate bufp = buf; 1985*0Sstevel@tonic-gate cp = strsetwithdecimal(bufp + 2, 1986*0Sstevel@tonic-gate (uint_t)((entry & 0x003F) + 192), 1987*0Sstevel@tonic-gate sizeof (buf) - 5); 1988*0Sstevel@tonic-gate *bufp++ = '\033'; /* Escape */ 1989*0Sstevel@tonic-gate *bufp++ = '['; 1990*0Sstevel@tonic-gate while (*cp != '\0') 1991*0Sstevel@tonic-gate *bufp++ = *cp++; 1992*0Sstevel@tonic-gate *bufp++ = 'z'; 1993*0Sstevel@tonic-gate *bufp = '\0'; 1994*0Sstevel@tonic-gate kbdputbuf(buf, q); 1995*0Sstevel@tonic-gate break; 1996*0Sstevel@tonic-gate 1997*0Sstevel@tonic-gate case TR_EVENT: 1998*0Sstevel@tonic-gate /* 1999*0Sstevel@tonic-gate * Take advantage of the similar 2000*0Sstevel@tonic-gate * ordering of kbd.h function keys and 2001*0Sstevel@tonic-gate * vuid_event.h function keys to do a 2002*0Sstevel@tonic-gate * simple translation to achieve a 2003*0Sstevel@tonic-gate * mapping between the 2 different 2004*0Sstevel@tonic-gate * address spaces. 2005*0Sstevel@tonic-gate */ 2006*0Sstevel@tonic-gate fe.id = (entry & 0x003F) + KEY_LEFTFIRST; 2007*0Sstevel@tonic-gate fe.value = 1; 2008*0Sstevel@tonic-gate /* 2009*0Sstevel@tonic-gate * Assume "up" table only generates 2010*0Sstevel@tonic-gate * shift changes. 2011*0Sstevel@tonic-gate */ 2012*0Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 2013*0Sstevel@tonic-gate /* 2014*0Sstevel@tonic-gate * Function key events can be expanded 2015*0Sstevel@tonic-gate * by terminal emulator software to 2016*0Sstevel@tonic-gate * produce the standard escape sequence 2017*0Sstevel@tonic-gate * generated by the TR_ASCII case above 2018*0Sstevel@tonic-gate * if a function key event is not used 2019*0Sstevel@tonic-gate * by terminal emulator software 2020*0Sstevel@tonic-gate * directly. 2021*0Sstevel@tonic-gate */ 2022*0Sstevel@tonic-gate break; 2023*0Sstevel@tonic-gate } 2024*0Sstevel@tonic-gate break; 2025*0Sstevel@tonic-gate 2026*0Sstevel@tonic-gate /* 2027*0Sstevel@tonic-gate * Remember when adding new entries that, 2028*0Sstevel@tonic-gate * if they should NOT auto-repeat, 2029*0Sstevel@tonic-gate * they should be put into the IF statement 2030*0Sstevel@tonic-gate * just above this switch block. 2031*0Sstevel@tonic-gate */ 2032*0Sstevel@tonic-gate case PADKEYS >> 8: 2033*0Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 2034*0Sstevel@tonic-gate 2035*0Sstevel@tonic-gate case TR_ASCII: 2036*0Sstevel@tonic-gate kbdputcode(kb_numlock_table[entry&0x1F], q); 2037*0Sstevel@tonic-gate break; 2038*0Sstevel@tonic-gate 2039*0Sstevel@tonic-gate case TR_EVENT: 2040*0Sstevel@tonic-gate /* 2041*0Sstevel@tonic-gate * Take advantage of the similar 2042*0Sstevel@tonic-gate * ordering of kbd.h keypad keys and 2043*0Sstevel@tonic-gate * vuid_event.h keypad keys to do a 2044*0Sstevel@tonic-gate * simple translation to achieve a 2045*0Sstevel@tonic-gate * mapping between the 2 different 2046*0Sstevel@tonic-gate * address spaces. 2047*0Sstevel@tonic-gate */ 2048*0Sstevel@tonic-gate fe.id = (entry & 0x001F) + VKEY_FIRSTPAD; 2049*0Sstevel@tonic-gate fe.value = 1; 2050*0Sstevel@tonic-gate /* 2051*0Sstevel@tonic-gate * Assume "up" table only generates 2052*0Sstevel@tonic-gate * shift changes. 2053*0Sstevel@tonic-gate */ 2054*0Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 2055*0Sstevel@tonic-gate /* 2056*0Sstevel@tonic-gate * Keypad key events can be expanded 2057*0Sstevel@tonic-gate * by terminal emulator software to 2058*0Sstevel@tonic-gate * produce the standard ascii character 2059*0Sstevel@tonic-gate * generated by the TR_ASCII case above 2060*0Sstevel@tonic-gate * if a keypad key event is not used 2061*0Sstevel@tonic-gate * by terminal emulator software 2062*0Sstevel@tonic-gate * directly. 2063*0Sstevel@tonic-gate */ 2064*0Sstevel@tonic-gate break; 2065*0Sstevel@tonic-gate } 2066*0Sstevel@tonic-gate 2067*0Sstevel@tonic-gate badentry: 2068*0Sstevel@tonic-gate break; 2069*0Sstevel@tonic-gate } 2070*0Sstevel@tonic-gate } 2071*0Sstevel@tonic-gate 2072*0Sstevel@tonic-gate static int 2073*0Sstevel@tonic-gate kbd_do_compose(ushort_t first_entry, ushort_t second_entry, 2074*0Sstevel@tonic-gate ushort_t *result_iso_ptr) 2075*0Sstevel@tonic-gate { 2076*0Sstevel@tonic-gate struct compose_sequence_t *ptr; 2077*0Sstevel@tonic-gate 2078*0Sstevel@tonic-gate ptr = &kb_compose_table[kb_compose_map[first_entry]]; 2079*0Sstevel@tonic-gate while (ptr->first == first_entry) { 2080*0Sstevel@tonic-gate if (ptr->second == second_entry) { 2081*0Sstevel@tonic-gate *result_iso_ptr = ptr->iso; 2082*0Sstevel@tonic-gate return (1); 2083*0Sstevel@tonic-gate } 2084*0Sstevel@tonic-gate ptr++; 2085*0Sstevel@tonic-gate } 2086*0Sstevel@tonic-gate return (0); 2087*0Sstevel@tonic-gate } 2088*0Sstevel@tonic-gate 2089*0Sstevel@tonic-gate static void 2090*0Sstevel@tonic-gate kbd_send_esc_event(char c, register struct kbddata *kbdd) 2091*0Sstevel@tonic-gate { 2092*0Sstevel@tonic-gate Firm_event fe; 2093*0Sstevel@tonic-gate 2094*0Sstevel@tonic-gate fe.id = c; 2095*0Sstevel@tonic-gate fe.value = 1; 2096*0Sstevel@tonic-gate fe.pair_type = FE_PAIR_NONE; 2097*0Sstevel@tonic-gate fe.pair = 0; 2098*0Sstevel@tonic-gate /* 2099*0Sstevel@tonic-gate * Pretend as if each cp pushed and released 2100*0Sstevel@tonic-gate * Calling kbdqueueevent avoids addr translation 2101*0Sstevel@tonic-gate * and pair base determination of kbdkeypressed. 2102*0Sstevel@tonic-gate */ 2103*0Sstevel@tonic-gate kbdqueueevent(kbdd, &fe); 2104*0Sstevel@tonic-gate fe.value = 0; 2105*0Sstevel@tonic-gate kbdqueueevent(kbdd, &fe); 2106*0Sstevel@tonic-gate } 2107*0Sstevel@tonic-gate 2108*0Sstevel@tonic-gate char * 2109*0Sstevel@tonic-gate strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs) 2110*0Sstevel@tonic-gate { 2111*0Sstevel@tonic-gate int hradix = 5; 2112*0Sstevel@tonic-gate char *bp; 2113*0Sstevel@tonic-gate int lowbit; 2114*0Sstevel@tonic-gate char *tab = "0123456789abcdef"; 2115*0Sstevel@tonic-gate 2116*0Sstevel@tonic-gate bp = buf + maxdigs; 2117*0Sstevel@tonic-gate *(--bp) = '\0'; 2118*0Sstevel@tonic-gate while (val) { 2119*0Sstevel@tonic-gate lowbit = val & 1; 2120*0Sstevel@tonic-gate val = (val >> 1); 2121*0Sstevel@tonic-gate *(--bp) = tab[val % hradix * 2 + lowbit]; 2122*0Sstevel@tonic-gate val /= hradix; 2123*0Sstevel@tonic-gate } 2124*0Sstevel@tonic-gate return (bp); 2125*0Sstevel@tonic-gate } 2126*0Sstevel@tonic-gate 2127*0Sstevel@tonic-gate static void 2128*0Sstevel@tonic-gate kbdkeypressed(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe, 2129*0Sstevel@tonic-gate ushort_t base) 2130*0Sstevel@tonic-gate { 2131*0Sstevel@tonic-gate register struct keyboardstate *k; 2132*0Sstevel@tonic-gate register short id_addr; 2133*0Sstevel@tonic-gate 2134*0Sstevel@tonic-gate /* Set pair values */ 2135*0Sstevel@tonic-gate if (fe->id < (ushort_t)VKEY_FIRST) { 2136*0Sstevel@tonic-gate /* 2137*0Sstevel@tonic-gate * If CTRLed, find the ID that would have been used had it 2138*0Sstevel@tonic-gate * not been CTRLed. 2139*0Sstevel@tonic-gate */ 2140*0Sstevel@tonic-gate k = &kbdd->kbdd_state; 2141*0Sstevel@tonic-gate if (k->k_shiftmask & (CTRLMASK | CTLSMASK)) { 2142*0Sstevel@tonic-gate struct keymap *km; 2143*0Sstevel@tonic-gate 2144*0Sstevel@tonic-gate km = settable(kbdd, 2145*0Sstevel@tonic-gate k->k_shiftmask & ~(CTRLMASK | CTLSMASK | UPMASK)); 2146*0Sstevel@tonic-gate if (km == NULL) 2147*0Sstevel@tonic-gate return; 2148*0Sstevel@tonic-gate base = km->keymap[key_station]; 2149*0Sstevel@tonic-gate } 2150*0Sstevel@tonic-gate if (base != fe->id) { 2151*0Sstevel@tonic-gate fe->pair_type = FE_PAIR_SET; 2152*0Sstevel@tonic-gate fe->pair = base; 2153*0Sstevel@tonic-gate goto send; 2154*0Sstevel@tonic-gate } 2155*0Sstevel@tonic-gate } 2156*0Sstevel@tonic-gate fe->pair_type = FE_PAIR_NONE; 2157*0Sstevel@tonic-gate fe->pair = 0; 2158*0Sstevel@tonic-gate send: 2159*0Sstevel@tonic-gate /* Adjust event id address for multiple keyboard/workstation support */ 2160*0Sstevel@tonic-gate switch (vuid_id_addr(fe->id)) { 2161*0Sstevel@tonic-gate case ASCII_FIRST: 2162*0Sstevel@tonic-gate id_addr = kbdd->kbdd_ascii_addr; 2163*0Sstevel@tonic-gate break; 2164*0Sstevel@tonic-gate case TOP_FIRST: 2165*0Sstevel@tonic-gate id_addr = kbdd->kbdd_top_addr; 2166*0Sstevel@tonic-gate break; 2167*0Sstevel@tonic-gate case VKEY_FIRST: 2168*0Sstevel@tonic-gate id_addr = kbdd->kbdd_vkey_addr; 2169*0Sstevel@tonic-gate break; 2170*0Sstevel@tonic-gate default: 2171*0Sstevel@tonic-gate id_addr = vuid_id_addr(fe->id); 2172*0Sstevel@tonic-gate } 2173*0Sstevel@tonic-gate fe->id = vuid_id_offset(fe->id) | id_addr; 2174*0Sstevel@tonic-gate kbdqueuepress(kbdd, key_station, fe); 2175*0Sstevel@tonic-gate } 2176*0Sstevel@tonic-gate 2177*0Sstevel@tonic-gate static void 2178*0Sstevel@tonic-gate kbdqueuepress(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe) 2179*0Sstevel@tonic-gate { 2180*0Sstevel@tonic-gate register struct key_event *ke, *ke_free; 2181*0Sstevel@tonic-gate register int i; 2182*0Sstevel@tonic-gate 2183*0Sstevel@tonic-gate if (key_station == IDLEKEY) 2184*0Sstevel@tonic-gate return; 2185*0Sstevel@tonic-gate #ifdef KBD_DEBUG 2186*0Sstevel@tonic-gate if (kbd_input_debug) printf("KBD PRESSED key=%d\n", key_station); 2187*0Sstevel@tonic-gate #endif 2188*0Sstevel@tonic-gate ke_free = 0; 2189*0Sstevel@tonic-gate /* Scan table of down key stations */ 2190*0Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT || 2191*0Sstevel@tonic-gate kbdd->kbdd_translate == TR_UNTRANS_EVENT) { 2192*0Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs; 2193*0Sstevel@tonic-gate i < kbdd->kbdd_downs_entries; 2194*0Sstevel@tonic-gate i++, ke++) { 2195*0Sstevel@tonic-gate /* Keycode already down? */ 2196*0Sstevel@tonic-gate if (ke->key_station == key_station) { 2197*0Sstevel@tonic-gate #ifdef KBD_DEBUG 2198*0Sstevel@tonic-gate printf("kbd: Double entry in downs table (%d,%d)!\n", key_station, i); 2199*0Sstevel@tonic-gate #endif 2200*0Sstevel@tonic-gate goto add_event; 2201*0Sstevel@tonic-gate } 2202*0Sstevel@tonic-gate if (ke->key_station == 0) 2203*0Sstevel@tonic-gate ke_free = ke; 2204*0Sstevel@tonic-gate } 2205*0Sstevel@tonic-gate if (ke_free) { 2206*0Sstevel@tonic-gate ke = ke_free; 2207*0Sstevel@tonic-gate goto add_event; 2208*0Sstevel@tonic-gate } 2209*0Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Too many keys down!"); 2210*0Sstevel@tonic-gate ke = kbdd->kbdd_downs; 2211*0Sstevel@tonic-gate } 2212*0Sstevel@tonic-gate add_event: 2213*0Sstevel@tonic-gate ke->key_station = key_station; 2214*0Sstevel@tonic-gate ke->event = *fe; 2215*0Sstevel@tonic-gate kbdqueueevent(kbdd, fe); 2216*0Sstevel@tonic-gate } 2217*0Sstevel@tonic-gate 2218*0Sstevel@tonic-gate static void 2219*0Sstevel@tonic-gate kbdkeyreleased(register struct kbddata *kbdd, uchar_t key_station) 2220*0Sstevel@tonic-gate { 2221*0Sstevel@tonic-gate register struct key_event *ke; 2222*0Sstevel@tonic-gate register int i; 2223*0Sstevel@tonic-gate 2224*0Sstevel@tonic-gate if (key_station == IDLEKEY) 2225*0Sstevel@tonic-gate return; 2226*0Sstevel@tonic-gate #ifdef KBD_DEBUG 2227*0Sstevel@tonic-gate if (kbd_input_debug) 2228*0Sstevel@tonic-gate printf("KBD RELEASE key=%d\n", key_station); 2229*0Sstevel@tonic-gate #endif 2230*0Sstevel@tonic-gate if (kbdd->kbdd_translate != TR_EVENT && 2231*0Sstevel@tonic-gate kbdd->kbdd_translate != TR_UNTRANS_EVENT) 2232*0Sstevel@tonic-gate return; 2233*0Sstevel@tonic-gate /* Scan table of down key stations */ 2234*0Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs; 2235*0Sstevel@tonic-gate i < kbdd->kbdd_downs_entries; 2236*0Sstevel@tonic-gate i++, ke++) { 2237*0Sstevel@tonic-gate /* Found? */ 2238*0Sstevel@tonic-gate if (ke->key_station == key_station) { 2239*0Sstevel@tonic-gate ke->key_station = 0; 2240*0Sstevel@tonic-gate ke->event.value = 0; 2241*0Sstevel@tonic-gate kbdqueueevent(kbdd, &ke->event); 2242*0Sstevel@tonic-gate } 2243*0Sstevel@tonic-gate } 2244*0Sstevel@tonic-gate 2245*0Sstevel@tonic-gate /* 2246*0Sstevel@tonic-gate * Ignore if couldn't find because may be called twice 2247*0Sstevel@tonic-gate * for the same key station in the case of the kbdrpt 2248*0Sstevel@tonic-gate * routine being called unnecessarily. 2249*0Sstevel@tonic-gate */ 2250*0Sstevel@tonic-gate } 2251*0Sstevel@tonic-gate 2252*0Sstevel@tonic-gate static void 2253*0Sstevel@tonic-gate kbdreleaseall(struct kbddata *kbdd) 2254*0Sstevel@tonic-gate { 2255*0Sstevel@tonic-gate register struct key_event *ke; 2256*0Sstevel@tonic-gate register int i; 2257*0Sstevel@tonic-gate 2258*0Sstevel@tonic-gate #ifdef KBD_DEBUG 2259*0Sstevel@tonic-gate if (kbd_debug && kbd_ra_debug) printf("KBD RELEASE ALL\n"); 2260*0Sstevel@tonic-gate #endif 2261*0Sstevel@tonic-gate /* Scan table of down key stations */ 2262*0Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs; 2263*0Sstevel@tonic-gate i < kbdd->kbdd_downs_entries; i++, ke++) { 2264*0Sstevel@tonic-gate /* Key station not zero */ 2265*0Sstevel@tonic-gate if (ke->key_station) 2266*0Sstevel@tonic-gate kbdkeyreleased(kbdd, ke->key_station); 2267*0Sstevel@tonic-gate /* kbdkeyreleased resets kbdd_downs entry */ 2268*0Sstevel@tonic-gate } 2269*0Sstevel@tonic-gate } 2270*0Sstevel@tonic-gate 2271*0Sstevel@tonic-gate /* 2272*0Sstevel@tonic-gate * Pass a keycode up the stream, if you can, otherwise throw it away. 2273*0Sstevel@tonic-gate */ 2274*0Sstevel@tonic-gate static void 2275*0Sstevel@tonic-gate kbdputcode(uint_t code, queue_t *q) 2276*0Sstevel@tonic-gate { 2277*0Sstevel@tonic-gate register mblk_t *bp; 2278*0Sstevel@tonic-gate 2279*0Sstevel@tonic-gate if (!canput(q)) 2280*0Sstevel@tonic-gate cmn_err(CE_WARN, "kbdputcode: Can't put block for keycode"); 2281*0Sstevel@tonic-gate else { 2282*0Sstevel@tonic-gate if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) 2283*0Sstevel@tonic-gate cmn_err(CE_WARN, 2284*0Sstevel@tonic-gate "kbdputcode: Can't allocate block for keycode"); 2285*0Sstevel@tonic-gate else { 2286*0Sstevel@tonic-gate *bp->b_wptr++ = code; 2287*0Sstevel@tonic-gate putnext(q, bp); 2288*0Sstevel@tonic-gate } 2289*0Sstevel@tonic-gate } 2290*0Sstevel@tonic-gate } 2291*0Sstevel@tonic-gate 2292*0Sstevel@tonic-gate /* 2293*0Sstevel@tonic-gate * Pass generated keycode sequence to upstream, if possible. 2294*0Sstevel@tonic-gate */ 2295*0Sstevel@tonic-gate static void 2296*0Sstevel@tonic-gate kbdputbuf(char *buf, queue_t *q) 2297*0Sstevel@tonic-gate { 2298*0Sstevel@tonic-gate register mblk_t *bp; 2299*0Sstevel@tonic-gate 2300*0Sstevel@tonic-gate if (!canput(q)) 2301*0Sstevel@tonic-gate cmn_err(CE_WARN, "kbdputbuf: Can't put block for keycode"); 2302*0Sstevel@tonic-gate else { 2303*0Sstevel@tonic-gate if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) 2304*0Sstevel@tonic-gate cmn_err(CE_WARN, 2305*0Sstevel@tonic-gate "kbdputbuf: Can't allocate block for keycode"); 2306*0Sstevel@tonic-gate else { 2307*0Sstevel@tonic-gate while (*buf) { 2308*0Sstevel@tonic-gate *bp->b_wptr++ = *buf; 2309*0Sstevel@tonic-gate buf++; 2310*0Sstevel@tonic-gate } 2311*0Sstevel@tonic-gate putnext(q, bp); 2312*0Sstevel@tonic-gate } 2313*0Sstevel@tonic-gate } 2314*0Sstevel@tonic-gate } 2315*0Sstevel@tonic-gate 2316*0Sstevel@tonic-gate /* 2317*0Sstevel@tonic-gate * Pass a VUID "firm event" up the stream, if you can. 2318*0Sstevel@tonic-gate */ 2319*0Sstevel@tonic-gate static void 2320*0Sstevel@tonic-gate kbdqueueevent(struct kbddata *kbdd, Firm_event *fe) 2321*0Sstevel@tonic-gate { 2322*0Sstevel@tonic-gate register queue_t *q; 2323*0Sstevel@tonic-gate register mblk_t *bp; 2324*0Sstevel@tonic-gate 2325*0Sstevel@tonic-gate if ((q = kbdd->kbdd_readq) == NULL) 2326*0Sstevel@tonic-gate return; 2327*0Sstevel@tonic-gate if (!canput(q)) { 2328*0Sstevel@tonic-gate if (kbd_overflow_msg) 2329*0Sstevel@tonic-gate cmn_err(CE_WARN, 2330*0Sstevel@tonic-gate "kbd: Buffer flushed when overflowed"); 2331*0Sstevel@tonic-gate kbdflush(kbdd); 2332*0Sstevel@tonic-gate kbd_overflow_cnt++; 2333*0Sstevel@tonic-gate } else { 2334*0Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) 2335*0Sstevel@tonic-gate cmn_err(CE_WARN, 2336*0Sstevel@tonic-gate "kbdqueueevent: Can't allocate block for event"); 2337*0Sstevel@tonic-gate else { 2338*0Sstevel@tonic-gate #if 1 /* XX64 */ 2339*0Sstevel@tonic-gate struct timeval now; 2340*0Sstevel@tonic-gate 2341*0Sstevel@tonic-gate /* 2342*0Sstevel@tonic-gate * XX64: This is something of a compromise. It 2343*0Sstevel@tonic-gate * seems justifiable based on the usage of these 2344*0Sstevel@tonic-gate * timestamps as an ordering relation as opposed 2345*0Sstevel@tonic-gate * to a strict timing thing. 2346*0Sstevel@tonic-gate * 2347*0Sstevel@tonic-gate * But should we restore Firm_event's time stamp 2348*0Sstevel@tonic-gate * to be a timeval, and send 32-bit and 64-bit 2349*0Sstevel@tonic-gate * events up the pipe? 2350*0Sstevel@tonic-gate */ 2351*0Sstevel@tonic-gate uniqtime(&now); 2352*0Sstevel@tonic-gate TIMEVAL_TO_TIMEVAL32(&fe->time, &now); 2353*0Sstevel@tonic-gate #else 2354*0Sstevel@tonic-gate uniqtime(&fe->time); 2355*0Sstevel@tonic-gate #endif 2356*0Sstevel@tonic-gate *(Firm_event *)bp->b_wptr = *fe; 2357*0Sstevel@tonic-gate bp->b_wptr += sizeof (Firm_event); 2358*0Sstevel@tonic-gate putnext(q, bp); 2359*0Sstevel@tonic-gate } 2360*0Sstevel@tonic-gate } 2361*0Sstevel@tonic-gate } 2362