17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*e4603304Sqz150045 * Common Development and Distribution License (the "License"). 6*e4603304Sqz150045 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*e4603304Sqz150045 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate /* SunOS-4.0 1.60 */ 287c478bd9Sstevel@tonic-gate /* From: SunOS4.0 sundev/kbd.c */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * Keyboard input streams module - handles conversion of up/down codes to 327c478bd9Sstevel@tonic-gate * ASCII or event format. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate #include <sys/param.h> 367c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 377c478bd9Sstevel@tonic-gate #include <sys/signal.h> 387c478bd9Sstevel@tonic-gate #include <sys/termios.h> 397c478bd9Sstevel@tonic-gate #include <sys/termio.h> 407c478bd9Sstevel@tonic-gate #include <sys/stream.h> 417c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 427c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 437c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 447c478bd9Sstevel@tonic-gate #include <sys/file.h> 457c478bd9Sstevel@tonic-gate #include <sys/uio.h> 467c478bd9Sstevel@tonic-gate #include <sys/errno.h> 477c478bd9Sstevel@tonic-gate #include <sys/time.h> 487c478bd9Sstevel@tonic-gate #include <sys/consdev.h> 497c478bd9Sstevel@tonic-gate #include <sys/kbd.h> 507c478bd9Sstevel@tonic-gate #include <sys/kbio.h> 517c478bd9Sstevel@tonic-gate #include <sys/kbdreg.h> 527c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h> 537c478bd9Sstevel@tonic-gate #include <sys/debug.h> 547c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 557c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 567c478bd9Sstevel@tonic-gate #include <sys/policy.h> 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate static struct streamtab kbd_info; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate static struct fmodsw fsw = { 637c478bd9Sstevel@tonic-gate "kb", 647c478bd9Sstevel@tonic-gate &kbd_info, 657c478bd9Sstevel@tonic-gate D_MP | D_MTPERMOD 667c478bd9Sstevel@tonic-gate }; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* 697c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = { 737c478bd9Sstevel@tonic-gate &mod_strmodops, "streams module for keyboard", &fsw 747c478bd9Sstevel@tonic-gate }; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 777c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlstrmod, NULL 787c478bd9Sstevel@tonic-gate }; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate int 817c478bd9Sstevel@tonic-gate _init(void) 827c478bd9Sstevel@tonic-gate { 837c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate int 877c478bd9Sstevel@tonic-gate _fini(void) 887c478bd9Sstevel@tonic-gate { 897c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate int 937c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * For now these are shared. 1007c478bd9Sstevel@tonic-gate * These data structures are static (defined in keytables.c) thus 1017c478bd9Sstevel@tonic-gate * there is no need to perform any locking. 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate extern struct keyboards keytables[]; 1047c478bd9Sstevel@tonic-gate extern char keystringtab[16][KTAB_STRLEN]; 1057c478bd9Sstevel@tonic-gate extern struct compose_sequence_t kb_compose_table[]; 1067c478bd9Sstevel@tonic-gate extern signed char kb_compose_map[]; 1077c478bd9Sstevel@tonic-gate extern struct fltaccent_sequence_t kb_fltaccent_table[]; 1087c478bd9Sstevel@tonic-gate extern uchar_t kb_numlock_table[]; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* 1117c478bd9Sstevel@tonic-gate * This value corresponds approximately to max 10 fingers 1127c478bd9Sstevel@tonic-gate */ 1137c478bd9Sstevel@tonic-gate static int kbd_downs_size = 15; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate typedef struct key_event { 1167c478bd9Sstevel@tonic-gate uchar_t key_station; /* Physical key station associated with event */ 1177c478bd9Sstevel@tonic-gate Firm_event event; /* Event that sent out on down */ 1187c478bd9Sstevel@tonic-gate } Key_event; 1197c478bd9Sstevel@tonic-gate struct kbddata { 1207c478bd9Sstevel@tonic-gate queue_t *kbdd_readq; 1217c478bd9Sstevel@tonic-gate queue_t *kbdd_writeq; 1227c478bd9Sstevel@tonic-gate mblk_t *kbdd_iocpending; /* "ioctl" awaiting buffer */ 1237c478bd9Sstevel@tonic-gate mblk_t *kbdd_replypending; /* "ioctl" reply awaiting result */ 1247c478bd9Sstevel@tonic-gate int kbdd_flags; /* random flags */ 1257c478bd9Sstevel@tonic-gate bufcall_id_t kbdd_bufcallid; /* bufcall id */ 1267c478bd9Sstevel@tonic-gate timeout_id_t kbdd_rptid; /* timeout id for kbdrpt() */ 1277c478bd9Sstevel@tonic-gate timeout_id_t kbdd_layoutid; /* timeout id for kbdlayout() */ 1287c478bd9Sstevel@tonic-gate int kbdd_iocid; /* ID of "ioctl" being waited for */ 1297c478bd9Sstevel@tonic-gate int kbdd_iocerror; /* error return from "ioctl" */ 1307c478bd9Sstevel@tonic-gate struct keyboardstate kbdd_state; 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * State of keyboard & keyboard 1337c478bd9Sstevel@tonic-gate * specific settings, e.g., tables 1347c478bd9Sstevel@tonic-gate */ 1357c478bd9Sstevel@tonic-gate int kbdd_translate; /* Translate keycodes? */ 1367c478bd9Sstevel@tonic-gate int kbdd_translatable; /* Keyboard is translatable? */ 1377c478bd9Sstevel@tonic-gate int kbdd_compat; /* Generating pre-4.1 events? */ 1387c478bd9Sstevel@tonic-gate short kbdd_ascii_addr; /* Vuid_id_addr for ascii events */ 1397c478bd9Sstevel@tonic-gate short kbdd_top_addr; /* Vuid_id_addr for top events */ 1407c478bd9Sstevel@tonic-gate short kbdd_vkey_addr; /* Vuid_id_addr for vkey events */ 1417c478bd9Sstevel@tonic-gate struct key_event *kbdd_downs; 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Table of key stations currently down 1447c478bd9Sstevel@tonic-gate * that have firm events that need 1457c478bd9Sstevel@tonic-gate * to be matched with up transitions 1467c478bd9Sstevel@tonic-gate * when kbdd_translate is TR_*EVENT 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate int kbdd_downs_entries; /* # of possible entries in kbdd_downs */ 1497c478bd9Sstevel@tonic-gate uint_t kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */ 1507c478bd9Sstevel@tonic-gate ushort_t compose_key; /* first compose key */ 1517c478bd9Sstevel@tonic-gate ushort_t fltaccent_entry; /* floating accent keymap entry */ 1527c478bd9Sstevel@tonic-gate char led_state; /* current state of LEDs */ 1537c478bd9Sstevel@tonic-gate }; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate #define KBD_OPEN 0x00000001 /* keyboard is open for business */ 1567c478bd9Sstevel@tonic-gate #define KBD_IOCWAIT 0x00000002 /* "open" waiting for "ioctl" to finish */ 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate #define NO_HARD_RESET 0 /* don't do hard reset */ 1597c478bd9Sstevel@tonic-gate #define HARD_RESET 1 /* do hard reset */ 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * Constants setup during the first open of a kbd (so that they can be patched 1647c478bd9Sstevel@tonic-gate * for debugging purposes). 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate static int kbd_repeatrate; 1677c478bd9Sstevel@tonic-gate static int kbd_repeatdelay; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate static int kbd_overflow_cnt; /* Number of times kbd overflowed input q */ 1707c478bd9Sstevel@tonic-gate static int kbd_overflow_msg = 1; /* Whether to print message on q overflow */ 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 1737c478bd9Sstevel@tonic-gate int kbd_debug = 0; 1747c478bd9Sstevel@tonic-gate int kbd_ra_debug = 0; 1757c478bd9Sstevel@tonic-gate int kbd_raw_debug = 0; 1767c478bd9Sstevel@tonic-gate int kbd_rpt_debug = 0; 1777c478bd9Sstevel@tonic-gate int kbd_input_debug = 0; 1787c478bd9Sstevel@tonic-gate #endif /* KBD_DEBUG */ 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate static int kbdopen(queue_t *, dev_t *, int, int, cred_t *); 1817c478bd9Sstevel@tonic-gate static int kbdclose(queue_t *, int, cred_t *); 1827c478bd9Sstevel@tonic-gate static void kbdwput(queue_t *, mblk_t *); 1837c478bd9Sstevel@tonic-gate static void kbdrput(queue_t *, mblk_t *); 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate static struct module_info kbdmiinfo = { 1867c478bd9Sstevel@tonic-gate 0, 1877c478bd9Sstevel@tonic-gate "kb", 1887c478bd9Sstevel@tonic-gate 0, 1897c478bd9Sstevel@tonic-gate INFPSZ, 1907c478bd9Sstevel@tonic-gate 2048, 1917c478bd9Sstevel@tonic-gate 128 1927c478bd9Sstevel@tonic-gate }; 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate static struct qinit kbdrinit = { 1957c478bd9Sstevel@tonic-gate (int (*)())kbdrput, 1967c478bd9Sstevel@tonic-gate (int (*)())NULL, 1977c478bd9Sstevel@tonic-gate kbdopen, 1987c478bd9Sstevel@tonic-gate kbdclose, 1997c478bd9Sstevel@tonic-gate (int (*)())NULL, 2007c478bd9Sstevel@tonic-gate &kbdmiinfo 2017c478bd9Sstevel@tonic-gate }; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate static struct module_info kbdmoinfo = { 2047c478bd9Sstevel@tonic-gate 0, 2057c478bd9Sstevel@tonic-gate "kb", 2067c478bd9Sstevel@tonic-gate 0, 2077c478bd9Sstevel@tonic-gate INFPSZ, 2087c478bd9Sstevel@tonic-gate 2048, 2097c478bd9Sstevel@tonic-gate 128 2107c478bd9Sstevel@tonic-gate }; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate static struct qinit kbdwinit = { 2137c478bd9Sstevel@tonic-gate (int (*)())kbdwput, 2147c478bd9Sstevel@tonic-gate (int (*)())NULL, 2157c478bd9Sstevel@tonic-gate kbdopen, 2167c478bd9Sstevel@tonic-gate kbdclose, 2177c478bd9Sstevel@tonic-gate (int (*)())NULL, 2187c478bd9Sstevel@tonic-gate &kbdmoinfo 2197c478bd9Sstevel@tonic-gate }; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate static struct streamtab kbd_info = { 2227c478bd9Sstevel@tonic-gate &kbdrinit, 2237c478bd9Sstevel@tonic-gate &kbdwinit, 2247c478bd9Sstevel@tonic-gate NULL, 2257c478bd9Sstevel@tonic-gate NULL, 2267c478bd9Sstevel@tonic-gate }; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate static void kbdreioctl(void *); 2297c478bd9Sstevel@tonic-gate static void kbdioctl(queue_t *, mblk_t *); 2307c478bd9Sstevel@tonic-gate static void kbdflush(struct kbddata *); 2317c478bd9Sstevel@tonic-gate static void kbduse(struct kbddata *, unsigned); 2327c478bd9Sstevel@tonic-gate static void kbdsetled(struct kbddata *); 2337c478bd9Sstevel@tonic-gate static void kbdcmd(queue_t *, char); 2347c478bd9Sstevel@tonic-gate static void kbdreset(struct kbddata *, uint_t); 2357c478bd9Sstevel@tonic-gate static int kbdsetkey(struct kbddata *, struct kiockey *, cred_t *); 2367c478bd9Sstevel@tonic-gate static int kbdgetkey(struct kbddata *, struct kiockey *); 2377c478bd9Sstevel@tonic-gate static int kbdskey(struct kbddata *, struct kiockeymap *, cred_t *); 2387c478bd9Sstevel@tonic-gate static int kbdgkey(struct kbddata *, struct kiockeymap *); 2397c478bd9Sstevel@tonic-gate static void kbdlayouttimeout(void *); 2407c478bd9Sstevel@tonic-gate static void kbdinput(struct kbddata *, unsigned); 2417c478bd9Sstevel@tonic-gate static void kbdid(struct kbddata *, int); 2427c478bd9Sstevel@tonic-gate static struct keymap *settable(struct kbddata *, uint_t); 2437c478bd9Sstevel@tonic-gate static void kbdrpt(void *); 2447c478bd9Sstevel@tonic-gate static void kbdcancelrpt(struct kbddata *); 2457c478bd9Sstevel@tonic-gate static void kbdtranslate(struct kbddata *, unsigned, queue_t *); 2467c478bd9Sstevel@tonic-gate static int kbd_do_compose(ushort_t, ushort_t, ushort_t *); 2477c478bd9Sstevel@tonic-gate static void kbd_send_esc_event(char, struct kbddata *); 2487c478bd9Sstevel@tonic-gate char *strsetwithdecimal(char *, uint_t, uint_t); 2497c478bd9Sstevel@tonic-gate static void kbdkeypressed(struct kbddata *, uchar_t, Firm_event *, 2507c478bd9Sstevel@tonic-gate ushort_t); 2517c478bd9Sstevel@tonic-gate static void kbdqueuepress(struct kbddata *, uchar_t, Firm_event *); 2527c478bd9Sstevel@tonic-gate static void kbdkeyreleased(struct kbddata *, uchar_t); 2537c478bd9Sstevel@tonic-gate static void kbdreleaseall(struct kbddata *); 2547c478bd9Sstevel@tonic-gate static void kbdputcode(uint_t, queue_t *); 2557c478bd9Sstevel@tonic-gate static void kbdputbuf(char *, queue_t *); 2567c478bd9Sstevel@tonic-gate static void kbdqueueevent(struct kbddata *, Firm_event *); 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* 2597c478bd9Sstevel@tonic-gate * Dummy qbufcall callback routine used by open and close. 2607c478bd9Sstevel@tonic-gate * The framework will wake up qwait_sig when we return from 2617c478bd9Sstevel@tonic-gate * this routine (as part of leaving the perimeters.) 2627c478bd9Sstevel@tonic-gate * (The framework enters the perimeters before calling the qbufcall() callback 2637c478bd9Sstevel@tonic-gate * and leaves the perimeters after the callback routine has executed. The 2647c478bd9Sstevel@tonic-gate * framework performs an implicit wakeup of any thread in qwait/qwait_sig 2657c478bd9Sstevel@tonic-gate * when it leaves the perimeter. See qwait(9E).) 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2687c478bd9Sstevel@tonic-gate static void dummy_callback(void *arg) 2697c478bd9Sstevel@tonic-gate {} 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* 2737c478bd9Sstevel@tonic-gate * Open a keyboard. 2747c478bd9Sstevel@tonic-gate * Ttyopen sets line characteristics 2757c478bd9Sstevel@tonic-gate */ 2767c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2777c478bd9Sstevel@tonic-gate static int 2787c478bd9Sstevel@tonic-gate kbdopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) 2797c478bd9Sstevel@tonic-gate { 2807c478bd9Sstevel@tonic-gate register int error; 2817c478bd9Sstevel@tonic-gate register struct kbddata *kbdd; 2827c478bd9Sstevel@tonic-gate mblk_t *mp; 2837c478bd9Sstevel@tonic-gate mblk_t *datap; 2847c478bd9Sstevel@tonic-gate register struct iocblk *iocb; 2857c478bd9Sstevel@tonic-gate register struct termios *cb; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* Set these up only once so that they could be changed from adb */ 2887c478bd9Sstevel@tonic-gate if (!kbd_repeatrate) { 2897c478bd9Sstevel@tonic-gate kbd_repeatrate = (hz+29)/30; 2907c478bd9Sstevel@tonic-gate kbd_repeatdelay = hz/2; 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate if (q->q_ptr != NULL) 2947c478bd9Sstevel@tonic-gate return (0); /* already attached */ 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* 2977c478bd9Sstevel@tonic-gate * Only allow open requests to succeed for privileged users. This 2987c478bd9Sstevel@tonic-gate * necessary to prevent users from pushing the "kb" module again 2997c478bd9Sstevel@tonic-gate * on the stream associated with /dev/kbd. 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate if (secpolicy_console(crp) != 0) { 3027c478bd9Sstevel@tonic-gate return (EPERM); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate switch (sflag) { 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate case MODOPEN: 3097c478bd9Sstevel@tonic-gate break; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate case CLONEOPEN: 3127c478bd9Sstevel@tonic-gate return (EINVAL); /* No Bozos! */ 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate /* allocate keyboard */ 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate kbdd = kmem_zalloc(sizeof (struct kbddata), KM_SLEEP); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* 3217c478bd9Sstevel@tonic-gate * Set up queue pointers, so that the "put" procedure will accept 3227c478bd9Sstevel@tonic-gate * the reply to the "ioctl" message we send down. 3237c478bd9Sstevel@tonic-gate */ 3247c478bd9Sstevel@tonic-gate q->q_ptr = kbdd; 3257c478bd9Sstevel@tonic-gate WR(q)->q_ptr = kbdd; 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate qprocson(q); 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate /* 3307c478bd9Sstevel@tonic-gate * Setup tty modes. 3317c478bd9Sstevel@tonic-gate */ 3327c478bd9Sstevel@tonic-gate while ((mp = mkiocb(TCSETSF)) == NULL) { 3337c478bd9Sstevel@tonic-gate timeout_id_t id = qbufcall(q, sizeof (struct iocblk), BPRI_HI, 3347c478bd9Sstevel@tonic-gate dummy_callback, NULL); 3357c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) { 3367c478bd9Sstevel@tonic-gate qunbufcall(q, id); 3377c478bd9Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 3387c478bd9Sstevel@tonic-gate qprocsoff(q); 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate return (EINTR); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate while ((datap = allocb(sizeof (struct termios), BPRI_HI)) == 3447c478bd9Sstevel@tonic-gate NULL) { 3457c478bd9Sstevel@tonic-gate timeout_id_t id = qbufcall(q, sizeof (struct termios), BPRI_HI, 3467c478bd9Sstevel@tonic-gate dummy_callback, NULL); 3477c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) { 3487c478bd9Sstevel@tonic-gate qunbufcall(q, id); 3497c478bd9Sstevel@tonic-gate freemsg(mp); 3507c478bd9Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 3517c478bd9Sstevel@tonic-gate qprocsoff(q); 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate return (EINTR); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate iocb = (struct iocblk *)mp->b_rptr; 3587c478bd9Sstevel@tonic-gate iocb->ioc_count = sizeof (struct termios); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate cb = (struct termios *)datap->b_rptr; 3617c478bd9Sstevel@tonic-gate cb->c_iflag = 0; 3627c478bd9Sstevel@tonic-gate cb->c_oflag = 0; 3637c478bd9Sstevel@tonic-gate cb->c_cflag = CREAD|CS8|B1200; 3647c478bd9Sstevel@tonic-gate cb->c_lflag = 0; 3657c478bd9Sstevel@tonic-gate bzero(cb->c_cc, NCCS); 3667c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (struct termios); 3677c478bd9Sstevel@tonic-gate mp->b_cont = datap; 3687c478bd9Sstevel@tonic-gate kbdd->kbdd_flags |= KBD_IOCWAIT; /* indicate that we're */ 3697c478bd9Sstevel@tonic-gate kbdd->kbdd_iocid = iocb->ioc_id; /* waiting for this response */ 3707c478bd9Sstevel@tonic-gate putnext(WR(q), mp); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate /* 3737c478bd9Sstevel@tonic-gate * Now wait for it. Let our read queue put routine wake us up 3747c478bd9Sstevel@tonic-gate * when it arrives. 3757c478bd9Sstevel@tonic-gate */ 3767c478bd9Sstevel@tonic-gate while (kbdd->kbdd_flags & KBD_IOCWAIT) { 3777c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) { 3787c478bd9Sstevel@tonic-gate error = EINTR; 3797c478bd9Sstevel@tonic-gate goto error; 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate if ((error = kbdd->kbdd_iocerror) != 0) 3837c478bd9Sstevel@tonic-gate goto error; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* 3867c478bd9Sstevel@tonic-gate * Set up private data. 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate kbdd->kbdd_readq = q; 3897c478bd9Sstevel@tonic-gate kbdd->kbdd_writeq = WR(q); 3907c478bd9Sstevel@tonic-gate kbdd->kbdd_iocpending = NULL; 3917c478bd9Sstevel@tonic-gate kbdd->kbdd_translatable = TR_CAN; 3927c478bd9Sstevel@tonic-gate kbdd->kbdd_translate = TR_ASCII; 3937c478bd9Sstevel@tonic-gate kbdd->kbdd_compat = 1; 3947c478bd9Sstevel@tonic-gate kbdd->kbdd_ascii_addr = ASCII_FIRST; 3957c478bd9Sstevel@tonic-gate kbdd->kbdd_top_addr = TOP_FIRST; 3967c478bd9Sstevel@tonic-gate kbdd->kbdd_vkey_addr = VKEY_FIRST; 3977c478bd9Sstevel@tonic-gate /* Allocate dynamic memory for downs table */ 3987c478bd9Sstevel@tonic-gate kbdd->kbdd_downs_entries = kbd_downs_size; 3997c478bd9Sstevel@tonic-gate kbdd->kbdd_downs_bytes = kbd_downs_size * sizeof (Key_event); 4007c478bd9Sstevel@tonic-gate kbdd->kbdd_downs = kmem_alloc(kbdd->kbdd_downs_bytes, KM_SLEEP); 4017c478bd9Sstevel@tonic-gate kbdd->kbdd_flags = KBD_OPEN; 4027c478bd9Sstevel@tonic-gate kbdd->led_state = 0; 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate /* 4057c478bd9Sstevel@tonic-gate * Reset kbd. 4067c478bd9Sstevel@tonic-gate */ 4077c478bd9Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate return (0); 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate error: 4127c478bd9Sstevel@tonic-gate qprocsoff(q); 4137c478bd9Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 4147c478bd9Sstevel@tonic-gate return (error); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate /* 4187c478bd9Sstevel@tonic-gate * Close a keyboard. 4197c478bd9Sstevel@tonic-gate */ 4207c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 4217c478bd9Sstevel@tonic-gate static int 4227c478bd9Sstevel@tonic-gate kbdclose(register queue_t *q, int flag, cred_t *crp) 4237c478bd9Sstevel@tonic-gate { 4247c478bd9Sstevel@tonic-gate register struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 4257c478bd9Sstevel@tonic-gate register mblk_t *mp; 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate qprocsoff(q); 4287c478bd9Sstevel@tonic-gate /* 4297c478bd9Sstevel@tonic-gate * Since we're about to destroy our private data, turn off 4307c478bd9Sstevel@tonic-gate * our open flag first, so we don't accept any more input 4317c478bd9Sstevel@tonic-gate * and try to use that data. 4327c478bd9Sstevel@tonic-gate */ 4337c478bd9Sstevel@tonic-gate kbdd->kbdd_flags = 0; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) { 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * There was a KIOCLAYOUT pending; presumably, it timed out. 4387c478bd9Sstevel@tonic-gate * Throw the reply away. 4397c478bd9Sstevel@tonic-gate */ 4407c478bd9Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 4417c478bd9Sstevel@tonic-gate freemsg(mp); 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate /* clear all timeouts */ 4457c478bd9Sstevel@tonic-gate if (kbdd->kbdd_bufcallid) 4467c478bd9Sstevel@tonic-gate qunbufcall(q, kbdd->kbdd_bufcallid); 4477c478bd9Sstevel@tonic-gate if (kbdd->kbdd_rptid) 4487c478bd9Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_rptid); 4497c478bd9Sstevel@tonic-gate if (kbdd->kbdd_layoutid) 4507c478bd9Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_layoutid); 4517c478bd9Sstevel@tonic-gate kmem_free(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes); 4527c478bd9Sstevel@tonic-gate kmem_free(kbdd, sizeof (struct kbddata)); 4537c478bd9Sstevel@tonic-gate return (0); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* 4577c478bd9Sstevel@tonic-gate * Line discipline output queue put procedure: handles M_IOCTL 4587c478bd9Sstevel@tonic-gate * messages. 4597c478bd9Sstevel@tonic-gate */ 4607c478bd9Sstevel@tonic-gate static void 4617c478bd9Sstevel@tonic-gate kbdwput(register queue_t *q, register mblk_t *mp) 4627c478bd9Sstevel@tonic-gate { 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * Process M_FLUSH, and some M_IOCTL, messages here; pass 4657c478bd9Sstevel@tonic-gate * everything else down. 4667c478bd9Sstevel@tonic-gate */ 4677c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate case M_FLUSH: 4707c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 4717c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 4727c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 4737c478bd9Sstevel@tonic-gate flushq(RD(q), FLUSHDATA); 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate default: 4767c478bd9Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */ 4777c478bd9Sstevel@tonic-gate break; 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate case M_IOCTL: 4807c478bd9Sstevel@tonic-gate kbdioctl(q, mp); 4817c478bd9Sstevel@tonic-gate break; 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate static void 4877c478bd9Sstevel@tonic-gate kbdreioctl(void *kbdd_addr) 4887c478bd9Sstevel@tonic-gate { 4897c478bd9Sstevel@tonic-gate struct kbddata *kbdd = kbdd_addr; 4907c478bd9Sstevel@tonic-gate queue_t *q; 4917c478bd9Sstevel@tonic-gate mblk_t *mp; 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate kbdd->kbdd_bufcallid = 0; 4947c478bd9Sstevel@tonic-gate q = kbdd->kbdd_writeq; 4957c478bd9Sstevel@tonic-gate if ((mp = kbdd->kbdd_iocpending) != NULL) { 4967c478bd9Sstevel@tonic-gate kbdd->kbdd_iocpending = NULL; /* not pending any more */ 4977c478bd9Sstevel@tonic-gate kbdioctl(q, mp); 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate static void 5027c478bd9Sstevel@tonic-gate kbdioctl(register queue_t *q, register mblk_t *mp) 5037c478bd9Sstevel@tonic-gate { 5047c478bd9Sstevel@tonic-gate register struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 5057c478bd9Sstevel@tonic-gate register struct iocblk *iocp; 5067c478bd9Sstevel@tonic-gate register short new_translate; 5077c478bd9Sstevel@tonic-gate register Vuid_addr_probe *addr_probe; 5087c478bd9Sstevel@tonic-gate register short *addr_ptr; 5097c478bd9Sstevel@tonic-gate mblk_t *datap; 5107c478bd9Sstevel@tonic-gate size_t ioctlrespsize; 5117c478bd9Sstevel@tonic-gate int err = 0; 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate case VUIDSFORMAT: 5187c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 5197c478bd9Sstevel@tonic-gate if (err != 0) 5207c478bd9Sstevel@tonic-gate break; 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ? 5237c478bd9Sstevel@tonic-gate TR_ASCII : TR_EVENT; 5247c478bd9Sstevel@tonic-gate if (new_translate == kbdd->kbdd_translate) 5257c478bd9Sstevel@tonic-gate break; 5267c478bd9Sstevel@tonic-gate kbdd->kbdd_translate = new_translate; 5277c478bd9Sstevel@tonic-gate goto output_format_change; 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate case KIOCTRANS: 5307c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 5317c478bd9Sstevel@tonic-gate if (err != 0) 5327c478bd9Sstevel@tonic-gate break; 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate new_translate = *(int *)mp->b_cont->b_rptr; 5357c478bd9Sstevel@tonic-gate if (new_translate == kbdd->kbdd_translate) 5367c478bd9Sstevel@tonic-gate break; 5377c478bd9Sstevel@tonic-gate kbdd->kbdd_translate = new_translate; 5387c478bd9Sstevel@tonic-gate goto output_format_change; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate case KIOCCMD: 5417c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 5427c478bd9Sstevel@tonic-gate if (err != 0) 5437c478bd9Sstevel@tonic-gate break; 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate kbdcmd(q, (char)(*(int *)mp->b_cont->b_rptr)); 5467c478bd9Sstevel@tonic-gate break; 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate case KIOCSLED: 5497c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (uchar_t)); 5507c478bd9Sstevel@tonic-gate if (err != 0) 5517c478bd9Sstevel@tonic-gate break; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate kbdd->led_state = *(uchar_t *)mp->b_cont->b_rptr; 5547c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 5557c478bd9Sstevel@tonic-gate break; 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate case KIOCGLED: 5587c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) { 5597c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 5607c478bd9Sstevel@tonic-gate goto allocfailure; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate *(uchar_t *)datap->b_wptr = kbdd->led_state; 5637c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (uchar_t); 5647c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 5657c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 5667c478bd9Sstevel@tonic-gate mp->b_cont = datap; 5677c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (uchar_t); 5687c478bd9Sstevel@tonic-gate break; 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate case VUIDGFORMAT: 5717c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 5727c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 5737c478bd9Sstevel@tonic-gate goto allocfailure; 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = 5767c478bd9Sstevel@tonic-gate (kbdd->kbdd_translate == TR_EVENT || 5777c478bd9Sstevel@tonic-gate kbdd->kbdd_translate == TR_UNTRANS_EVENT) ? 5787c478bd9Sstevel@tonic-gate VUID_FIRM_EVENT: VUID_NATIVE; 5797c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 5807c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 5817c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 5827c478bd9Sstevel@tonic-gate mp->b_cont = datap; 5837c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 5847c478bd9Sstevel@tonic-gate break; 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate case KIOCGTRANS: 5877c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 5887c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 5897c478bd9Sstevel@tonic-gate goto allocfailure; 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_translate; 5927c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 5937c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 5947c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 5957c478bd9Sstevel@tonic-gate mp->b_cont = datap; 5967c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 5977c478bd9Sstevel@tonic-gate break; 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate case VUIDSADDR: 6007c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe)); 6017c478bd9Sstevel@tonic-gate if (err != 0) 6027c478bd9Sstevel@tonic-gate break; 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 6057c478bd9Sstevel@tonic-gate switch (addr_probe->base) { 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate case ASCII_FIRST: 6087c478bd9Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_ascii_addr; 6097c478bd9Sstevel@tonic-gate break; 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate case TOP_FIRST: 6127c478bd9Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_top_addr; 6137c478bd9Sstevel@tonic-gate break; 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate case VKEY_FIRST: 6167c478bd9Sstevel@tonic-gate addr_ptr = &kbdd->kbdd_vkey_addr; 6177c478bd9Sstevel@tonic-gate break; 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate default: 6207c478bd9Sstevel@tonic-gate err = ENODEV; 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate if ((err == 0) && (*addr_ptr != addr_probe->data.next)) { 6237c478bd9Sstevel@tonic-gate *addr_ptr = addr_probe->data.next; 6247c478bd9Sstevel@tonic-gate goto output_format_change; 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate break; 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate case VUIDGADDR: 6297c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe)); 6307c478bd9Sstevel@tonic-gate if (err != 0) 6317c478bd9Sstevel@tonic-gate break; 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 6347c478bd9Sstevel@tonic-gate switch (addr_probe->base) { 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate case ASCII_FIRST: 6377c478bd9Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_ascii_addr; 6387c478bd9Sstevel@tonic-gate break; 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate case TOP_FIRST: 6417c478bd9Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_top_addr; 6427c478bd9Sstevel@tonic-gate break; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate case VKEY_FIRST: 6457c478bd9Sstevel@tonic-gate addr_probe->data.current = kbdd->kbdd_vkey_addr; 6467c478bd9Sstevel@tonic-gate break; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate default: 6497c478bd9Sstevel@tonic-gate err = ENODEV; 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate break; 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate case KIOCTRANSABLE: 6547c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 6557c478bd9Sstevel@tonic-gate if (err != 0) 6567c478bd9Sstevel@tonic-gate break; 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translatable != *(int *)mp->b_cont->b_rptr) { 6597c478bd9Sstevel@tonic-gate kbdd->kbdd_translatable = *(int *)mp->b_cont->b_rptr; 6607c478bd9Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 6617c478bd9Sstevel@tonic-gate goto output_format_change; 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate break; 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate case KIOCGTRANSABLE: 6667c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 6677c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 6687c478bd9Sstevel@tonic-gate goto allocfailure; 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_translatable; 6717c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 6727c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 6737c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 6747c478bd9Sstevel@tonic-gate mp->b_cont = datap; 6757c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 6767c478bd9Sstevel@tonic-gate break; 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate case KIOCSCOMPAT: 6797c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 6807c478bd9Sstevel@tonic-gate if (err != 0) 6817c478bd9Sstevel@tonic-gate break; 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate kbdd->kbdd_compat = *(int *)mp->b_cont->b_rptr; 6847c478bd9Sstevel@tonic-gate break; 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate case KIOCGCOMPAT: 6877c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 6887c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 6897c478bd9Sstevel@tonic-gate goto allocfailure; 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_compat; 6927c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 6937c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 6947c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 6957c478bd9Sstevel@tonic-gate mp->b_cont = datap; 6967c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 6977c478bd9Sstevel@tonic-gate break; 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate case KIOCSETKEY: 7007c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockey)); 7017c478bd9Sstevel@tonic-gate if (err != 0) 7027c478bd9Sstevel@tonic-gate break; 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate err = kbdsetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr, 7057c478bd9Sstevel@tonic-gate iocp->ioc_cr); 7067c478bd9Sstevel@tonic-gate /* 7077c478bd9Sstevel@tonic-gate * Since this only affects any subsequent key presses, 7087c478bd9Sstevel@tonic-gate * don't goto output_format_change. One might want to 7097c478bd9Sstevel@tonic-gate * toggle the keytable entries dynamically. 7107c478bd9Sstevel@tonic-gate */ 7117c478bd9Sstevel@tonic-gate break; 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate case KIOCGETKEY: 7147c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockey)); 7157c478bd9Sstevel@tonic-gate if (err != 0) 7167c478bd9Sstevel@tonic-gate break; 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate err = kbdgetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr); 7197c478bd9Sstevel@tonic-gate break; 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate case KIOCSKEY: 7227c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockeymap)); 7237c478bd9Sstevel@tonic-gate if (err != 0) 7247c478bd9Sstevel@tonic-gate break; 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate err = kbdskey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr, 7277c478bd9Sstevel@tonic-gate iocp->ioc_cr); 7287c478bd9Sstevel@tonic-gate /* 7297c478bd9Sstevel@tonic-gate * Since this only affects any subsequent key presses, 7307c478bd9Sstevel@tonic-gate * don't goto output_format_change. One might want to 7317c478bd9Sstevel@tonic-gate * toggle the keytable entries dynamically. 7327c478bd9Sstevel@tonic-gate */ 7337c478bd9Sstevel@tonic-gate break; 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate case KIOCGKEY: 7367c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (struct kiockeymap)); 7377c478bd9Sstevel@tonic-gate if (err != 0) 7387c478bd9Sstevel@tonic-gate break; 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate err = kbdgkey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr); 7417c478bd9Sstevel@tonic-gate break; 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate case KIOCSDIRECT: 7447c478bd9Sstevel@tonic-gate goto output_format_change; 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate case KIOCGDIRECT: 7477c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 7487c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 7497c478bd9Sstevel@tonic-gate goto allocfailure; 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = 1; /* always direct */ 7527c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 7537c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 7547c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 7557c478bd9Sstevel@tonic-gate mp->b_cont = datap; 7567c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 7577c478bd9Sstevel@tonic-gate break; 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate case KIOCTYPE: 7607c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 7617c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 7627c478bd9Sstevel@tonic-gate goto allocfailure; 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = kbdd->kbdd_state.k_id; 7657c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 7667c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 7677c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 7687c478bd9Sstevel@tonic-gate mp->b_cont = datap; 7697c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 7707c478bd9Sstevel@tonic-gate break; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate case KIOCLAYOUT: 7737c478bd9Sstevel@tonic-gate if ((datap = kbdd->kbdd_replypending) != NULL) { 7747c478bd9Sstevel@tonic-gate /* 7757c478bd9Sstevel@tonic-gate * There was an earlier KIOCLAYOUT pending; presumably, 7767c478bd9Sstevel@tonic-gate * it timed out. Throw the reply away. 7777c478bd9Sstevel@tonic-gate */ 7787c478bd9Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 7797c478bd9Sstevel@tonic-gate freemsg(datap); 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_id == KB_SUN4 || 7837c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_id == KB_PC) { 7847c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 7857c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 7867c478bd9Sstevel@tonic-gate goto allocfailure; 7877c478bd9Sstevel@tonic-gate } 7887c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0; 7897c478bd9Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */ 7907c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 7917c478bd9Sstevel@tonic-gate if (mp->b_cont) /* free msg to prevent memory leak */ 7927c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 7937c478bd9Sstevel@tonic-gate mp->b_cont = datap; 7947c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 7957c478bd9Sstevel@tonic-gate kbdd->kbdd_replypending = mp; 7967c478bd9Sstevel@tonic-gate kbdcmd(q, (char)KBD_CMD_GETLAYOUT); 7977c478bd9Sstevel@tonic-gate if (kbdd->kbdd_layoutid) 7987c478bd9Sstevel@tonic-gate (void) quntimeout(q, kbdd->kbdd_layoutid); 7997c478bd9Sstevel@tonic-gate kbdd->kbdd_layoutid = qtimeout(q, kbdlayouttimeout, 8007c478bd9Sstevel@tonic-gate kbdd, hz / 5); 8017c478bd9Sstevel@tonic-gate return; /* wait for reply from keyboard */ 8027c478bd9Sstevel@tonic-gate } else { 8037c478bd9Sstevel@tonic-gate /* 8047c478bd9Sstevel@tonic-gate * Not a Type 4 keyboard; return an immediate error. 8057c478bd9Sstevel@tonic-gate */ 8067c478bd9Sstevel@tonic-gate err = EINVAL; 8077c478bd9Sstevel@tonic-gate break; 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate case KIOCGRPTDELAY: 8117c478bd9Sstevel@tonic-gate /* 8127c478bd9Sstevel@tonic-gate * Report the autorepeat delay, unit in millisecond 8137c478bd9Sstevel@tonic-gate */ 8147c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 8157c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 8167c478bd9Sstevel@tonic-gate goto allocfailure; 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatdelay); 8197c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate /* free msg to prevent memory leak */ 8227c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL) 8237c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 8247c478bd9Sstevel@tonic-gate mp->b_cont = datap; 8257c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 8267c478bd9Sstevel@tonic-gate break; 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate case KIOCSRPTDELAY: 8297c478bd9Sstevel@tonic-gate /* 8307c478bd9Sstevel@tonic-gate * Set the autorepeat delay 8317c478bd9Sstevel@tonic-gate */ 8327c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate if (err != 0) 8357c478bd9Sstevel@tonic-gate break; 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate /* validate the input */ 8387c478bd9Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) { 8397c478bd9Sstevel@tonic-gate err = EINVAL; 8407c478bd9Sstevel@tonic-gate break; 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate kbd_repeatdelay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 8437c478bd9Sstevel@tonic-gate if (kbd_repeatdelay <= 0) 8447c478bd9Sstevel@tonic-gate kbd_repeatdelay = 1; 8457c478bd9Sstevel@tonic-gate break; 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate case KIOCGRPTRATE: 8487c478bd9Sstevel@tonic-gate /* 8497c478bd9Sstevel@tonic-gate * Report the autorepeat rate 8507c478bd9Sstevel@tonic-gate */ 8517c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 8527c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int); 8537c478bd9Sstevel@tonic-gate goto allocfailure; 8547c478bd9Sstevel@tonic-gate } 8557c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatrate); 8567c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int); 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate /* free msg to prevent memory leak */ 8597c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL) 8607c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 8617c478bd9Sstevel@tonic-gate mp->b_cont = datap; 8627c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int); 8637c478bd9Sstevel@tonic-gate break; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate case KIOCSRPTRATE: 8667c478bd9Sstevel@tonic-gate /* 8677c478bd9Sstevel@tonic-gate * Set the autorepeat rate 8687c478bd9Sstevel@tonic-gate */ 8697c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int)); 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate if (err != 0) 8727c478bd9Sstevel@tonic-gate break; 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate /* validate the input */ 8757c478bd9Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) { 8767c478bd9Sstevel@tonic-gate err = EINVAL; 8777c478bd9Sstevel@tonic-gate break; 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate kbd_repeatrate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 8807c478bd9Sstevel@tonic-gate if (kbd_repeatrate <= 0) 8817c478bd9Sstevel@tonic-gate kbd_repeatrate = 1; 8827c478bd9Sstevel@tonic-gate break; 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate default: 8857c478bd9Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */ 8867c478bd9Sstevel@tonic-gate return; 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate goto done; 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate output_format_change: 8917c478bd9Sstevel@tonic-gate kbdflush(kbdd); 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate done: 8947c478bd9Sstevel@tonic-gate if (err != 0) { 8957c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0; 8967c478bd9Sstevel@tonic-gate iocp->ioc_error = err; 8977c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK; 8987c478bd9Sstevel@tonic-gate } else { 8997c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0; 9007c478bd9Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */ 9017c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate qreply(q, mp); 9047c478bd9Sstevel@tonic-gate return; 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate allocfailure: 9077c478bd9Sstevel@tonic-gate /* 9087c478bd9Sstevel@tonic-gate * We needed to allocate something to handle this "ioctl", but 9097c478bd9Sstevel@tonic-gate * couldn't; save this "ioctl" and arrange to get called back when 9107c478bd9Sstevel@tonic-gate * it's more likely that we can get what we need. 9117c478bd9Sstevel@tonic-gate * If there's already one being saved, throw it out, since it 9127c478bd9Sstevel@tonic-gate * must have timed out. 9137c478bd9Sstevel@tonic-gate */ 9147c478bd9Sstevel@tonic-gate if (kbdd->kbdd_iocpending != NULL) 9157c478bd9Sstevel@tonic-gate freemsg(kbdd->kbdd_iocpending); 9167c478bd9Sstevel@tonic-gate kbdd->kbdd_iocpending = mp; 9177c478bd9Sstevel@tonic-gate if (kbdd->kbdd_bufcallid) 9187c478bd9Sstevel@tonic-gate qunbufcall(q, kbdd->kbdd_bufcallid); 9197c478bd9Sstevel@tonic-gate kbdd->kbdd_bufcallid = qbufcall(q, ioctlrespsize, BPRI_HI, 9207c478bd9Sstevel@tonic-gate kbdreioctl, kbdd); 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate static void 9247c478bd9Sstevel@tonic-gate kbdflush(register struct kbddata *kbdd) 9257c478bd9Sstevel@tonic-gate { 9267c478bd9Sstevel@tonic-gate register queue_t *q; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate /* Flush pending data already sent upstream */ 9297c478bd9Sstevel@tonic-gate if ((q = kbdd->kbdd_readq) != NULL && q->q_next != NULL) 9307c478bd9Sstevel@tonic-gate (void) putnextctl1(q, M_FLUSH, FLUSHR); 9317c478bd9Sstevel@tonic-gate /* Flush pending ups */ 9327c478bd9Sstevel@tonic-gate bzero(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes); 9337c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate /* 9377c478bd9Sstevel@tonic-gate * Pass keycode upstream, either translated or untranslated. 9387c478bd9Sstevel@tonic-gate */ 9397c478bd9Sstevel@tonic-gate static void 9407c478bd9Sstevel@tonic-gate kbduse(register struct kbddata *kbdd, unsigned keycode) 9417c478bd9Sstevel@tonic-gate { 9427c478bd9Sstevel@tonic-gate register queue_t *readq; 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 9457c478bd9Sstevel@tonic-gate if (kbd_input_debug) printf("KBD USE key=%d\n", keycode); 9467c478bd9Sstevel@tonic-gate #endif 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate if ((readq = kbdd->kbdd_readq) == NULL) 9497c478bd9Sstevel@tonic-gate return; 9507c478bd9Sstevel@tonic-gate if (!kbdd->kbdd_translatable || 9517c478bd9Sstevel@tonic-gate kbdd->kbdd_translate == TR_NONE) 9527c478bd9Sstevel@tonic-gate kbdputcode(keycode, readq); 9537c478bd9Sstevel@tonic-gate else 9547c478bd9Sstevel@tonic-gate kbdtranslate(kbdd, keycode, readq); 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate /* 9587c478bd9Sstevel@tonic-gate * kbdclick is used to remember the current click value of the 9597c478bd9Sstevel@tonic-gate * Sun-3 keyboard. This brain damaged keyboard will reset the 9607c478bd9Sstevel@tonic-gate * clicking to the "default" value after a reset command and 9617c478bd9Sstevel@tonic-gate * there is no way to read out the current click value. We 9627c478bd9Sstevel@tonic-gate * cannot send a click command immediately after the reset 9637c478bd9Sstevel@tonic-gate * command or the keyboard gets screwed up. So we wait until 9647c478bd9Sstevel@tonic-gate * we get the ID byte before we send back the click command. 9657c478bd9Sstevel@tonic-gate * Unfortunately, this means that there is a small window 9667c478bd9Sstevel@tonic-gate * where the keyboard can click when it really shouldn't be. 9677c478bd9Sstevel@tonic-gate * A value of -1 means that kbdclick has not been initialized yet. 9687c478bd9Sstevel@tonic-gate */ 9697c478bd9Sstevel@tonic-gate static int kbdclick = -1; 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate /* 9727c478bd9Sstevel@tonic-gate * Send command byte to keyboard, if you can. 9737c478bd9Sstevel@tonic-gate */ 9747c478bd9Sstevel@tonic-gate static void 9757c478bd9Sstevel@tonic-gate kbdcmd(register queue_t *q, char cmd) 9767c478bd9Sstevel@tonic-gate { 9777c478bd9Sstevel@tonic-gate register mblk_t *bp; 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate if (canput(q)) { 9807c478bd9Sstevel@tonic-gate if ((bp = allocb(1, BPRI_MED)) == NULL) 9817c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 9827c478bd9Sstevel@tonic-gate "kbdcmd: Can't allocate block for command"); 9837c478bd9Sstevel@tonic-gate else { 9847c478bd9Sstevel@tonic-gate *bp->b_wptr++ = cmd; 9857c478bd9Sstevel@tonic-gate putnext(q, bp); 9867c478bd9Sstevel@tonic-gate if (cmd == KBD_CMD_NOCLICK) 9877c478bd9Sstevel@tonic-gate kbdclick = 0; 9887c478bd9Sstevel@tonic-gate else if (cmd == KBD_CMD_CLICK) 9897c478bd9Sstevel@tonic-gate kbdclick = 1; 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate /* 9957c478bd9Sstevel@tonic-gate * Update the keyboard LEDs to match the current keyboard state. 9967c478bd9Sstevel@tonic-gate * Do this only on Type 4 keyboards; other keyboards don't support the 9977c478bd9Sstevel@tonic-gate * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs). 9987c478bd9Sstevel@tonic-gate */ 9997c478bd9Sstevel@tonic-gate static void 10007c478bd9Sstevel@tonic-gate kbdsetled(register struct kbddata *kbdd) 10017c478bd9Sstevel@tonic-gate { 10027c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_id == KB_SUN4 || 10037c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_id == KB_PC) { 10047c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_SETLED); 10057c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, kbdd->led_state); 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate /* 10107c478bd9Sstevel@tonic-gate * Reset the keyboard 10117c478bd9Sstevel@tonic-gate */ 10127c478bd9Sstevel@tonic-gate static void 10137c478bd9Sstevel@tonic-gate kbdreset(register struct kbddata *kbdd, uint_t hard_reset) 10147c478bd9Sstevel@tonic-gate { 10157c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 10187c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translatable) { 10197c478bd9Sstevel@tonic-gate k->k_idstate = KID_NONE; 10207c478bd9Sstevel@tonic-gate k->k_id = -1; 10217c478bd9Sstevel@tonic-gate k->k_state = NORMAL; 10227c478bd9Sstevel@tonic-gate if (hard_reset) 10237c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_RESET); 10247c478bd9Sstevel@tonic-gate } else { 10257c478bd9Sstevel@tonic-gate bzero(k, sizeof (struct keyboardstate)); 10267c478bd9Sstevel@tonic-gate k->k_id = KB_ASCII; 10277c478bd9Sstevel@tonic-gate k->k_idstate = KID_OK; 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate /* 10327c478bd9Sstevel@tonic-gate * Old special codes. 10337c478bd9Sstevel@tonic-gate */ 10347c478bd9Sstevel@tonic-gate #define OLD_SHIFTKEYS 0x80 10357c478bd9Sstevel@tonic-gate #define OLD_BUCKYBITS 0x90 10367c478bd9Sstevel@tonic-gate #define OLD_FUNNY 0xA0 10377c478bd9Sstevel@tonic-gate #define OLD_FA_UMLAUT 0xA9 10387c478bd9Sstevel@tonic-gate #define OLD_FA_CFLEX 0xAA 10397c478bd9Sstevel@tonic-gate #define OLD_FA_TILDE 0xAB 10407c478bd9Sstevel@tonic-gate #define OLD_FA_CEDILLA 0xAC 10417c478bd9Sstevel@tonic-gate #define OLD_FA_ACUTE 0xAD 10427c478bd9Sstevel@tonic-gate #define OLD_FA_GRAVE 0xAE 10437c478bd9Sstevel@tonic-gate #define OLD_ISOCHAR 0xAF 10447c478bd9Sstevel@tonic-gate #define OLD_STRING 0xB0 10457c478bd9Sstevel@tonic-gate #define OLD_LEFTFUNC 0xC0 10467c478bd9Sstevel@tonic-gate #define OLD_RIGHTFUNC 0xD0 10477c478bd9Sstevel@tonic-gate #define OLD_TOPFUNC 0xE0 10487c478bd9Sstevel@tonic-gate #define OLD_BOTTOMFUNC 0xF0 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate /* 10517c478bd9Sstevel@tonic-gate * Map old special codes to new ones. 10527c478bd9Sstevel@tonic-gate * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F. 10537c478bd9Sstevel@tonic-gate */ 10547c478bd9Sstevel@tonic-gate static ushort_t special_old_to_new[] = { 10557c478bd9Sstevel@tonic-gate SHIFTKEYS, 10567c478bd9Sstevel@tonic-gate BUCKYBITS, 10577c478bd9Sstevel@tonic-gate FUNNY, 10587c478bd9Sstevel@tonic-gate STRING, 10597c478bd9Sstevel@tonic-gate LEFTFUNC, 10607c478bd9Sstevel@tonic-gate RIGHTFUNC, 10617c478bd9Sstevel@tonic-gate TOPFUNC, 10627c478bd9Sstevel@tonic-gate BOTTOMFUNC, 10637c478bd9Sstevel@tonic-gate }; 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate /* 10667c478bd9Sstevel@tonic-gate * Set individual keystation translation from old-style entry. 10677c478bd9Sstevel@tonic-gate * TODO: Have each keyboard own own translation tables. 10687c478bd9Sstevel@tonic-gate */ 10697c478bd9Sstevel@tonic-gate static int 10707c478bd9Sstevel@tonic-gate kbdsetkey(register struct kbddata *kbdd, struct kiockey *key, cred_t *cr) 10717c478bd9Sstevel@tonic-gate { 10727c478bd9Sstevel@tonic-gate int strtabindex, i; 10737c478bd9Sstevel@tonic-gate struct keymap *km; 10747c478bd9Sstevel@tonic-gate register int tablemask; 10757c478bd9Sstevel@tonic-gate register ushort_t entry; 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 10787c478bd9Sstevel@tonic-gate return (EINVAL); 10797c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 10807c478bd9Sstevel@tonic-gate return (EINVAL); 10817c478bd9Sstevel@tonic-gate tablemask = key->kio_tablemask; 10827c478bd9Sstevel@tonic-gate if (tablemask == KIOCABORT1) { 10837c478bd9Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 10847c478bd9Sstevel@tonic-gate return (EPERM); 10857c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station; 10867c478bd9Sstevel@tonic-gate return (0); 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate if (tablemask == KIOCABORT2) { 10897c478bd9Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 10907c478bd9Sstevel@tonic-gate return (EPERM); 10917c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station; 10927c478bd9Sstevel@tonic-gate return (0); 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate if ((tablemask & ALTGRAPHMASK) || 10957c478bd9Sstevel@tonic-gate (km = settable(kbdd, (uint_t)tablemask)) == NULL) 10967c478bd9Sstevel@tonic-gate return (EINVAL); 10977c478bd9Sstevel@tonic-gate if (key->kio_entry >= (uchar_t)OLD_STRING && 10987c478bd9Sstevel@tonic-gate key->kio_entry <= (uchar_t)(OLD_STRING + 15)) { 10997c478bd9Sstevel@tonic-gate strtabindex = key->kio_entry - OLD_STRING; 11007c478bd9Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 11017c478bd9Sstevel@tonic-gate keystringtab[strtabindex][i] = key->kio_string[i]; 11027c478bd9Sstevel@tonic-gate keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate entry = key->kio_entry; 11057c478bd9Sstevel@tonic-gate /* 11067c478bd9Sstevel@tonic-gate * There's nothing we need do with OLD_ISOCHAR. 11077c478bd9Sstevel@tonic-gate */ 11087c478bd9Sstevel@tonic-gate if (entry != OLD_ISOCHAR) { 11097c478bd9Sstevel@tonic-gate if (entry & 0x80) { 11107c478bd9Sstevel@tonic-gate if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE) 11117c478bd9Sstevel@tonic-gate entry = FA_CLASS + (entry & 0x0F) - 9; 11127c478bd9Sstevel@tonic-gate else 11137c478bd9Sstevel@tonic-gate entry = 11147c478bd9Sstevel@tonic-gate special_old_to_new[entry >> 4 & 0x07] 11157c478bd9Sstevel@tonic-gate + (entry & 0x0F); 11167c478bd9Sstevel@tonic-gate } 11177c478bd9Sstevel@tonic-gate } 11187c478bd9Sstevel@tonic-gate km->keymap[key->kio_station] = entry; 11197c478bd9Sstevel@tonic-gate return (0); 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate /* 11237c478bd9Sstevel@tonic-gate * Map new special codes to old ones. 11247c478bd9Sstevel@tonic-gate * Indexed by (new special code) >> 8; add (new special code) & 0xFF. 11257c478bd9Sstevel@tonic-gate */ 11267c478bd9Sstevel@tonic-gate static uchar_t special_new_to_old[] = { 11277c478bd9Sstevel@tonic-gate 0, /* normal */ 11287c478bd9Sstevel@tonic-gate OLD_SHIFTKEYS, /* SHIFTKEYS */ 11297c478bd9Sstevel@tonic-gate OLD_BUCKYBITS, /* BUCKYBITS */ 11307c478bd9Sstevel@tonic-gate OLD_FUNNY, /* FUNNY */ 11317c478bd9Sstevel@tonic-gate OLD_FA_UMLAUT, /* FA_CLASS */ 11327c478bd9Sstevel@tonic-gate OLD_STRING, /* STRING */ 11337c478bd9Sstevel@tonic-gate OLD_LEFTFUNC, /* FUNCKEYS */ 11347c478bd9Sstevel@tonic-gate }; 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate /* 11377c478bd9Sstevel@tonic-gate * Get individual keystation translation as old-style entry. 11387c478bd9Sstevel@tonic-gate */ 11397c478bd9Sstevel@tonic-gate static int 11407c478bd9Sstevel@tonic-gate kbdgetkey(register struct kbddata *kbdd, struct kiockey *key) 11417c478bd9Sstevel@tonic-gate { 11427c478bd9Sstevel@tonic-gate int strtabindex, i; 11437c478bd9Sstevel@tonic-gate struct keymap *km; 11447c478bd9Sstevel@tonic-gate register ushort_t entry; 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 11477c478bd9Sstevel@tonic-gate return (EINVAL); 11487c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 11497c478bd9Sstevel@tonic-gate return (EINVAL); 11507c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) { 11517c478bd9Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1; 11527c478bd9Sstevel@tonic-gate return (0); 11537c478bd9Sstevel@tonic-gate } 11547c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) { 11557c478bd9Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2; 11567c478bd9Sstevel@tonic-gate return (0); 11577c478bd9Sstevel@tonic-gate } 11587c478bd9Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 11597c478bd9Sstevel@tonic-gate return (EINVAL); 11607c478bd9Sstevel@tonic-gate entry = km->keymap[key->kio_station]; 11617c478bd9Sstevel@tonic-gate if (entry & 0xFF00) 11627c478bd9Sstevel@tonic-gate key->kio_entry = 11637c478bd9Sstevel@tonic-gate special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8] 11647c478bd9Sstevel@tonic-gate + (entry & 0x00FF); 11657c478bd9Sstevel@tonic-gate else { 11667c478bd9Sstevel@tonic-gate if (entry & 0x80) 11677c478bd9Sstevel@tonic-gate key->kio_entry = (ushort_t)OLD_ISOCHAR; /* you lose */ 11687c478bd9Sstevel@tonic-gate else 11697c478bd9Sstevel@tonic-gate key->kio_entry = (ushort_t)entry; 11707c478bd9Sstevel@tonic-gate } 11717c478bd9Sstevel@tonic-gate if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) { 11727c478bd9Sstevel@tonic-gate strtabindex = entry - STRING; 11737c478bd9Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 11747c478bd9Sstevel@tonic-gate key->kio_string[i] = keystringtab[strtabindex][i]; 11757c478bd9Sstevel@tonic-gate } 11767c478bd9Sstevel@tonic-gate return (0); 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate /* 11807c478bd9Sstevel@tonic-gate * Set individual keystation translation from new-style entry. 11817c478bd9Sstevel@tonic-gate * TODO: Have each keyboard own own translation tables. 11827c478bd9Sstevel@tonic-gate */ 11837c478bd9Sstevel@tonic-gate static int 11847c478bd9Sstevel@tonic-gate kbdskey(register struct kbddata *kbdd, struct kiockeymap *key, cred_t *cr) 11857c478bd9Sstevel@tonic-gate { 11867c478bd9Sstevel@tonic-gate int strtabindex, i; 11877c478bd9Sstevel@tonic-gate struct keymap *km; 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 11907c478bd9Sstevel@tonic-gate return (EINVAL); 11917c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 11927c478bd9Sstevel@tonic-gate return (EINVAL); 11937c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) { 11947c478bd9Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 11957c478bd9Sstevel@tonic-gate return (EPERM); 11967c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station; 11977c478bd9Sstevel@tonic-gate return (0); 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) { 12007c478bd9Sstevel@tonic-gate if (secpolicy_console(cr) != 0) 12017c478bd9Sstevel@tonic-gate return (EPERM); 12027c478bd9Sstevel@tonic-gate kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station; 12037c478bd9Sstevel@tonic-gate return (0); 12047c478bd9Sstevel@tonic-gate } 12057c478bd9Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 12067c478bd9Sstevel@tonic-gate return (EINVAL); 12077c478bd9Sstevel@tonic-gate if (key->kio_entry >= STRING && 12087c478bd9Sstevel@tonic-gate key->kio_entry <= (ushort_t)(STRING + 15)) { 12097c478bd9Sstevel@tonic-gate strtabindex = key->kio_entry-STRING; 12107c478bd9Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 12117c478bd9Sstevel@tonic-gate keystringtab[strtabindex][i] = key->kio_string[i]; 12127c478bd9Sstevel@tonic-gate keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 12137c478bd9Sstevel@tonic-gate } 12147c478bd9Sstevel@tonic-gate km->keymap[key->kio_station] = key->kio_entry; 12157c478bd9Sstevel@tonic-gate return (0); 12167c478bd9Sstevel@tonic-gate } 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate /* 12197c478bd9Sstevel@tonic-gate * Get individual keystation translation as new-style entry. 12207c478bd9Sstevel@tonic-gate */ 12217c478bd9Sstevel@tonic-gate static int 12227c478bd9Sstevel@tonic-gate kbdgkey(register struct kbddata *kbdd, struct kiockeymap *key) 12237c478bd9Sstevel@tonic-gate { 12247c478bd9Sstevel@tonic-gate int strtabindex, i; 12257c478bd9Sstevel@tonic-gate struct keymap *km; 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate if (key->kio_station >= KEYMAP_SIZE) 12287c478bd9Sstevel@tonic-gate return (EINVAL); 12297c478bd9Sstevel@tonic-gate if (kbdd->kbdd_state.k_curkeyboard == NULL) 12307c478bd9Sstevel@tonic-gate return (EINVAL); 12317c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT1) { 12327c478bd9Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1; 12337c478bd9Sstevel@tonic-gate return (0); 12347c478bd9Sstevel@tonic-gate } 12357c478bd9Sstevel@tonic-gate if (key->kio_tablemask == KIOCABORT2) { 12367c478bd9Sstevel@tonic-gate key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2; 12377c478bd9Sstevel@tonic-gate return (0); 12387c478bd9Sstevel@tonic-gate } 12397c478bd9Sstevel@tonic-gate if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 12407c478bd9Sstevel@tonic-gate return (EINVAL); 12417c478bd9Sstevel@tonic-gate key->kio_entry = km->keymap[key->kio_station]; 12427c478bd9Sstevel@tonic-gate if (key->kio_entry >= STRING && 12437c478bd9Sstevel@tonic-gate key->kio_entry <= (ushort_t)(STRING + 15)) { 12447c478bd9Sstevel@tonic-gate strtabindex = key->kio_entry-STRING; 12457c478bd9Sstevel@tonic-gate for (i = 0; i < KTAB_STRLEN; i++) 12467c478bd9Sstevel@tonic-gate key->kio_string[i] = keystringtab[strtabindex][i]; 12477c478bd9Sstevel@tonic-gate } 12487c478bd9Sstevel@tonic-gate return (0); 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate static void 12527c478bd9Sstevel@tonic-gate kbdlayouttimeout(void *arg) 12537c478bd9Sstevel@tonic-gate { 12547c478bd9Sstevel@tonic-gate struct kbddata *kbdd = arg; 12557c478bd9Sstevel@tonic-gate mblk_t *mp; 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate kbdd->kbdd_layoutid = 0; 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate /* 12607c478bd9Sstevel@tonic-gate * Timed out waiting for reply to "get keyboard layout" command. 12617c478bd9Sstevel@tonic-gate * Return an ETIME error. 12627c478bd9Sstevel@tonic-gate */ 12637c478bd9Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) { 12647c478bd9Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 12657c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK; 12667c478bd9Sstevel@tonic-gate ((struct iocblk *)mp->b_rptr)->ioc_error = ETIME; 12677c478bd9Sstevel@tonic-gate putnext(kbdd->kbdd_readq, mp); 12687c478bd9Sstevel@tonic-gate } 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate /* 12727c478bd9Sstevel@tonic-gate * Put procedure for input from driver end of stream (read queue). 12737c478bd9Sstevel@tonic-gate */ 12747c478bd9Sstevel@tonic-gate static void 12757c478bd9Sstevel@tonic-gate kbdrput(register queue_t *q, register mblk_t *mp) 12767c478bd9Sstevel@tonic-gate { 12777c478bd9Sstevel@tonic-gate struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 12787c478bd9Sstevel@tonic-gate register mblk_t *bp; 12797c478bd9Sstevel@tonic-gate register uchar_t *readp; 12807c478bd9Sstevel@tonic-gate struct iocblk *iocp; 12817c478bd9Sstevel@tonic-gate 12827c478bd9Sstevel@tonic-gate if (kbdd == 0) { 12837c478bd9Sstevel@tonic-gate freemsg(mp); /* nobody's listening */ 12847c478bd9Sstevel@tonic-gate return; 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate case M_FLUSH: 12907c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 12917c478bd9Sstevel@tonic-gate flushq(WR(q), FLUSHDATA); 12927c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 12937c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate default: 12967c478bd9Sstevel@tonic-gate putnext(q, mp); 12977c478bd9Sstevel@tonic-gate return; 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate case M_BREAK: 13007c478bd9Sstevel@tonic-gate /* 13017c478bd9Sstevel@tonic-gate * Will get M_BREAK only if this is not the system 13027c478bd9Sstevel@tonic-gate * keyboard, otherwise serial port will eat break 13037c478bd9Sstevel@tonic-gate * and call kmdb/OBP, without passing anything up. 13047c478bd9Sstevel@tonic-gate */ 13057c478bd9Sstevel@tonic-gate freemsg(mp); 13067c478bd9Sstevel@tonic-gate return; 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate case M_IOCACK: 13097c478bd9Sstevel@tonic-gate case M_IOCNAK: 13107c478bd9Sstevel@tonic-gate /* 13117c478bd9Sstevel@tonic-gate * If we are doing an "ioctl" ourselves, check if this 13127c478bd9Sstevel@tonic-gate * is the reply to that code. If so, wake up the 13137c478bd9Sstevel@tonic-gate * "open" routine, and toss the reply, otherwise just 13147c478bd9Sstevel@tonic-gate * pass it up. 13157c478bd9Sstevel@tonic-gate */ 13167c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 13177c478bd9Sstevel@tonic-gate if (!(kbdd->kbdd_flags & KBD_IOCWAIT) || 13187c478bd9Sstevel@tonic-gate iocp->ioc_id != kbdd->kbdd_iocid) { 13197c478bd9Sstevel@tonic-gate /* 13207c478bd9Sstevel@tonic-gate * This isn't the reply we're looking for. Move along. 13217c478bd9Sstevel@tonic-gate */ 13227c478bd9Sstevel@tonic-gate if (kbdd->kbdd_flags & KBD_OPEN) 13237c478bd9Sstevel@tonic-gate putnext(q, mp); 13247c478bd9Sstevel@tonic-gate else 13257c478bd9Sstevel@tonic-gate freemsg(mp); /* not ready to listen */ 13267c478bd9Sstevel@tonic-gate } else { 13277c478bd9Sstevel@tonic-gate kbdd->kbdd_flags &= ~KBD_IOCWAIT; 13287c478bd9Sstevel@tonic-gate kbdd->kbdd_iocerror = iocp->ioc_error; 13297c478bd9Sstevel@tonic-gate freemsg(mp); 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate return; 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate case M_DATA: 13347c478bd9Sstevel@tonic-gate if (!(kbdd->kbdd_flags & KBD_OPEN)) { 13357c478bd9Sstevel@tonic-gate freemsg(mp); /* not read to listen */ 13367c478bd9Sstevel@tonic-gate return; 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate break; 13397c478bd9Sstevel@tonic-gate } 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate /* 13427c478bd9Sstevel@tonic-gate * A data message, consisting of bytes from the keyboard. 13437c478bd9Sstevel@tonic-gate * Ram them through our state machine. 13447c478bd9Sstevel@tonic-gate */ 13457c478bd9Sstevel@tonic-gate bp = mp; 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate do { 13487c478bd9Sstevel@tonic-gate readp = bp->b_rptr; 13497c478bd9Sstevel@tonic-gate while (readp < bp->b_wptr) 13507c478bd9Sstevel@tonic-gate kbdinput(kbdd, *readp++); 13517c478bd9Sstevel@tonic-gate bp->b_rptr = readp; 13527c478bd9Sstevel@tonic-gate } while ((bp = bp->b_cont) != NULL); /* next block, if any */ 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate freemsg(mp); 13557c478bd9Sstevel@tonic-gate } 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate /* 13587c478bd9Sstevel@tonic-gate * A keypress was received. Process it through the state machine 13597c478bd9Sstevel@tonic-gate * to check for aborts. 13607c478bd9Sstevel@tonic-gate */ 13617c478bd9Sstevel@tonic-gate static void 13627c478bd9Sstevel@tonic-gate kbdinput(register struct kbddata *kbdd, register unsigned key) 13637c478bd9Sstevel@tonic-gate { 13647c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 13657c478bd9Sstevel@tonic-gate register mblk_t *mp; 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 13687c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 13697c478bd9Sstevel@tonic-gate if (kbd_input_debug) 13707c478bd9Sstevel@tonic-gate printf("kbdinput key %x\n", key); 13717c478bd9Sstevel@tonic-gate #endif 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate switch (k->k_idstate) { 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate case KID_NONE: 13767c478bd9Sstevel@tonic-gate if (key == RESETKEY) { 13777c478bd9Sstevel@tonic-gate k->k_idstate = KID_GOT_PREFACE; 13787c478bd9Sstevel@tonic-gate } else { 13797c478bd9Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 13807c478bd9Sstevel@tonic-gate /* allows hot plug of kbd after booting without kbd */ 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate return; 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate case KID_GOT_PREFACE: 13857c478bd9Sstevel@tonic-gate kbdid(kbdd, (int)key); 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate /* 13887c478bd9Sstevel@tonic-gate * We just did a reset command to a Type 3 or Type 4 13897c478bd9Sstevel@tonic-gate * keyboard which sets the click back to the default 13907c478bd9Sstevel@tonic-gate * (which is currently ON!). We use the kbdclick 13917c478bd9Sstevel@tonic-gate * variable to see if the keyboard should be turned on 13927c478bd9Sstevel@tonic-gate * or off. If it has not been set, then we use the 13937c478bd9Sstevel@tonic-gate * keyboard-click? property. 13947c478bd9Sstevel@tonic-gate */ 13957c478bd9Sstevel@tonic-gate switch (kbdclick) { 13967c478bd9Sstevel@tonic-gate case 0: 13977c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK); 13987c478bd9Sstevel@tonic-gate break; 13997c478bd9Sstevel@tonic-gate case 1: 14007c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_CLICK); 14017c478bd9Sstevel@tonic-gate break; 14027c478bd9Sstevel@tonic-gate case -1: 14037c478bd9Sstevel@tonic-gate default: 14047c478bd9Sstevel@tonic-gate { 14057c478bd9Sstevel@tonic-gate char wrkbuf[8]; 14067c478bd9Sstevel@tonic-gate int len; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK); 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate bzero(wrkbuf, 8); 14117c478bd9Sstevel@tonic-gate len = 7; 14127c478bd9Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_ANY, 14137c478bd9Sstevel@tonic-gate ddi_root_node(), 0, "keyboard-click?", 14147c478bd9Sstevel@tonic-gate (caddr_t)wrkbuf, &len) == 14157c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS && 14167c478bd9Sstevel@tonic-gate len > 0 && len < 8) { 14177c478bd9Sstevel@tonic-gate if (strcmp(wrkbuf, "true") == 0) { 14187c478bd9Sstevel@tonic-gate kbdcmd(kbdd->kbdd_writeq, 14197c478bd9Sstevel@tonic-gate KBD_CMD_CLICK); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate } 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate break; 14247c478bd9Sstevel@tonic-gate } 14257c478bd9Sstevel@tonic-gate /* 14267c478bd9Sstevel@tonic-gate * A keyboard reset clears the LEDs. 14277c478bd9Sstevel@tonic-gate * Restore the LEDs from the last value we set 14287c478bd9Sstevel@tonic-gate * them to. 14297c478bd9Sstevel@tonic-gate */ 14307c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 14317c478bd9Sstevel@tonic-gate return; 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate case KID_OK: 14347c478bd9Sstevel@tonic-gate switch (key) { 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate #if defined(KBD_PRESSED_PREFIX) 14377c478bd9Sstevel@tonic-gate case KBD_PRESSED_PREFIX: 14387c478bd9Sstevel@tonic-gate k->k_idstate = KID_GOT_PRESSED; 14397c478bd9Sstevel@tonic-gate return; 14407c478bd9Sstevel@tonic-gate #endif 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate #if defined(KBD_RELEASED_PREFIX) 14437c478bd9Sstevel@tonic-gate case KBD_RELEASED_PREFIX: 14447c478bd9Sstevel@tonic-gate k->k_idstate = KID_GOT_RELEASED; 14457c478bd9Sstevel@tonic-gate return; 14467c478bd9Sstevel@tonic-gate #endif 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate case 0: 14497c478bd9Sstevel@tonic-gate kbdreset(kbdd, HARD_RESET); 14507c478bd9Sstevel@tonic-gate return; 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate /* 14537c478bd9Sstevel@tonic-gate * we want to check for ID only if we are in 14547c478bd9Sstevel@tonic-gate * translatable mode. 14557c478bd9Sstevel@tonic-gate */ 14567c478bd9Sstevel@tonic-gate case RESETKEY: 14577c478bd9Sstevel@tonic-gate kbdreset(kbdd, NO_HARD_RESET); 14587c478bd9Sstevel@tonic-gate if (k->k_idstate == KID_NONE) { 14597c478bd9Sstevel@tonic-gate k->k_idstate = KID_GOT_PREFACE; 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate return; 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate case LAYOUTKEY: 14647c478bd9Sstevel@tonic-gate k->k_idstate = KID_GOT_LAYOUT; 14657c478bd9Sstevel@tonic-gate return; 14667c478bd9Sstevel@tonic-gate } 14677c478bd9Sstevel@tonic-gate break; 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate #if defined(KBD_PRESSED_PREFIX) 14707c478bd9Sstevel@tonic-gate case KID_GOT_PRESSED: 14717c478bd9Sstevel@tonic-gate key = BUILDKEY(key, PRESSED); 14727c478bd9Sstevel@tonic-gate k->k_idstate = KID_OK; 14737c478bd9Sstevel@tonic-gate break; 14747c478bd9Sstevel@tonic-gate #endif 14757c478bd9Sstevel@tonic-gate #if defined(KBD_RELEASED_PREFIX) 14767c478bd9Sstevel@tonic-gate case KID_GOT_RELEASED: 14777c478bd9Sstevel@tonic-gate key = BUILDKEY(key, RELEASED); 14787c478bd9Sstevel@tonic-gate k->k_idstate = KID_OK; 14797c478bd9Sstevel@tonic-gate break; 14807c478bd9Sstevel@tonic-gate #endif 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate case KID_GOT_LAYOUT: 14837c478bd9Sstevel@tonic-gate if (kbdd->kbdd_layoutid) 14847c478bd9Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, 14857c478bd9Sstevel@tonic-gate kbdd->kbdd_layoutid); 14867c478bd9Sstevel@tonic-gate if ((mp = kbdd->kbdd_replypending) != NULL) { 14877c478bd9Sstevel@tonic-gate kbdd->kbdd_replypending = NULL; 14887c478bd9Sstevel@tonic-gate *(int *)mp->b_cont->b_wptr = key; 14897c478bd9Sstevel@tonic-gate mp->b_cont->b_wptr += sizeof (int); 14907c478bd9Sstevel@tonic-gate putnext(kbdd->kbdd_readq, mp); 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate k->k_idstate = KID_OK; 14937c478bd9Sstevel@tonic-gate return; 14947c478bd9Sstevel@tonic-gate } 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate switch (k->k_state) { 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate #if defined(__sparc) 14997c478bd9Sstevel@tonic-gate normalstate: 15007c478bd9Sstevel@tonic-gate k->k_state = NORMAL; 15017c478bd9Sstevel@tonic-gate /* FALLTHRU */ 15027c478bd9Sstevel@tonic-gate #endif 15037c478bd9Sstevel@tonic-gate case NORMAL: 15047c478bd9Sstevel@tonic-gate #if defined(__sparc) 15057c478bd9Sstevel@tonic-gate if (k->k_curkeyboard) { 15067c478bd9Sstevel@tonic-gate if (key == k->k_curkeyboard->k_abort1) { 15077c478bd9Sstevel@tonic-gate k->k_state = ABORT1; 15087c478bd9Sstevel@tonic-gate break; 15097c478bd9Sstevel@tonic-gate } 1510*e4603304Sqz150045 if ((key == k->k_curkeyboard->k_newabort1) || 1511*e4603304Sqz150045 (key == k->k_curkeyboard->k_newabort1a)) { 1512*e4603304Sqz150045 k->k_state = NEWABORT1; 1513*e4603304Sqz150045 break; 1514*e4603304Sqz150045 } 15157c478bd9Sstevel@tonic-gate } 15167c478bd9Sstevel@tonic-gate #endif 15177c478bd9Sstevel@tonic-gate kbduse(kbdd, key); 15187c478bd9Sstevel@tonic-gate break; 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate #if defined(__sparc) 15217c478bd9Sstevel@tonic-gate case ABORT1: 15227c478bd9Sstevel@tonic-gate if (k->k_curkeyboard) { 15237c478bd9Sstevel@tonic-gate /* 15247c478bd9Sstevel@tonic-gate * Only recognize this as an abort sequence if 15257c478bd9Sstevel@tonic-gate * the "hardware" console is set to be this device. 15267c478bd9Sstevel@tonic-gate */ 15277c478bd9Sstevel@tonic-gate if (key == k->k_curkeyboard->k_abort2 && 15287c478bd9Sstevel@tonic-gate rconsvp == wsconsvp) { 15297c478bd9Sstevel@tonic-gate DELAY(100000); 15307c478bd9Sstevel@tonic-gate abort_sequence_enter((char *)NULL); 15317c478bd9Sstevel@tonic-gate k->k_state = NORMAL; 15327c478bd9Sstevel@tonic-gate kbduse(kbdd, IDLEKEY); /* fake */ 15337c478bd9Sstevel@tonic-gate return; 15347c478bd9Sstevel@tonic-gate } else { 15357c478bd9Sstevel@tonic-gate kbduse(kbdd, k->k_curkeyboard->k_abort1); 15367c478bd9Sstevel@tonic-gate goto normalstate; 15377c478bd9Sstevel@tonic-gate } 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate break; 1540*e4603304Sqz150045 case NEWABORT1: 1541*e4603304Sqz150045 if (k->k_curkeyboard) { 1542*e4603304Sqz150045 /* 1543*e4603304Sqz150045 * Only recognize this as an abort sequence if 1544*e4603304Sqz150045 * the "hardware" console is set to be this device. 1545*e4603304Sqz150045 */ 1546*e4603304Sqz150045 if (key == k->k_curkeyboard->k_newabort2 && 1547*e4603304Sqz150045 rconsvp == wsconsvp) { 1548*e4603304Sqz150045 DELAY(100000); 1549*e4603304Sqz150045 abort_sequence_enter((char *)NULL); 1550*e4603304Sqz150045 k->k_state = NORMAL; 1551*e4603304Sqz150045 kbduse(kbdd, IDLEKEY); /* fake */ 1552*e4603304Sqz150045 return; 1553*e4603304Sqz150045 } else { 1554*e4603304Sqz150045 kbduse(kbdd, k->k_curkeyboard->k_newabort1); 1555*e4603304Sqz150045 goto normalstate; 1556*e4603304Sqz150045 } 1557*e4603304Sqz150045 } 1558*e4603304Sqz150045 break; 15597c478bd9Sstevel@tonic-gate #endif 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate case COMPOSE1: 15627c478bd9Sstevel@tonic-gate case COMPOSE2: 15637c478bd9Sstevel@tonic-gate case FLTACCENT: 15647c478bd9Sstevel@tonic-gate if (key != IDLEKEY) 15657c478bd9Sstevel@tonic-gate kbduse(kbdd, key); 15667c478bd9Sstevel@tonic-gate break; 15677c478bd9Sstevel@tonic-gate } 15687c478bd9Sstevel@tonic-gate } 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate static void 15717c478bd9Sstevel@tonic-gate kbdid(register struct kbddata *kbdd, int id) 15727c478bd9Sstevel@tonic-gate { 15737c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 15747c478bd9Sstevel@tonic-gate int i; 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate k->k_idstate = KID_OK; 15797c478bd9Sstevel@tonic-gate k->k_shiftmask = 0; 15807c478bd9Sstevel@tonic-gate k->k_buckybits = 0; 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate /* 15837c478bd9Sstevel@tonic-gate * Reset k_rptkey to IDLEKEY. We need to cancel 15847c478bd9Sstevel@tonic-gate * the autorepeat feature, if any. 15857c478bd9Sstevel@tonic-gate */ 15867c478bd9Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) { 15877c478bd9Sstevel@tonic-gate if (kbdd->kbdd_rptid) 15887c478bd9Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid); 15897c478bd9Sstevel@tonic-gate kbdd->kbdd_rptid = 0; 15907c478bd9Sstevel@tonic-gate k->k_rptkey = IDLEKEY; 15917c478bd9Sstevel@tonic-gate } 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate k->k_curkeyboard = NULL; 15947c478bd9Sstevel@tonic-gate for (i = 0; keytables[i].table; i++) { 15957c478bd9Sstevel@tonic-gate if (keytables[i].id == id) { 15967c478bd9Sstevel@tonic-gate k->k_id = id; 15977c478bd9Sstevel@tonic-gate k->k_curkeyboard = keytables[i].table; 15987c478bd9Sstevel@tonic-gate break; 15997c478bd9Sstevel@tonic-gate } 16007c478bd9Sstevel@tonic-gate } 16017c478bd9Sstevel@tonic-gate if (!k->k_curkeyboard) { 16027c478bd9Sstevel@tonic-gate k->k_id = keytables[0].id; 16037c478bd9Sstevel@tonic-gate k->k_curkeyboard = keytables[0].table; 16047c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Unknown keyboard type, " 16057c478bd9Sstevel@tonic-gate "Type %d assumed", k->k_id); 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate /* 16107c478bd9Sstevel@tonic-gate * This routine determines which table we should look in to decode 16117c478bd9Sstevel@tonic-gate * the current keycode. 16127c478bd9Sstevel@tonic-gate */ 16137c478bd9Sstevel@tonic-gate static struct keymap * 16147c478bd9Sstevel@tonic-gate settable(register struct kbddata *kbdd, register uint_t mask) 16157c478bd9Sstevel@tonic-gate { 16167c478bd9Sstevel@tonic-gate register struct keyboard *kp; 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate kp = kbdd->kbdd_state.k_curkeyboard; 16197c478bd9Sstevel@tonic-gate if (kp == NULL) 16207c478bd9Sstevel@tonic-gate return (NULL); 16217c478bd9Sstevel@tonic-gate if (mask & UPMASK) 16227c478bd9Sstevel@tonic-gate return (kp->k_up); 16237c478bd9Sstevel@tonic-gate if (mask & NUMLOCKMASK) 16247c478bd9Sstevel@tonic-gate return (kp->k_numlock); 16257c478bd9Sstevel@tonic-gate if (mask & CTRLMASK) 16267c478bd9Sstevel@tonic-gate return (kp->k_control); 16277c478bd9Sstevel@tonic-gate if (mask & ALTGRAPHMASK) 16287c478bd9Sstevel@tonic-gate return (kp->k_altgraph); 16297c478bd9Sstevel@tonic-gate if (mask & SHIFTMASK) 16307c478bd9Sstevel@tonic-gate return (kp->k_shifted); 16317c478bd9Sstevel@tonic-gate if (mask & CAPSMASK) 16327c478bd9Sstevel@tonic-gate return (kp->k_caps); 16337c478bd9Sstevel@tonic-gate return (kp->k_normal); 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate static void 16377c478bd9Sstevel@tonic-gate kbdrpt(void *arg) 16387c478bd9Sstevel@tonic-gate { 16397c478bd9Sstevel@tonic-gate struct kbddata *kbdd = arg; 16407c478bd9Sstevel@tonic-gate struct keyboardstate *k; 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 16437c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 16447c478bd9Sstevel@tonic-gate if (kbd_rpt_debug) 16457c478bd9Sstevel@tonic-gate printf("kbdrpt key %x\n", k->k_rptkey); 16467c478bd9Sstevel@tonic-gate #endif 16477c478bd9Sstevel@tonic-gate kbdd->kbdd_rptid = 0; 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate kbdkeyreleased(kbdd, KEYOF(k->k_rptkey)); 16507c478bd9Sstevel@tonic-gate kbduse(kbdd, k->k_rptkey); 16517c478bd9Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) { 16527c478bd9Sstevel@tonic-gate kbdd->kbdd_rptid = qtimeout(kbdd->kbdd_readq, kbdrpt, 16537c478bd9Sstevel@tonic-gate kbdd, kbd_repeatrate); 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate } 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate static void 16587c478bd9Sstevel@tonic-gate kbdcancelrpt(register struct kbddata *kbdd) 16597c478bd9Sstevel@tonic-gate { 16607c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 16637c478bd9Sstevel@tonic-gate if (k->k_rptkey != IDLEKEY) { 16647c478bd9Sstevel@tonic-gate if (kbdd->kbdd_rptid) 16657c478bd9Sstevel@tonic-gate (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid); 16667c478bd9Sstevel@tonic-gate kbdd->kbdd_rptid = 0; 16677c478bd9Sstevel@tonic-gate k->k_rptkey = IDLEKEY; 16687c478bd9Sstevel@tonic-gate } 16697c478bd9Sstevel@tonic-gate ASSERT(kbdd->kbdd_rptid == 0); 16707c478bd9Sstevel@tonic-gate } 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate static void 16737c478bd9Sstevel@tonic-gate kbdtranslate(struct kbddata *kbdd, unsigned keycode, queue_t *q) 16747c478bd9Sstevel@tonic-gate { 16757c478bd9Sstevel@tonic-gate register uchar_t key; 16767c478bd9Sstevel@tonic-gate register unsigned newstate; 16777c478bd9Sstevel@tonic-gate unsigned shiftmask; 16787c478bd9Sstevel@tonic-gate register ushort_t entry, entrytype; 16797c478bd9Sstevel@tonic-gate register char *cp, *bufp; 16807c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 16817c478bd9Sstevel@tonic-gate ushort_t result_iso; 16827c478bd9Sstevel@tonic-gate struct keymap *km; 16837c478bd9Sstevel@tonic-gate Firm_event fe; 16847c478bd9Sstevel@tonic-gate int i, ret_val; 16857c478bd9Sstevel@tonic-gate char buf[14]; 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 16887c478bd9Sstevel@tonic-gate newstate = STATEOF(keycode); 16897c478bd9Sstevel@tonic-gate key = KEYOF(keycode); 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 16927c478bd9Sstevel@tonic-gate if (kbd_input_debug) { 16937c478bd9Sstevel@tonic-gate printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n", 16947c478bd9Sstevel@tonic-gate keycode, newstate, key); 16957c478bd9Sstevel@tonic-gate } 16967c478bd9Sstevel@tonic-gate #endif 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_UNTRANS_EVENT) { 16997c478bd9Sstevel@tonic-gate if (newstate == PRESSED) { 17007c478bd9Sstevel@tonic-gate bzero(&fe, sizeof (fe)); 17017c478bd9Sstevel@tonic-gate fe.id = key; 17027c478bd9Sstevel@tonic-gate fe.value = 1; 17037c478bd9Sstevel@tonic-gate kbdqueuepress(kbdd, key, &fe); 17047c478bd9Sstevel@tonic-gate } else { 17057c478bd9Sstevel@tonic-gate kbdkeyreleased(kbdd, key); 17067c478bd9Sstevel@tonic-gate } 17077c478bd9Sstevel@tonic-gate return; 17087c478bd9Sstevel@tonic-gate } 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate shiftmask = k->k_shiftmask; 17117c478bd9Sstevel@tonic-gate if (newstate == RELEASED) 17127c478bd9Sstevel@tonic-gate shiftmask |= UPMASK; 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate km = settable(kbdd, shiftmask); 17157c478bd9Sstevel@tonic-gate if (km == NULL) { /* gross error */ 17167c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 17177c478bd9Sstevel@tonic-gate return; 17187c478bd9Sstevel@tonic-gate } 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate if (key >= KEYMAP_SIZE) 17217c478bd9Sstevel@tonic-gate return; 17227c478bd9Sstevel@tonic-gate entry = km->keymap[key]; 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate if (entry == NONL) { 17257c478bd9Sstevel@tonic-gate /* 17267c478bd9Sstevel@tonic-gate * NONL appears only in the Num Lock table, and indicates that 17277c478bd9Sstevel@tonic-gate * this key is not affected by Num Lock. This means we should 17287c478bd9Sstevel@tonic-gate * ask for the table we would have gotten had Num Lock not been 17297c478bd9Sstevel@tonic-gate * down, and translate using that table. 17307c478bd9Sstevel@tonic-gate */ 17317c478bd9Sstevel@tonic-gate km = settable(kbdd, shiftmask & ~NUMLOCKMASK); 17327c478bd9Sstevel@tonic-gate if (km == NULL) { /* gross error */ 17337c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 17347c478bd9Sstevel@tonic-gate return; 17357c478bd9Sstevel@tonic-gate } 17367c478bd9Sstevel@tonic-gate entry = km->keymap[key]; 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate entrytype = (ushort_t)(entry & 0xFF00) >> 8; 17397c478bd9Sstevel@tonic-gate 17407c478bd9Sstevel@tonic-gate if (entrytype == (SHIFTKEYS >> 8)) { 17417c478bd9Sstevel@tonic-gate /* 17427c478bd9Sstevel@tonic-gate * Handle the state of toggle shifts specially. 17437c478bd9Sstevel@tonic-gate * Ups should be ignored, and downs should be mapped to ups if 17447c478bd9Sstevel@tonic-gate * that shift is currently on. 17457c478bd9Sstevel@tonic-gate */ 17467c478bd9Sstevel@tonic-gate if ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts) { 17477c478bd9Sstevel@tonic-gate if ((1 << (entry & 0x0F)) & k->k_togglemask) { 17487c478bd9Sstevel@tonic-gate newstate = RELEASED; /* toggling off */ 17497c478bd9Sstevel@tonic-gate } else { 17507c478bd9Sstevel@tonic-gate newstate = PRESSED; /* toggling on */ 17517c478bd9Sstevel@tonic-gate } 17527c478bd9Sstevel@tonic-gate } 17537c478bd9Sstevel@tonic-gate } else { 17547c478bd9Sstevel@tonic-gate /* 17557c478bd9Sstevel@tonic-gate * Handle Compose and floating accent key sequences 17567c478bd9Sstevel@tonic-gate */ 17577c478bd9Sstevel@tonic-gate if (k->k_state == COMPOSE1) { 17587c478bd9Sstevel@tonic-gate if (newstate == RELEASED) 17597c478bd9Sstevel@tonic-gate return; 17607c478bd9Sstevel@tonic-gate if (entry < ASCII_SET_SIZE) { 17617c478bd9Sstevel@tonic-gate if (kb_compose_map[entry] >= 0) { 17627c478bd9Sstevel@tonic-gate kbdd->compose_key = entry; 17637c478bd9Sstevel@tonic-gate k->k_state = COMPOSE2; 17647c478bd9Sstevel@tonic-gate return; 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate } 17677c478bd9Sstevel@tonic-gate k->k_state = NORMAL; 17687c478bd9Sstevel@tonic-gate kbdd->led_state &= ~LED_COMPOSE; 17697c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 17707c478bd9Sstevel@tonic-gate return; 17717c478bd9Sstevel@tonic-gate } else if (k->k_state == COMPOSE2) { 17727c478bd9Sstevel@tonic-gate if (newstate == RELEASED) 17737c478bd9Sstevel@tonic-gate return; 17747c478bd9Sstevel@tonic-gate k->k_state = NORMAL; /* next state is "normal" */ 17757c478bd9Sstevel@tonic-gate kbdd->led_state &= ~LED_COMPOSE; 17767c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 17777c478bd9Sstevel@tonic-gate if (entry < ASCII_SET_SIZE) { 17787c478bd9Sstevel@tonic-gate if (kb_compose_map[entry] >= 0) { 17797c478bd9Sstevel@tonic-gate if (kbdd->compose_key <= entry) { 17807c478bd9Sstevel@tonic-gate ret_val = kbd_do_compose( 17817c478bd9Sstevel@tonic-gate kbdd->compose_key, 17827c478bd9Sstevel@tonic-gate entry, 17837c478bd9Sstevel@tonic-gate &result_iso); 17847c478bd9Sstevel@tonic-gate } else { 17857c478bd9Sstevel@tonic-gate ret_val = kbd_do_compose( 17867c478bd9Sstevel@tonic-gate entry, 17877c478bd9Sstevel@tonic-gate kbdd->compose_key, 17887c478bd9Sstevel@tonic-gate &result_iso); 17897c478bd9Sstevel@tonic-gate } 17907c478bd9Sstevel@tonic-gate if (ret_val == 1) { 17917c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == 17927c478bd9Sstevel@tonic-gate TR_EVENT) { 17937c478bd9Sstevel@tonic-gate fe.id = 17947c478bd9Sstevel@tonic-gate (kbdd->kbdd_compat ? 17957c478bd9Sstevel@tonic-gate ISO_FIRST : EUC_FIRST) 17967c478bd9Sstevel@tonic-gate + result_iso; 17977c478bd9Sstevel@tonic-gate fe.value = 1; 17987c478bd9Sstevel@tonic-gate kbdqueueevent( 17997c478bd9Sstevel@tonic-gate kbdd, 18007c478bd9Sstevel@tonic-gate &fe); 18017c478bd9Sstevel@tonic-gate } else if ( 18027c478bd9Sstevel@tonic-gate kbdd->kbdd_translate == 18037c478bd9Sstevel@tonic-gate TR_ASCII) 18047c478bd9Sstevel@tonic-gate kbdputcode( 18057c478bd9Sstevel@tonic-gate result_iso, 18067c478bd9Sstevel@tonic-gate q); 18077c478bd9Sstevel@tonic-gate } 18087c478bd9Sstevel@tonic-gate } 18097c478bd9Sstevel@tonic-gate } 18107c478bd9Sstevel@tonic-gate return; 18117c478bd9Sstevel@tonic-gate } else if (k->k_state == FLTACCENT) { 18127c478bd9Sstevel@tonic-gate if (newstate == RELEASED) 18137c478bd9Sstevel@tonic-gate return; 18147c478bd9Sstevel@tonic-gate k->k_state = NORMAL; /* next state is "normal" */ 18157c478bd9Sstevel@tonic-gate for (i = 0; 18167c478bd9Sstevel@tonic-gate (kb_fltaccent_table[i].fa_entry 18177c478bd9Sstevel@tonic-gate != kbdd->fltaccent_entry) || 18187c478bd9Sstevel@tonic-gate (kb_fltaccent_table[i].ascii != entry); 18197c478bd9Sstevel@tonic-gate i++) { 18207c478bd9Sstevel@tonic-gate if (kb_fltaccent_table[i].fa_entry == 0) 18217c478bd9Sstevel@tonic-gate /* Invalid second key: ignore key */ 18227c478bd9Sstevel@tonic-gate return; 18237c478bd9Sstevel@tonic-gate } 18247c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT) { 18257c478bd9Sstevel@tonic-gate fe.id = (kbdd->kbdd_compat ? 18267c478bd9Sstevel@tonic-gate ISO_FIRST : EUC_FIRST) 18277c478bd9Sstevel@tonic-gate + kb_fltaccent_table[i].iso; 18287c478bd9Sstevel@tonic-gate fe.value = 1; 18297c478bd9Sstevel@tonic-gate kbdqueueevent(kbdd, &fe); 18307c478bd9Sstevel@tonic-gate } else if (kbdd->kbdd_translate == TR_ASCII) 18317c478bd9Sstevel@tonic-gate kbdputcode(kb_fltaccent_table[i].iso, q); 18327c478bd9Sstevel@tonic-gate return; 18337c478bd9Sstevel@tonic-gate } 18347c478bd9Sstevel@tonic-gate } 18357c478bd9Sstevel@tonic-gate 18367c478bd9Sstevel@tonic-gate /* 18377c478bd9Sstevel@tonic-gate * If the key is going down, and it's not one of the keys that doesn't 18387c478bd9Sstevel@tonic-gate * auto-repeat, set up the auto-repeat timeout. 18397c478bd9Sstevel@tonic-gate * 18407c478bd9Sstevel@tonic-gate * The keys that don't auto-repeat are the Compose key, 18417c478bd9Sstevel@tonic-gate * the shift keys, the "bucky bit" keys, the "floating accent" keys, 18427c478bd9Sstevel@tonic-gate * and the function keys when in TR_EVENT mode. 18437c478bd9Sstevel@tonic-gate */ 18447c478bd9Sstevel@tonic-gate if (newstate == PRESSED && entrytype != (SHIFTKEYS >> 8) && 18457c478bd9Sstevel@tonic-gate entrytype != (BUCKYBITS >> 8) && entrytype != (FUNNY >> 8) && 18467c478bd9Sstevel@tonic-gate entrytype != (FA_CLASS >> 8) && 18477c478bd9Sstevel@tonic-gate !((entrytype == (FUNCKEYS >> 8) || entrytype == (PADKEYS >> 8)) && 18487c478bd9Sstevel@tonic-gate kbdd->kbdd_translate == TR_EVENT)) { 18497c478bd9Sstevel@tonic-gate if (k->k_rptkey != keycode) { 18507c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 18517c478bd9Sstevel@tonic-gate kbdd->kbdd_rptid = qtimeout(q, kbdrpt, kbdd, 18527c478bd9Sstevel@tonic-gate kbd_repeatdelay); 18537c478bd9Sstevel@tonic-gate k->k_rptkey = keycode; 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate } else if (key == KEYOF(k->k_rptkey)) /* key going up */ 18567c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 18577c478bd9Sstevel@tonic-gate if ((newstate == RELEASED) && (kbdd->kbdd_translate == TR_EVENT)) 18587c478bd9Sstevel@tonic-gate kbdkeyreleased(kbdd, key); 18597c478bd9Sstevel@tonic-gate 18607c478bd9Sstevel@tonic-gate /* 18617c478bd9Sstevel@tonic-gate * We assume here that keys other than shift keys and bucky keys have 18627c478bd9Sstevel@tonic-gate * entries in the "up" table that cause nothing to be done, and thus we 18637c478bd9Sstevel@tonic-gate * don't have to check for newstate == RELEASED. 18647c478bd9Sstevel@tonic-gate */ 18657c478bd9Sstevel@tonic-gate switch (entrytype) { 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate case 0x0: /* regular key */ 18687c478bd9Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate case TR_EVENT: 18717c478bd9Sstevel@tonic-gate fe.id = entry | k->k_buckybits; 18727c478bd9Sstevel@tonic-gate fe.value = 1; 18737c478bd9Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, entry); 18747c478bd9Sstevel@tonic-gate break; 18757c478bd9Sstevel@tonic-gate 18767c478bd9Sstevel@tonic-gate case TR_ASCII: 18777c478bd9Sstevel@tonic-gate kbdputcode(entry | k->k_buckybits, q); 18787c478bd9Sstevel@tonic-gate break; 18797c478bd9Sstevel@tonic-gate } 18807c478bd9Sstevel@tonic-gate break; 18817c478bd9Sstevel@tonic-gate 18827c478bd9Sstevel@tonic-gate case SHIFTKEYS >> 8: { 18837c478bd9Sstevel@tonic-gate uint_t shiftbit = 1 << (entry & 0x0F); 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate /* Modify toggle state (see toggle processing above) */ 18867c478bd9Sstevel@tonic-gate if (shiftbit & k->k_curkeyboard->k_toggleshifts) { 18877c478bd9Sstevel@tonic-gate if (newstate == RELEASED) { 18887c478bd9Sstevel@tonic-gate if (shiftbit == CAPSMASK) { 18897c478bd9Sstevel@tonic-gate kbdd->led_state &= ~LED_CAPS_LOCK; 18907c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 18917c478bd9Sstevel@tonic-gate } else if (shiftbit == NUMLOCKMASK) { 18927c478bd9Sstevel@tonic-gate kbdd->led_state &= ~LED_NUM_LOCK; 18937c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 18947c478bd9Sstevel@tonic-gate } 18957c478bd9Sstevel@tonic-gate k->k_togglemask &= ~shiftbit; 18967c478bd9Sstevel@tonic-gate } else { 18977c478bd9Sstevel@tonic-gate if (shiftbit == CAPSMASK) { 18987c478bd9Sstevel@tonic-gate kbdd->led_state |= LED_CAPS_LOCK; 18997c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 19007c478bd9Sstevel@tonic-gate } else if (shiftbit == NUMLOCKMASK) { 19017c478bd9Sstevel@tonic-gate kbdd->led_state |= LED_NUM_LOCK; 19027c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 19037c478bd9Sstevel@tonic-gate } 19047c478bd9Sstevel@tonic-gate k->k_togglemask |= shiftbit; 19057c478bd9Sstevel@tonic-gate } 19067c478bd9Sstevel@tonic-gate } 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate if (newstate == RELEASED) 19097c478bd9Sstevel@tonic-gate k->k_shiftmask &= ~shiftbit; 19107c478bd9Sstevel@tonic-gate else 19117c478bd9Sstevel@tonic-gate k->k_shiftmask |= shiftbit; 19127c478bd9Sstevel@tonic-gate 19137c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) { 19147c478bd9Sstevel@tonic-gate /* 19157c478bd9Sstevel@tonic-gate * Relying on ordinal correspondence between 19167c478bd9Sstevel@tonic-gate * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL & 19177c478bd9Sstevel@tonic-gate * kbd.h CAPSLOCK-RIGHTCTRL in order to 19187c478bd9Sstevel@tonic-gate * correctly translate entry into fe.id. 19197c478bd9Sstevel@tonic-gate */ 19207c478bd9Sstevel@tonic-gate fe.id = SHIFT_CAPSLOCK + (entry & 0x0F); 19217c478bd9Sstevel@tonic-gate fe.value = 1; 19227c478bd9Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 19237c478bd9Sstevel@tonic-gate } 19247c478bd9Sstevel@tonic-gate break; 19257c478bd9Sstevel@tonic-gate } 19267c478bd9Sstevel@tonic-gate 19277c478bd9Sstevel@tonic-gate case BUCKYBITS >> 8: 19287c478bd9Sstevel@tonic-gate k->k_buckybits ^= 1 << (7 + (entry & 0x0F)); 19297c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) { 19307c478bd9Sstevel@tonic-gate /* 19317c478bd9Sstevel@tonic-gate * Relying on ordinal correspondence between 19327c478bd9Sstevel@tonic-gate * vuid_event.h SHIFT_META-SHIFT_TOP & 19337c478bd9Sstevel@tonic-gate * kbd.h METABIT-SYSTEMBIT in order to 19347c478bd9Sstevel@tonic-gate * correctly translate entry into fe.id. 19357c478bd9Sstevel@tonic-gate */ 19367c478bd9Sstevel@tonic-gate fe.id = SHIFT_META + (entry & 0x0F); 19377c478bd9Sstevel@tonic-gate fe.value = 1; 19387c478bd9Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 19397c478bd9Sstevel@tonic-gate } 19407c478bd9Sstevel@tonic-gate break; 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate case FUNNY >> 8: 19437c478bd9Sstevel@tonic-gate switch (entry) { 19447c478bd9Sstevel@tonic-gate case NOP: 19457c478bd9Sstevel@tonic-gate break; 19467c478bd9Sstevel@tonic-gate 19477c478bd9Sstevel@tonic-gate case IDLE: 19487c478bd9Sstevel@tonic-gate /* Fall thru into RESET code */ 19497c478bd9Sstevel@tonic-gate /* FALLTHRU */ 19507c478bd9Sstevel@tonic-gate case RESET: 19517c478bd9Sstevel@tonic-gate gotreset: 19527c478bd9Sstevel@tonic-gate k->k_shiftmask &= k->k_curkeyboard->k_idleshifts; 19537c478bd9Sstevel@tonic-gate k->k_shiftmask |= k->k_togglemask; 19547c478bd9Sstevel@tonic-gate k->k_buckybits &= k->k_curkeyboard->k_idlebuckys; 19557c478bd9Sstevel@tonic-gate kbdcancelrpt(kbdd); 19567c478bd9Sstevel@tonic-gate kbdreleaseall(kbdd); 19577c478bd9Sstevel@tonic-gate break; 19587c478bd9Sstevel@tonic-gate 19597c478bd9Sstevel@tonic-gate case ERROR: 19607c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Error detected"); 19617c478bd9Sstevel@tonic-gate goto gotreset; 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate case COMPOSE: 19647c478bd9Sstevel@tonic-gate k->k_state = COMPOSE1; 19657c478bd9Sstevel@tonic-gate kbdd->led_state |= LED_COMPOSE; 19667c478bd9Sstevel@tonic-gate kbdsetled(kbdd); 19677c478bd9Sstevel@tonic-gate break; 19687c478bd9Sstevel@tonic-gate /* 19697c478bd9Sstevel@tonic-gate * Remember when adding new entries that, 19707c478bd9Sstevel@tonic-gate * if they should NOT auto-repeat, 19717c478bd9Sstevel@tonic-gate * they should be put into the IF statement 19727c478bd9Sstevel@tonic-gate * just above this switch block. 19737c478bd9Sstevel@tonic-gate */ 19747c478bd9Sstevel@tonic-gate default: 19757c478bd9Sstevel@tonic-gate goto badentry; 19767c478bd9Sstevel@tonic-gate } 19777c478bd9Sstevel@tonic-gate break; 19787c478bd9Sstevel@tonic-gate 19797c478bd9Sstevel@tonic-gate case FA_CLASS >> 8: 19807c478bd9Sstevel@tonic-gate if (k->k_state == NORMAL) { 19817c478bd9Sstevel@tonic-gate kbdd->fltaccent_entry = entry; 19827c478bd9Sstevel@tonic-gate k->k_state = FLTACCENT; 19837c478bd9Sstevel@tonic-gate } 19847c478bd9Sstevel@tonic-gate return; 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate case STRING >> 8: 19877c478bd9Sstevel@tonic-gate cp = &keystringtab[entry & 0x0F][0]; 19887c478bd9Sstevel@tonic-gate while (*cp != '\0') { 19897c478bd9Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 19907c478bd9Sstevel@tonic-gate 19917c478bd9Sstevel@tonic-gate case TR_EVENT: 19927c478bd9Sstevel@tonic-gate kbd_send_esc_event(*cp, kbdd); 19937c478bd9Sstevel@tonic-gate break; 19947c478bd9Sstevel@tonic-gate 19957c478bd9Sstevel@tonic-gate case TR_ASCII: 19967c478bd9Sstevel@tonic-gate kbdputcode((uchar_t)*cp, q); 19977c478bd9Sstevel@tonic-gate break; 19987c478bd9Sstevel@tonic-gate } 19997c478bd9Sstevel@tonic-gate cp++; 20007c478bd9Sstevel@tonic-gate } 20017c478bd9Sstevel@tonic-gate break; 20027c478bd9Sstevel@tonic-gate 20037c478bd9Sstevel@tonic-gate case FUNCKEYS >> 8: 20047c478bd9Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate case TR_ASCII: 20077c478bd9Sstevel@tonic-gate bufp = buf; 20087c478bd9Sstevel@tonic-gate cp = strsetwithdecimal(bufp + 2, 20097c478bd9Sstevel@tonic-gate (uint_t)((entry & 0x003F) + 192), 20107c478bd9Sstevel@tonic-gate sizeof (buf) - 5); 20117c478bd9Sstevel@tonic-gate *bufp++ = '\033'; /* Escape */ 20127c478bd9Sstevel@tonic-gate *bufp++ = '['; 20137c478bd9Sstevel@tonic-gate while (*cp != '\0') 20147c478bd9Sstevel@tonic-gate *bufp++ = *cp++; 20157c478bd9Sstevel@tonic-gate *bufp++ = 'z'; 20167c478bd9Sstevel@tonic-gate *bufp = '\0'; 20177c478bd9Sstevel@tonic-gate kbdputbuf(buf, q); 20187c478bd9Sstevel@tonic-gate break; 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate case TR_EVENT: 20217c478bd9Sstevel@tonic-gate /* 20227c478bd9Sstevel@tonic-gate * Take advantage of the similar 20237c478bd9Sstevel@tonic-gate * ordering of kbd.h function keys and 20247c478bd9Sstevel@tonic-gate * vuid_event.h function keys to do a 20257c478bd9Sstevel@tonic-gate * simple translation to achieve a 20267c478bd9Sstevel@tonic-gate * mapping between the 2 different 20277c478bd9Sstevel@tonic-gate * address spaces. 20287c478bd9Sstevel@tonic-gate */ 20297c478bd9Sstevel@tonic-gate fe.id = (entry & 0x003F) + KEY_LEFTFIRST; 20307c478bd9Sstevel@tonic-gate fe.value = 1; 20317c478bd9Sstevel@tonic-gate /* 20327c478bd9Sstevel@tonic-gate * Assume "up" table only generates 20337c478bd9Sstevel@tonic-gate * shift changes. 20347c478bd9Sstevel@tonic-gate */ 20357c478bd9Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 20367c478bd9Sstevel@tonic-gate /* 20377c478bd9Sstevel@tonic-gate * Function key events can be expanded 20387c478bd9Sstevel@tonic-gate * by terminal emulator software to 20397c478bd9Sstevel@tonic-gate * produce the standard escape sequence 20407c478bd9Sstevel@tonic-gate * generated by the TR_ASCII case above 20417c478bd9Sstevel@tonic-gate * if a function key event is not used 20427c478bd9Sstevel@tonic-gate * by terminal emulator software 20437c478bd9Sstevel@tonic-gate * directly. 20447c478bd9Sstevel@tonic-gate */ 20457c478bd9Sstevel@tonic-gate break; 20467c478bd9Sstevel@tonic-gate } 20477c478bd9Sstevel@tonic-gate break; 20487c478bd9Sstevel@tonic-gate 20497c478bd9Sstevel@tonic-gate /* 20507c478bd9Sstevel@tonic-gate * Remember when adding new entries that, 20517c478bd9Sstevel@tonic-gate * if they should NOT auto-repeat, 20527c478bd9Sstevel@tonic-gate * they should be put into the IF statement 20537c478bd9Sstevel@tonic-gate * just above this switch block. 20547c478bd9Sstevel@tonic-gate */ 20557c478bd9Sstevel@tonic-gate case PADKEYS >> 8: 20567c478bd9Sstevel@tonic-gate switch (kbdd->kbdd_translate) { 20577c478bd9Sstevel@tonic-gate 20587c478bd9Sstevel@tonic-gate case TR_ASCII: 20597c478bd9Sstevel@tonic-gate kbdputcode(kb_numlock_table[entry&0x1F], q); 20607c478bd9Sstevel@tonic-gate break; 20617c478bd9Sstevel@tonic-gate 20627c478bd9Sstevel@tonic-gate case TR_EVENT: 20637c478bd9Sstevel@tonic-gate /* 20647c478bd9Sstevel@tonic-gate * Take advantage of the similar 20657c478bd9Sstevel@tonic-gate * ordering of kbd.h keypad keys and 20667c478bd9Sstevel@tonic-gate * vuid_event.h keypad keys to do a 20677c478bd9Sstevel@tonic-gate * simple translation to achieve a 20687c478bd9Sstevel@tonic-gate * mapping between the 2 different 20697c478bd9Sstevel@tonic-gate * address spaces. 20707c478bd9Sstevel@tonic-gate */ 20717c478bd9Sstevel@tonic-gate fe.id = (entry & 0x001F) + VKEY_FIRSTPAD; 20727c478bd9Sstevel@tonic-gate fe.value = 1; 20737c478bd9Sstevel@tonic-gate /* 20747c478bd9Sstevel@tonic-gate * Assume "up" table only generates 20757c478bd9Sstevel@tonic-gate * shift changes. 20767c478bd9Sstevel@tonic-gate */ 20777c478bd9Sstevel@tonic-gate kbdkeypressed(kbdd, key, &fe, fe.id); 20787c478bd9Sstevel@tonic-gate /* 20797c478bd9Sstevel@tonic-gate * Keypad key events can be expanded 20807c478bd9Sstevel@tonic-gate * by terminal emulator software to 20817c478bd9Sstevel@tonic-gate * produce the standard ascii character 20827c478bd9Sstevel@tonic-gate * generated by the TR_ASCII case above 20837c478bd9Sstevel@tonic-gate * if a keypad key event is not used 20847c478bd9Sstevel@tonic-gate * by terminal emulator software 20857c478bd9Sstevel@tonic-gate * directly. 20867c478bd9Sstevel@tonic-gate */ 20877c478bd9Sstevel@tonic-gate break; 20887c478bd9Sstevel@tonic-gate } 20897c478bd9Sstevel@tonic-gate 20907c478bd9Sstevel@tonic-gate badentry: 20917c478bd9Sstevel@tonic-gate break; 20927c478bd9Sstevel@tonic-gate } 20937c478bd9Sstevel@tonic-gate } 20947c478bd9Sstevel@tonic-gate 20957c478bd9Sstevel@tonic-gate static int 20967c478bd9Sstevel@tonic-gate kbd_do_compose(ushort_t first_entry, ushort_t second_entry, 20977c478bd9Sstevel@tonic-gate ushort_t *result_iso_ptr) 20987c478bd9Sstevel@tonic-gate { 20997c478bd9Sstevel@tonic-gate struct compose_sequence_t *ptr; 21007c478bd9Sstevel@tonic-gate 21017c478bd9Sstevel@tonic-gate ptr = &kb_compose_table[kb_compose_map[first_entry]]; 21027c478bd9Sstevel@tonic-gate while (ptr->first == first_entry) { 21037c478bd9Sstevel@tonic-gate if (ptr->second == second_entry) { 21047c478bd9Sstevel@tonic-gate *result_iso_ptr = ptr->iso; 21057c478bd9Sstevel@tonic-gate return (1); 21067c478bd9Sstevel@tonic-gate } 21077c478bd9Sstevel@tonic-gate ptr++; 21087c478bd9Sstevel@tonic-gate } 21097c478bd9Sstevel@tonic-gate return (0); 21107c478bd9Sstevel@tonic-gate } 21117c478bd9Sstevel@tonic-gate 21127c478bd9Sstevel@tonic-gate static void 21137c478bd9Sstevel@tonic-gate kbd_send_esc_event(char c, register struct kbddata *kbdd) 21147c478bd9Sstevel@tonic-gate { 21157c478bd9Sstevel@tonic-gate Firm_event fe; 21167c478bd9Sstevel@tonic-gate 21177c478bd9Sstevel@tonic-gate fe.id = c; 21187c478bd9Sstevel@tonic-gate fe.value = 1; 21197c478bd9Sstevel@tonic-gate fe.pair_type = FE_PAIR_NONE; 21207c478bd9Sstevel@tonic-gate fe.pair = 0; 21217c478bd9Sstevel@tonic-gate /* 21227c478bd9Sstevel@tonic-gate * Pretend as if each cp pushed and released 21237c478bd9Sstevel@tonic-gate * Calling kbdqueueevent avoids addr translation 21247c478bd9Sstevel@tonic-gate * and pair base determination of kbdkeypressed. 21257c478bd9Sstevel@tonic-gate */ 21267c478bd9Sstevel@tonic-gate kbdqueueevent(kbdd, &fe); 21277c478bd9Sstevel@tonic-gate fe.value = 0; 21287c478bd9Sstevel@tonic-gate kbdqueueevent(kbdd, &fe); 21297c478bd9Sstevel@tonic-gate } 21307c478bd9Sstevel@tonic-gate 21317c478bd9Sstevel@tonic-gate char * 21327c478bd9Sstevel@tonic-gate strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs) 21337c478bd9Sstevel@tonic-gate { 21347c478bd9Sstevel@tonic-gate int hradix = 5; 21357c478bd9Sstevel@tonic-gate char *bp; 21367c478bd9Sstevel@tonic-gate int lowbit; 21377c478bd9Sstevel@tonic-gate char *tab = "0123456789abcdef"; 21387c478bd9Sstevel@tonic-gate 21397c478bd9Sstevel@tonic-gate bp = buf + maxdigs; 21407c478bd9Sstevel@tonic-gate *(--bp) = '\0'; 21417c478bd9Sstevel@tonic-gate while (val) { 21427c478bd9Sstevel@tonic-gate lowbit = val & 1; 21437c478bd9Sstevel@tonic-gate val = (val >> 1); 21447c478bd9Sstevel@tonic-gate *(--bp) = tab[val % hradix * 2 + lowbit]; 21457c478bd9Sstevel@tonic-gate val /= hradix; 21467c478bd9Sstevel@tonic-gate } 21477c478bd9Sstevel@tonic-gate return (bp); 21487c478bd9Sstevel@tonic-gate } 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate static void 21517c478bd9Sstevel@tonic-gate kbdkeypressed(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe, 21527c478bd9Sstevel@tonic-gate ushort_t base) 21537c478bd9Sstevel@tonic-gate { 21547c478bd9Sstevel@tonic-gate register struct keyboardstate *k; 21557c478bd9Sstevel@tonic-gate register short id_addr; 21567c478bd9Sstevel@tonic-gate 21577c478bd9Sstevel@tonic-gate /* Set pair values */ 21587c478bd9Sstevel@tonic-gate if (fe->id < (ushort_t)VKEY_FIRST) { 21597c478bd9Sstevel@tonic-gate /* 21607c478bd9Sstevel@tonic-gate * If CTRLed, find the ID that would have been used had it 21617c478bd9Sstevel@tonic-gate * not been CTRLed. 21627c478bd9Sstevel@tonic-gate */ 21637c478bd9Sstevel@tonic-gate k = &kbdd->kbdd_state; 21647c478bd9Sstevel@tonic-gate if (k->k_shiftmask & (CTRLMASK | CTLSMASK)) { 21657c478bd9Sstevel@tonic-gate struct keymap *km; 21667c478bd9Sstevel@tonic-gate 21677c478bd9Sstevel@tonic-gate km = settable(kbdd, 21687c478bd9Sstevel@tonic-gate k->k_shiftmask & ~(CTRLMASK | CTLSMASK | UPMASK)); 21697c478bd9Sstevel@tonic-gate if (km == NULL) 21707c478bd9Sstevel@tonic-gate return; 21717c478bd9Sstevel@tonic-gate base = km->keymap[key_station]; 21727c478bd9Sstevel@tonic-gate } 21737c478bd9Sstevel@tonic-gate if (base != fe->id) { 21747c478bd9Sstevel@tonic-gate fe->pair_type = FE_PAIR_SET; 21757c478bd9Sstevel@tonic-gate fe->pair = base; 21767c478bd9Sstevel@tonic-gate goto send; 21777c478bd9Sstevel@tonic-gate } 21787c478bd9Sstevel@tonic-gate } 21797c478bd9Sstevel@tonic-gate fe->pair_type = FE_PAIR_NONE; 21807c478bd9Sstevel@tonic-gate fe->pair = 0; 21817c478bd9Sstevel@tonic-gate send: 21827c478bd9Sstevel@tonic-gate /* Adjust event id address for multiple keyboard/workstation support */ 21837c478bd9Sstevel@tonic-gate switch (vuid_id_addr(fe->id)) { 21847c478bd9Sstevel@tonic-gate case ASCII_FIRST: 21857c478bd9Sstevel@tonic-gate id_addr = kbdd->kbdd_ascii_addr; 21867c478bd9Sstevel@tonic-gate break; 21877c478bd9Sstevel@tonic-gate case TOP_FIRST: 21887c478bd9Sstevel@tonic-gate id_addr = kbdd->kbdd_top_addr; 21897c478bd9Sstevel@tonic-gate break; 21907c478bd9Sstevel@tonic-gate case VKEY_FIRST: 21917c478bd9Sstevel@tonic-gate id_addr = kbdd->kbdd_vkey_addr; 21927c478bd9Sstevel@tonic-gate break; 21937c478bd9Sstevel@tonic-gate default: 21947c478bd9Sstevel@tonic-gate id_addr = vuid_id_addr(fe->id); 21957c478bd9Sstevel@tonic-gate } 21967c478bd9Sstevel@tonic-gate fe->id = vuid_id_offset(fe->id) | id_addr; 21977c478bd9Sstevel@tonic-gate kbdqueuepress(kbdd, key_station, fe); 21987c478bd9Sstevel@tonic-gate } 21997c478bd9Sstevel@tonic-gate 22007c478bd9Sstevel@tonic-gate static void 22017c478bd9Sstevel@tonic-gate kbdqueuepress(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe) 22027c478bd9Sstevel@tonic-gate { 22037c478bd9Sstevel@tonic-gate register struct key_event *ke, *ke_free; 22047c478bd9Sstevel@tonic-gate register int i; 22057c478bd9Sstevel@tonic-gate 22067c478bd9Sstevel@tonic-gate if (key_station == IDLEKEY) 22077c478bd9Sstevel@tonic-gate return; 22087c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 22097c478bd9Sstevel@tonic-gate if (kbd_input_debug) printf("KBD PRESSED key=%d\n", key_station); 22107c478bd9Sstevel@tonic-gate #endif 22117c478bd9Sstevel@tonic-gate ke_free = 0; 22127c478bd9Sstevel@tonic-gate /* Scan table of down key stations */ 22137c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate == TR_EVENT || 22147c478bd9Sstevel@tonic-gate kbdd->kbdd_translate == TR_UNTRANS_EVENT) { 22157c478bd9Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs; 22167c478bd9Sstevel@tonic-gate i < kbdd->kbdd_downs_entries; 22177c478bd9Sstevel@tonic-gate i++, ke++) { 22187c478bd9Sstevel@tonic-gate /* Keycode already down? */ 22197c478bd9Sstevel@tonic-gate if (ke->key_station == key_station) { 22207c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 22217c478bd9Sstevel@tonic-gate printf("kbd: Double entry in downs table (%d,%d)!\n", key_station, i); 22227c478bd9Sstevel@tonic-gate #endif 22237c478bd9Sstevel@tonic-gate goto add_event; 22247c478bd9Sstevel@tonic-gate } 22257c478bd9Sstevel@tonic-gate if (ke->key_station == 0) 22267c478bd9Sstevel@tonic-gate ke_free = ke; 22277c478bd9Sstevel@tonic-gate } 22287c478bd9Sstevel@tonic-gate if (ke_free) { 22297c478bd9Sstevel@tonic-gate ke = ke_free; 22307c478bd9Sstevel@tonic-gate goto add_event; 22317c478bd9Sstevel@tonic-gate } 22327c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "kbd: Too many keys down!"); 22337c478bd9Sstevel@tonic-gate ke = kbdd->kbdd_downs; 22347c478bd9Sstevel@tonic-gate } 22357c478bd9Sstevel@tonic-gate add_event: 22367c478bd9Sstevel@tonic-gate ke->key_station = key_station; 22377c478bd9Sstevel@tonic-gate ke->event = *fe; 22387c478bd9Sstevel@tonic-gate kbdqueueevent(kbdd, fe); 22397c478bd9Sstevel@tonic-gate } 22407c478bd9Sstevel@tonic-gate 22417c478bd9Sstevel@tonic-gate static void 22427c478bd9Sstevel@tonic-gate kbdkeyreleased(register struct kbddata *kbdd, uchar_t key_station) 22437c478bd9Sstevel@tonic-gate { 22447c478bd9Sstevel@tonic-gate register struct key_event *ke; 22457c478bd9Sstevel@tonic-gate register int i; 22467c478bd9Sstevel@tonic-gate 22477c478bd9Sstevel@tonic-gate if (key_station == IDLEKEY) 22487c478bd9Sstevel@tonic-gate return; 22497c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 22507c478bd9Sstevel@tonic-gate if (kbd_input_debug) 22517c478bd9Sstevel@tonic-gate printf("KBD RELEASE key=%d\n", key_station); 22527c478bd9Sstevel@tonic-gate #endif 22537c478bd9Sstevel@tonic-gate if (kbdd->kbdd_translate != TR_EVENT && 22547c478bd9Sstevel@tonic-gate kbdd->kbdd_translate != TR_UNTRANS_EVENT) 22557c478bd9Sstevel@tonic-gate return; 22567c478bd9Sstevel@tonic-gate /* Scan table of down key stations */ 22577c478bd9Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs; 22587c478bd9Sstevel@tonic-gate i < kbdd->kbdd_downs_entries; 22597c478bd9Sstevel@tonic-gate i++, ke++) { 22607c478bd9Sstevel@tonic-gate /* Found? */ 22617c478bd9Sstevel@tonic-gate if (ke->key_station == key_station) { 22627c478bd9Sstevel@tonic-gate ke->key_station = 0; 22637c478bd9Sstevel@tonic-gate ke->event.value = 0; 22647c478bd9Sstevel@tonic-gate kbdqueueevent(kbdd, &ke->event); 22657c478bd9Sstevel@tonic-gate } 22667c478bd9Sstevel@tonic-gate } 22677c478bd9Sstevel@tonic-gate 22687c478bd9Sstevel@tonic-gate /* 22697c478bd9Sstevel@tonic-gate * Ignore if couldn't find because may be called twice 22707c478bd9Sstevel@tonic-gate * for the same key station in the case of the kbdrpt 22717c478bd9Sstevel@tonic-gate * routine being called unnecessarily. 22727c478bd9Sstevel@tonic-gate */ 22737c478bd9Sstevel@tonic-gate } 22747c478bd9Sstevel@tonic-gate 22757c478bd9Sstevel@tonic-gate static void 22767c478bd9Sstevel@tonic-gate kbdreleaseall(struct kbddata *kbdd) 22777c478bd9Sstevel@tonic-gate { 22787c478bd9Sstevel@tonic-gate register struct key_event *ke; 22797c478bd9Sstevel@tonic-gate register int i; 22807c478bd9Sstevel@tonic-gate 22817c478bd9Sstevel@tonic-gate #ifdef KBD_DEBUG 22827c478bd9Sstevel@tonic-gate if (kbd_debug && kbd_ra_debug) printf("KBD RELEASE ALL\n"); 22837c478bd9Sstevel@tonic-gate #endif 22847c478bd9Sstevel@tonic-gate /* Scan table of down key stations */ 22857c478bd9Sstevel@tonic-gate for (i = 0, ke = kbdd->kbdd_downs; 22867c478bd9Sstevel@tonic-gate i < kbdd->kbdd_downs_entries; i++, ke++) { 22877c478bd9Sstevel@tonic-gate /* Key station not zero */ 22887c478bd9Sstevel@tonic-gate if (ke->key_station) 22897c478bd9Sstevel@tonic-gate kbdkeyreleased(kbdd, ke->key_station); 22907c478bd9Sstevel@tonic-gate /* kbdkeyreleased resets kbdd_downs entry */ 22917c478bd9Sstevel@tonic-gate } 22927c478bd9Sstevel@tonic-gate } 22937c478bd9Sstevel@tonic-gate 22947c478bd9Sstevel@tonic-gate /* 22957c478bd9Sstevel@tonic-gate * Pass a keycode up the stream, if you can, otherwise throw it away. 22967c478bd9Sstevel@tonic-gate */ 22977c478bd9Sstevel@tonic-gate static void 22987c478bd9Sstevel@tonic-gate kbdputcode(uint_t code, queue_t *q) 22997c478bd9Sstevel@tonic-gate { 23007c478bd9Sstevel@tonic-gate register mblk_t *bp; 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate if (!canput(q)) 23037c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "kbdputcode: Can't put block for keycode"); 23047c478bd9Sstevel@tonic-gate else { 23057c478bd9Sstevel@tonic-gate if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) 23067c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 23077c478bd9Sstevel@tonic-gate "kbdputcode: Can't allocate block for keycode"); 23087c478bd9Sstevel@tonic-gate else { 23097c478bd9Sstevel@tonic-gate *bp->b_wptr++ = code; 23107c478bd9Sstevel@tonic-gate putnext(q, bp); 23117c478bd9Sstevel@tonic-gate } 23127c478bd9Sstevel@tonic-gate } 23137c478bd9Sstevel@tonic-gate } 23147c478bd9Sstevel@tonic-gate 23157c478bd9Sstevel@tonic-gate /* 23167c478bd9Sstevel@tonic-gate * Pass generated keycode sequence to upstream, if possible. 23177c478bd9Sstevel@tonic-gate */ 23187c478bd9Sstevel@tonic-gate static void 23197c478bd9Sstevel@tonic-gate kbdputbuf(char *buf, queue_t *q) 23207c478bd9Sstevel@tonic-gate { 23217c478bd9Sstevel@tonic-gate register mblk_t *bp; 23227c478bd9Sstevel@tonic-gate 23237c478bd9Sstevel@tonic-gate if (!canput(q)) 23247c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "kbdputbuf: Can't put block for keycode"); 23257c478bd9Sstevel@tonic-gate else { 23267c478bd9Sstevel@tonic-gate if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) 23277c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 23287c478bd9Sstevel@tonic-gate "kbdputbuf: Can't allocate block for keycode"); 23297c478bd9Sstevel@tonic-gate else { 23307c478bd9Sstevel@tonic-gate while (*buf) { 23317c478bd9Sstevel@tonic-gate *bp->b_wptr++ = *buf; 23327c478bd9Sstevel@tonic-gate buf++; 23337c478bd9Sstevel@tonic-gate } 23347c478bd9Sstevel@tonic-gate putnext(q, bp); 23357c478bd9Sstevel@tonic-gate } 23367c478bd9Sstevel@tonic-gate } 23377c478bd9Sstevel@tonic-gate } 23387c478bd9Sstevel@tonic-gate 23397c478bd9Sstevel@tonic-gate /* 23407c478bd9Sstevel@tonic-gate * Pass a VUID "firm event" up the stream, if you can. 23417c478bd9Sstevel@tonic-gate */ 23427c478bd9Sstevel@tonic-gate static void 23437c478bd9Sstevel@tonic-gate kbdqueueevent(struct kbddata *kbdd, Firm_event *fe) 23447c478bd9Sstevel@tonic-gate { 23457c478bd9Sstevel@tonic-gate register queue_t *q; 23467c478bd9Sstevel@tonic-gate register mblk_t *bp; 23477c478bd9Sstevel@tonic-gate 23487c478bd9Sstevel@tonic-gate if ((q = kbdd->kbdd_readq) == NULL) 23497c478bd9Sstevel@tonic-gate return; 23507c478bd9Sstevel@tonic-gate if (!canput(q)) { 23517c478bd9Sstevel@tonic-gate if (kbd_overflow_msg) 23527c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 23537c478bd9Sstevel@tonic-gate "kbd: Buffer flushed when overflowed"); 23547c478bd9Sstevel@tonic-gate kbdflush(kbdd); 23557c478bd9Sstevel@tonic-gate kbd_overflow_cnt++; 23567c478bd9Sstevel@tonic-gate } else { 23577c478bd9Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) 23587c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 23597c478bd9Sstevel@tonic-gate "kbdqueueevent: Can't allocate block for event"); 23607c478bd9Sstevel@tonic-gate else { 23617c478bd9Sstevel@tonic-gate #if 1 /* XX64 */ 23627c478bd9Sstevel@tonic-gate struct timeval now; 23637c478bd9Sstevel@tonic-gate 23647c478bd9Sstevel@tonic-gate /* 23657c478bd9Sstevel@tonic-gate * XX64: This is something of a compromise. It 23667c478bd9Sstevel@tonic-gate * seems justifiable based on the usage of these 23677c478bd9Sstevel@tonic-gate * timestamps as an ordering relation as opposed 23687c478bd9Sstevel@tonic-gate * to a strict timing thing. 23697c478bd9Sstevel@tonic-gate * 23707c478bd9Sstevel@tonic-gate * But should we restore Firm_event's time stamp 23717c478bd9Sstevel@tonic-gate * to be a timeval, and send 32-bit and 64-bit 23727c478bd9Sstevel@tonic-gate * events up the pipe? 23737c478bd9Sstevel@tonic-gate */ 23747c478bd9Sstevel@tonic-gate uniqtime(&now); 23757c478bd9Sstevel@tonic-gate TIMEVAL_TO_TIMEVAL32(&fe->time, &now); 23767c478bd9Sstevel@tonic-gate #else 23777c478bd9Sstevel@tonic-gate uniqtime(&fe->time); 23787c478bd9Sstevel@tonic-gate #endif 23797c478bd9Sstevel@tonic-gate *(Firm_event *)bp->b_wptr = *fe; 23807c478bd9Sstevel@tonic-gate bp->b_wptr += sizeof (Firm_event); 23817c478bd9Sstevel@tonic-gate putnext(q, bp); 23827c478bd9Sstevel@tonic-gate } 23837c478bd9Sstevel@tonic-gate } 23847c478bd9Sstevel@tonic-gate } 2385