summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/kbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/kbd.c')
-rw-r--r--usr/src/uts/common/io/kbd.c2444
1 files changed, 0 insertions, 2444 deletions
diff --git a/usr/src/uts/common/io/kbd.c b/usr/src/uts/common/io/kbd.c
deleted file mode 100644
index 1b58db4c7b..0000000000
--- a/usr/src/uts/common/io/kbd.c
+++ /dev/null
@@ -1,2444 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
- /* SunOS-4.0 1.60 */
-/* From: SunOS4.0 sundev/kbd.c */
-
-/*
- * Keyboard input streams module - handles conversion of up/down codes to
- * ASCII or event format.
- */
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/sysmacros.h>
-#include <sys/signal.h>
-#include <sys/termios.h>
-#include <sys/termio.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/strsun.h>
-#include <sys/kmem.h>
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/consdev.h>
-#include <sys/kbd.h>
-#include <sys/kbio.h>
-#include <sys/kbdreg.h>
-#include <sys/vuid_event.h>
-#include <sys/debug.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/policy.h>
-
-#include <sys/modctl.h>
-#include <sys/beep.h>
-#include <sys/int_limits.h>
-
-static struct streamtab kbd_info;
-
-static struct fmodsw fsw = {
- "kb",
- &kbd_info,
- D_MP | D_MTPERMOD
-};
-
-/*
- * Module linkage information for the kernel.
- */
-
-static struct modlstrmod modlstrmod = {
- &mod_strmodops, "streams module for keyboard", &fsw
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1, (void *)&modlstrmod, NULL
-};
-
-int
-_init(void)
-{
- return (mod_install(&modlinkage));
-}
-
-int
-_fini(void)
-{
- return (mod_remove(&modlinkage));
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-/*
- * For now these are shared.
- * These data structures are static (defined in keytables.c) thus
- * there is no need to perform any locking.
- */
-extern struct keyboards keytables[];
-extern char keystringtab[16][KTAB_STRLEN];
-extern struct compose_sequence_t kb_compose_table[];
-extern signed char kb_compose_map[];
-extern struct fltaccent_sequence_t kb_fltaccent_table[];
-extern uchar_t kb_numlock_table[];
-
-/*
- * This value corresponds approximately to max 10 fingers
- */
-static int kbd_downs_size = 15;
-
-typedef struct key_event {
- uchar_t key_station; /* Physical key station associated with event */
- Firm_event event; /* Event that sent out on down */
-} Key_event;
-struct kbddata {
- queue_t *kbdd_readq;
- queue_t *kbdd_writeq;
- mblk_t *kbdd_iocpending; /* "ioctl" awaiting buffer */
- mblk_t *kbdd_replypending; /* "ioctl" reply awaiting result */
- int kbdd_flags; /* random flags */
- bufcall_id_t kbdd_bufcallid; /* bufcall id */
- timeout_id_t kbdd_rptid; /* timeout id for kbdrpt() */
- timeout_id_t kbdd_layoutid; /* timeout id for kbdlayout() */
- int kbdd_iocid; /* ID of "ioctl" being waited for */
- int kbdd_iocerror; /* error return from "ioctl" */
- struct keyboardstate kbdd_state;
- /*
- * State of keyboard & keyboard
- * specific settings, e.g., tables
- */
- int kbdd_translate; /* Translate keycodes? */
- int kbdd_translatable; /* Keyboard is translatable? */
- int kbdd_compat; /* Generating pre-4.1 events? */
- short kbdd_ascii_addr; /* Vuid_id_addr for ascii events */
- short kbdd_top_addr; /* Vuid_id_addr for top events */
- short kbdd_vkey_addr; /* Vuid_id_addr for vkey events */
- struct key_event *kbdd_downs;
- /*
- * Table of key stations currently down
- * that have firm events that need
- * to be matched with up transitions
- * when kbdd_translate is TR_*EVENT
- */
- int kbdd_downs_entries; /* # of possible entries in kbdd_downs */
- uint_t kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */
- ushort_t compose_key; /* first compose key */
- ushort_t fltaccent_entry; /* floating accent keymap entry */
- char led_state; /* current state of LEDs */
- unsigned char shiftkey; /* used for the new abort keys */
-};
-
-#define KBD_OPEN 0x00000001 /* keyboard is open for business */
-#define KBD_IOCWAIT 0x00000002 /* "open" waiting for "ioctl" to finish */
-
-#define NO_HARD_RESET 0 /* don't do hard reset */
-#define HARD_RESET 1 /* do hard reset */
-
-
-/*
- * Constants setup during the first open of a kbd (so that they can be patched
- * for debugging purposes).
- */
-static int kbd_repeatrate;
-static int kbd_repeatdelay;
-
-static int kbd_overflow_cnt; /* Number of times kbd overflowed input q */
-static int kbd_overflow_msg = 1; /* Whether to print message on q overflow */
-
-#ifdef KBD_DEBUG
-int kbd_debug = 0;
-int kbd_ra_debug = 0;
-int kbd_raw_debug = 0;
-int kbd_rpt_debug = 0;
-int kbd_input_debug = 0;
-#endif /* KBD_DEBUG */
-
-static int kbdopen(queue_t *, dev_t *, int, int, cred_t *);
-static int kbdclose(queue_t *, int, cred_t *);
-static void kbdwput(queue_t *, mblk_t *);
-static void kbdrput(queue_t *, mblk_t *);
-
-static struct module_info kbdmiinfo = {
- 0,
- "kb",
- 0,
- INFPSZ,
- 2048,
- 128
-};
-
-static struct qinit kbdrinit = {
- (int (*)())kbdrput,
- (int (*)())NULL,
- kbdopen,
- kbdclose,
- (int (*)())NULL,
- &kbdmiinfo
-};
-
-static struct module_info kbdmoinfo = {
- 0,
- "kb",
- 0,
- INFPSZ,
- 2048,
- 128
-};
-
-static struct qinit kbdwinit = {
- (int (*)())kbdwput,
- (int (*)())NULL,
- kbdopen,
- kbdclose,
- (int (*)())NULL,
- &kbdmoinfo
-};
-
-static struct streamtab kbd_info = {
- &kbdrinit,
- &kbdwinit,
- NULL,
- NULL,
-};
-
-static void kbdreioctl(void *);
-static void kbdioctl(queue_t *, mblk_t *);
-static void kbdflush(struct kbddata *);
-static void kbduse(struct kbddata *, unsigned);
-static void kbdsetled(struct kbddata *);
-static void kbd_beep_off(void *arg);
-static void kbd_beep_on(void *arg);
-static void kbdcmd(queue_t *, char);
-static void kbdreset(struct kbddata *, uint_t);
-static int kbdsetkey(struct kbddata *, struct kiockey *, cred_t *);
-static int kbdgetkey(struct kbddata *, struct kiockey *);
-static int kbdskey(struct kbddata *, struct kiockeymap *, cred_t *);
-static int kbdgkey(struct kbddata *, struct kiockeymap *);
-static void kbdlayouttimeout(void *);
-static void kbdinput(struct kbddata *, unsigned);
-static void kbdid(struct kbddata *, int);
-static struct keymap *settable(struct kbddata *, uint_t);
-static void kbdrpt(void *);
-static void kbdcancelrpt(struct kbddata *);
-static void kbdtranslate(struct kbddata *, unsigned, queue_t *);
-static int kbd_do_compose(ushort_t, ushort_t, ushort_t *);
-static void kbd_send_esc_event(char, struct kbddata *);
-char *strsetwithdecimal(char *, uint_t, uint_t);
-static void kbdkeypressed(struct kbddata *, uchar_t, Firm_event *,
- ushort_t);
-static void kbdqueuepress(struct kbddata *, uchar_t, Firm_event *);
-static void kbdkeyreleased(struct kbddata *, uchar_t);
-static void kbdreleaseall(struct kbddata *);
-static void kbdputcode(uint_t, queue_t *);
-static void kbdputbuf(char *, queue_t *);
-static void kbdqueueevent(struct kbddata *, Firm_event *);
-
-/*
- * Dummy qbufcall callback routine used by open and close.
- * The framework will wake up qwait_sig when we return from
- * this routine (as part of leaving the perimeters.)
- * (The framework enters the perimeters before calling the qbufcall() callback
- * and leaves the perimeters after the callback routine has executed. The
- * framework performs an implicit wakeup of any thread in qwait/qwait_sig
- * when it leaves the perimeter. See qwait(9E).)
- */
-/* ARGSUSED */
-static void dummy_callback(void *arg)
-{}
-
-
-/*
- * Open a keyboard.
- * Ttyopen sets line characteristics
- */
-/* ARGSUSED */
-static int
-kbdopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
-{
- register int error;
- register struct kbddata *kbdd;
- mblk_t *mp;
- mblk_t *datap;
- register struct iocblk *iocb;
- register struct termios *cb;
-
- /* Set these up only once so that they could be changed from adb */
- if (!kbd_repeatrate) {
- kbd_repeatrate = (hz+29)/30;
- kbd_repeatdelay = hz/2;
- }
-
- if (q->q_ptr != NULL)
- return (0); /* already attached */
-
- /*
- * Only allow open requests to succeed for privileged users. This
- * necessary to prevent users from pushing the "kb" module again
- * on the stream associated with /dev/kbd.
- */
- if (secpolicy_console(crp) != 0) {
- return (EPERM);
- }
-
-
- switch (sflag) {
-
- case MODOPEN:
- break;
-
- case CLONEOPEN:
- return (EINVAL); /* No Bozos! */
- }
-
- /* allocate keyboard */
-
- kbdd = kmem_zalloc(sizeof (struct kbddata), KM_SLEEP);
-
-
- /*
- * Set up queue pointers, so that the "put" procedure will accept
- * the reply to the "ioctl" message we send down.
- */
- q->q_ptr = kbdd;
- WR(q)->q_ptr = kbdd;
-
- qprocson(q);
-
- /*
- * Setup tty modes.
- */
- while ((mp = mkiocb(TCSETSF)) == NULL) {
- timeout_id_t id = qbufcall(q, sizeof (struct iocblk), BPRI_HI,
- dummy_callback, NULL);
- if (!qwait_sig(q)) {
- qunbufcall(q, id);
- kmem_free(kbdd, sizeof (struct kbddata));
- qprocsoff(q);
-
- return (EINTR);
- }
- }
- while ((datap = allocb(sizeof (struct termios), BPRI_HI)) ==
- NULL) {
- timeout_id_t id = qbufcall(q, sizeof (struct termios), BPRI_HI,
- dummy_callback, NULL);
- if (!qwait_sig(q)) {
- qunbufcall(q, id);
- freemsg(mp);
- kmem_free(kbdd, sizeof (struct kbddata));
- qprocsoff(q);
-
- return (EINTR);
- }
- }
-
- iocb = (struct iocblk *)mp->b_rptr;
- iocb->ioc_count = sizeof (struct termios);
-
- cb = (struct termios *)datap->b_rptr;
- cb->c_iflag = 0;
- cb->c_oflag = 0;
- cb->c_cflag = CREAD|CS8|B1200;
- cb->c_lflag = 0;
- bzero(cb->c_cc, NCCS);
- datap->b_wptr += sizeof (struct termios);
- mp->b_cont = datap;
- kbdd->kbdd_flags |= KBD_IOCWAIT; /* indicate that we're */
- kbdd->kbdd_iocid = iocb->ioc_id; /* waiting for this response */
- putnext(WR(q), mp);
-
- /*
- * Now wait for it. Let our read queue put routine wake us up
- * when it arrives.
- */
- while (kbdd->kbdd_flags & KBD_IOCWAIT) {
- if (!qwait_sig(q)) {
- error = EINTR;
- goto error;
- }
- }
- if ((error = kbdd->kbdd_iocerror) != 0)
- goto error;
-
- /*
- * Set up private data.
- */
- kbdd->kbdd_readq = q;
- kbdd->kbdd_writeq = WR(q);
- kbdd->kbdd_iocpending = NULL;
- kbdd->kbdd_translatable = TR_CAN;
- kbdd->kbdd_translate = TR_ASCII;
- kbdd->kbdd_compat = 1;
- kbdd->kbdd_ascii_addr = ASCII_FIRST;
- kbdd->kbdd_top_addr = TOP_FIRST;
- kbdd->kbdd_vkey_addr = VKEY_FIRST;
- /* Allocate dynamic memory for downs table */
- kbdd->kbdd_downs_entries = kbd_downs_size;
- kbdd->kbdd_downs_bytes = kbd_downs_size * sizeof (Key_event);
- kbdd->kbdd_downs = kmem_alloc(kbdd->kbdd_downs_bytes, KM_SLEEP);
- kbdd->kbdd_flags = KBD_OPEN;
- kbdd->led_state = 0;
-
- /*
- * Reset kbd.
- */
- kbdreset(kbdd, HARD_RESET);
-
- (void) beep_init((void *)WR(q), kbd_beep_on, kbd_beep_off, NULL);
-
- return (0);
-
-error:
- qprocsoff(q);
- kmem_free(kbdd, sizeof (struct kbddata));
- return (error);
-}
-
-/*
- * Close a keyboard.
- */
-/* ARGSUSED1 */
-static int
-kbdclose(register queue_t *q, int flag, cred_t *crp)
-{
- register struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
- register mblk_t *mp;
-
- qprocsoff(q);
- (void) beep_fini();
- /*
- * Since we're about to destroy our private data, turn off
- * our open flag first, so we don't accept any more input
- * and try to use that data.
- */
- kbdd->kbdd_flags = 0;
-
- if ((mp = kbdd->kbdd_replypending) != NULL) {
- /*
- * There was a KIOCLAYOUT pending; presumably, it timed out.
- * Throw the reply away.
- */
- kbdd->kbdd_replypending = NULL;
- freemsg(mp);
- }
-
- /* clear all timeouts */
- if (kbdd->kbdd_bufcallid)
- qunbufcall(q, kbdd->kbdd_bufcallid);
- if (kbdd->kbdd_rptid)
- (void) quntimeout(q, kbdd->kbdd_rptid);
- if (kbdd->kbdd_layoutid)
- (void) quntimeout(q, kbdd->kbdd_layoutid);
- kmem_free(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes);
- kmem_free(kbdd, sizeof (struct kbddata));
- return (0);
-}
-
-/*
- * Line discipline output queue put procedure: handles M_IOCTL
- * messages.
- */
-static void
-kbdwput(register queue_t *q, register mblk_t *mp)
-{
- /*
- * Process M_FLUSH, and some M_IOCTL, messages here; pass
- * everything else down.
- */
- switch (mp->b_datap->db_type) {
-
- case M_FLUSH:
- if (*mp->b_rptr & FLUSHW)
- flushq(q, FLUSHDATA);
- if (*mp->b_rptr & FLUSHR)
- flushq(RD(q), FLUSHDATA);
-
- default:
- putnext(q, mp); /* pass it down the line */
- break;
-
- case M_IOCTL:
- kbdioctl(q, mp);
- break;
- }
-}
-
-
-static void
-kbdreioctl(void *kbdd_addr)
-{
- struct kbddata *kbdd = kbdd_addr;
- queue_t *q;
- mblk_t *mp;
-
- kbdd->kbdd_bufcallid = 0;
- q = kbdd->kbdd_writeq;
- if ((mp = kbdd->kbdd_iocpending) != NULL) {
- kbdd->kbdd_iocpending = NULL; /* not pending any more */
- kbdioctl(q, mp);
- }
-}
-
-static void
-kbdioctl(register queue_t *q, register mblk_t *mp)
-{
- register struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
- register struct iocblk *iocp;
- register short new_translate;
- register Vuid_addr_probe *addr_probe;
- register short *addr_ptr;
- mblk_t *datap;
- size_t ioctlrespsize;
- int err = 0;
- int tmp;
- int cycles;
- int frequency;
- int msecs;
-
- iocp = (struct iocblk *)mp->b_rptr;
-
- switch (iocp->ioc_cmd) {
-
- case VUIDSFORMAT:
- err = miocpullup(mp, sizeof (int));
- if (err != 0)
- break;
-
- new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ?
- TR_ASCII : TR_EVENT;
- if (new_translate == kbdd->kbdd_translate)
- break;
- kbdd->kbdd_translate = new_translate;
- goto output_format_change;
-
- case KIOCTRANS:
- err = miocpullup(mp, sizeof (int));
- if (err != 0)
- break;
-
- new_translate = *(int *)mp->b_cont->b_rptr;
- if (new_translate == kbdd->kbdd_translate)
- break;
- kbdd->kbdd_translate = new_translate;
- goto output_format_change;
-
- case KIOCCMD:
- err = miocpullup(mp, sizeof (int));
- if (err != 0)
- break;
-
- tmp = (char)(*(int *)mp->b_cont->b_rptr);
- if (tmp == KBD_CMD_BELL)
- (void) beeper_on(BEEP_TYPE4);
- else if (tmp == KBD_CMD_NOBELL)
- (void) beeper_off();
- else
- kbdcmd(q, tmp);
- break;
-
- case KIOCMKTONE:
- if (iocp->ioc_count != TRANSPARENT) {
- /*
- * We don't support non-transparent ioctls,
- * i.e. I_STR ioctls
- */
- err = EINVAL;
- break;
- }
- tmp = (int)(*(intptr_t *)mp->b_cont->b_rptr);
- cycles = tmp & 0xffff;
- msecs = (tmp >> 16) & 0xffff;
-
- if (cycles == 0)
- frequency = UINT16_MAX;
- else if (cycles == UINT16_MAX)
- frequency = 0;
- else {
- frequency = (PIT_HZ + cycles / 2) / cycles;
- if (frequency > UINT16_MAX)
- frequency = UINT16_MAX;
- }
-
- err = beep_mktone(frequency, msecs);
- break;
-
- case KIOCSLED:
- err = miocpullup(mp, sizeof (uchar_t));
- if (err != 0)
- break;
-
- kbdd->led_state = *(uchar_t *)mp->b_cont->b_rptr;
- kbdsetled(kbdd);
- break;
-
- case KIOCGLED:
- if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) {
- ioctlrespsize = sizeof (int);
- goto allocfailure;
- }
- *(uchar_t *)datap->b_wptr = kbdd->led_state;
- datap->b_wptr += sizeof (uchar_t);
- if (mp->b_cont) /* free msg to prevent memory leak */
- freemsg(mp->b_cont);
- mp->b_cont = datap;
- iocp->ioc_count = sizeof (uchar_t);
- break;
-
- case VUIDGFORMAT:
- if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
- ioctlrespsize = sizeof (int);
- goto allocfailure;
- }
- *(int *)datap->b_wptr =
- (kbdd->kbdd_translate == TR_EVENT ||
- kbdd->kbdd_translate == TR_UNTRANS_EVENT) ?
- VUID_FIRM_EVENT: VUID_NATIVE;
- datap->b_wptr += sizeof (int);
- if (mp->b_cont) /* free msg to prevent memory leak */
- freemsg(mp->b_cont);
- mp->b_cont = datap;
- iocp->ioc_count = sizeof (int);
- break;
-
- case KIOCGTRANS:
- if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
- ioctlrespsize = sizeof (int);
- goto allocfailure;
- }
- *(int *)datap->b_wptr = kbdd->kbdd_translate;
- datap->b_wptr += sizeof (int);
- if (mp->b_cont) /* free msg to prevent memory leak */
- freemsg(mp->b_cont);
- mp->b_cont = datap;
- iocp->ioc_count = sizeof (int);
- break;
-
- case VUIDSADDR:
- err = miocpullup(mp, sizeof (Vuid_addr_probe));
- if (err != 0)
- break;
-
- addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
- switch (addr_probe->base) {
-
- case ASCII_FIRST:
- addr_ptr = &kbdd->kbdd_ascii_addr;
- break;
-
- case TOP_FIRST:
- addr_ptr = &kbdd->kbdd_top_addr;
- break;
-
- case VKEY_FIRST:
- addr_ptr = &kbdd->kbdd_vkey_addr;
- break;
-
- default:
- err = ENODEV;
- }
- if ((err == 0) && (*addr_ptr != addr_probe->data.next)) {
- *addr_ptr = addr_probe->data.next;
- goto output_format_change;
- }
- break;
-
- case VUIDGADDR:
- err = miocpullup(mp, sizeof (Vuid_addr_probe));
- if (err != 0)
- break;
-
- addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
- switch (addr_probe->base) {
-
- case ASCII_FIRST:
- addr_probe->data.current = kbdd->kbdd_ascii_addr;
- break;
-
- case TOP_FIRST:
- addr_probe->data.current = kbdd->kbdd_top_addr;
- break;
-
- case VKEY_FIRST:
- addr_probe->data.current = kbdd->kbdd_vkey_addr;
- break;
-
- default:
- err = ENODEV;
- }
- break;
-
- case KIOCTRANSABLE:
- err = miocpullup(mp, sizeof (int));
- if (err != 0)
- break;
-
- if (kbdd->kbdd_translatable != *(int *)mp->b_cont->b_rptr) {
- kbdd->kbdd_translatable = *(int *)mp->b_cont->b_rptr;
- kbdreset(kbdd, HARD_RESET);
- goto output_format_change;
- }
- break;
-
- case KIOCGTRANSABLE:
- if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
- ioctlrespsize = sizeof (int);
- goto allocfailure;
- }
- *(int *)datap->b_wptr = kbdd->kbdd_translatable;
- datap->b_wptr += sizeof (int);
- if (mp->b_cont) /* free msg to prevent memory leak */
- freemsg(mp->b_cont);
- mp->b_cont = datap;
- iocp->ioc_count = sizeof (int);
- break;
-
- case KIOCSCOMPAT:
- err = miocpullup(mp, sizeof (int));
- if (err != 0)
- break;
-
- kbdd->kbdd_compat = *(int *)mp->b_cont->b_rptr;
- break;
-
- case KIOCGCOMPAT:
- if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
- ioctlrespsize = sizeof (int);
- goto allocfailure;
- }
- *(int *)datap->b_wptr = kbdd->kbdd_compat;
- datap->b_wptr += sizeof (int);
- if (mp->b_cont) /* free msg to prevent memory leak */
- freemsg(mp->b_cont);
- mp->b_cont = datap;
- iocp->ioc_count = sizeof (int);
- break;
-
- case KIOCSETKEY:
- err = miocpullup(mp, sizeof (struct kiockey));
- if (err != 0)
- break;
-
- err = kbdsetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr,
- iocp->ioc_cr);
- /*
- * Since this only affects any subsequent key presses,
- * don't goto output_format_change. One might want to
- * toggle the keytable entries dynamically.
- */
- break;
-
- case KIOCGETKEY:
- err = miocpullup(mp, sizeof (struct kiockey));
- if (err != 0)
- break;
-
- err = kbdgetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr);
- break;
-
- case KIOCSKEY:
- err = miocpullup(mp, sizeof (struct kiockeymap));
- if (err != 0)
- break;
-
- err = kbdskey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr,
- iocp->ioc_cr);
- /*
- * Since this only affects any subsequent key presses,
- * don't goto output_format_change. One might want to
- * toggle the keytable entries dynamically.
- */
- break;
-
- case KIOCGKEY:
- err = miocpullup(mp, sizeof (struct kiockeymap));
- if (err != 0)
- break;
-
- err = kbdgkey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr);
- break;
-
- case KIOCSDIRECT:
- goto output_format_change;
-
- case KIOCGDIRECT:
- if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
- ioctlrespsize = sizeof (int);
- goto allocfailure;
- }
- *(int *)datap->b_wptr = 1; /* always direct */
- datap->b_wptr += sizeof (int);
- if (mp->b_cont) /* free msg to prevent memory leak */
- freemsg(mp->b_cont);
- mp->b_cont = datap;
- iocp->ioc_count = sizeof (int);
- break;
-
- case KIOCTYPE:
- if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
- ioctlrespsize = sizeof (int);
- goto allocfailure;
- }
- *(int *)datap->b_wptr = kbdd->kbdd_state.k_id;
- datap->b_wptr += sizeof (int);
- if (mp->b_cont) /* free msg to prevent memory leak */
- freemsg(mp->b_cont);
- mp->b_cont = datap;
- iocp->ioc_count = sizeof (int);
- break;
-
- case KIOCLAYOUT:
- if ((datap = kbdd->kbdd_replypending) != NULL) {
- /*
- * There was an earlier KIOCLAYOUT pending; presumably,
- * it timed out. Throw the reply away.
- */
- kbdd->kbdd_replypending = NULL;
- freemsg(datap);
- }
-
- if (kbdd->kbdd_state.k_id == KB_SUN4 ||
- kbdd->kbdd_state.k_id == KB_PC) {
- if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
- ioctlrespsize = sizeof (int);
- goto allocfailure;
- }
- iocp->ioc_rval = 0;
- iocp->ioc_error = 0; /* brain rot */
- iocp->ioc_count = sizeof (int);
- if (mp->b_cont) /* free msg to prevent memory leak */
- freemsg(mp->b_cont);
- mp->b_cont = datap;
- mp->b_datap->db_type = M_IOCACK;
- kbdd->kbdd_replypending = mp;
- kbdcmd(q, (char)KBD_CMD_GETLAYOUT);
- if (kbdd->kbdd_layoutid)
- (void) quntimeout(q, kbdd->kbdd_layoutid);
- kbdd->kbdd_layoutid = qtimeout(q, kbdlayouttimeout,
- kbdd, hz / 5);
- return; /* wait for reply from keyboard */
- } else {
- /*
- * Not a Type 4 keyboard; return an immediate error.
- */
- err = EINVAL;
- break;
- }
-
- case KIOCGRPTDELAY:
- /*
- * Report the autorepeat delay, unit in millisecond
- */
- if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
- ioctlrespsize = sizeof (int);
- goto allocfailure;
- }
- *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatdelay);
- datap->b_wptr += sizeof (int);
-
- /* free msg to prevent memory leak */
- if (mp->b_cont != NULL)
- freemsg(mp->b_cont);
- mp->b_cont = datap;
- iocp->ioc_count = sizeof (int);
- break;
-
- case KIOCSRPTDELAY:
- /*
- * Set the autorepeat delay
- */
- err = miocpullup(mp, sizeof (int));
-
- if (err != 0)
- break;
-
- /* validate the input */
- if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) {
- err = EINVAL;
- break;
- }
- kbd_repeatdelay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
- if (kbd_repeatdelay <= 0)
- kbd_repeatdelay = 1;
- break;
-
- case KIOCGRPTRATE:
- /*
- * Report the autorepeat rate
- */
- if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
- ioctlrespsize = sizeof (int);
- goto allocfailure;
- }
- *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatrate);
- datap->b_wptr += sizeof (int);
-
- /* free msg to prevent memory leak */
- if (mp->b_cont != NULL)
- freemsg(mp->b_cont);
- mp->b_cont = datap;
- iocp->ioc_count = sizeof (int);
- break;
-
- case KIOCSRPTRATE:
- /*
- * Set the autorepeat rate
- */
- err = miocpullup(mp, sizeof (int));
-
- if (err != 0)
- break;
-
- /* validate the input */
- if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) {
- err = EINVAL;
- break;
- }
- kbd_repeatrate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
- if (kbd_repeatrate <= 0)
- kbd_repeatrate = 1;
- break;
-
- default:
- putnext(q, mp); /* pass it down the line */
- return;
- }
- goto done;
-
-output_format_change:
- kbdflush(kbdd);
-
-done:
- if (err != 0) {
- iocp->ioc_rval = 0;
- iocp->ioc_error = err;
- mp->b_datap->db_type = M_IOCNAK;
- } else {
- iocp->ioc_rval = 0;
- iocp->ioc_error = 0; /* brain rot */
- mp->b_datap->db_type = M_IOCACK;
- }
- qreply(q, mp);
- return;
-
-allocfailure:
- /*
- * We needed to allocate something to handle this "ioctl", but
- * couldn't; save this "ioctl" and arrange to get called back when
- * it's more likely that we can get what we need.
- * If there's already one being saved, throw it out, since it
- * must have timed out.
- */
- if (kbdd->kbdd_iocpending != NULL)
- freemsg(kbdd->kbdd_iocpending);
- kbdd->kbdd_iocpending = mp;
- if (kbdd->kbdd_bufcallid)
- qunbufcall(q, kbdd->kbdd_bufcallid);
- kbdd->kbdd_bufcallid = qbufcall(q, ioctlrespsize, BPRI_HI,
- kbdreioctl, kbdd);
-}
-
-static void
-kbdflush(register struct kbddata *kbdd)
-{
- register queue_t *q;
-
- /* Flush pending data already sent upstream */
- if ((q = kbdd->kbdd_readq) != NULL && q->q_next != NULL)
- (void) putnextctl1(q, M_FLUSH, FLUSHR);
- /* Flush pending ups */
- bzero(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes);
- kbdcancelrpt(kbdd);
-}
-
-/*
- * Pass keycode upstream, either translated or untranslated.
- */
-static void
-kbduse(register struct kbddata *kbdd, unsigned keycode)
-{
- register queue_t *readq;
-
-#ifdef KBD_DEBUG
- if (kbd_input_debug) printf("KBD USE key=%d\n", keycode);
-#endif
-
- if ((readq = kbdd->kbdd_readq) == NULL)
- return;
- if (!kbdd->kbdd_translatable ||
- kbdd->kbdd_translate == TR_NONE)
- kbdputcode(keycode, readq);
- else
- kbdtranslate(kbdd, keycode, readq);
-}
-
-static void
-kbd_beep_on(void *arg)
-{
- kbdcmd((queue_t *)arg, KBD_CMD_BELL);
-}
-
-
-static void
-kbd_beep_off(void *arg)
-{
- kbdcmd((queue_t *)arg, KBD_CMD_NOBELL);
-}
-
-
-/*
- * kbdclick is used to remember the current click value of the
- * Sun-3 keyboard. This brain damaged keyboard will reset the
- * clicking to the "default" value after a reset command and
- * there is no way to read out the current click value. We
- * cannot send a click command immediately after the reset
- * command or the keyboard gets screwed up. So we wait until
- * we get the ID byte before we send back the click command.
- * Unfortunately, this means that there is a small window
- * where the keyboard can click when it really shouldn't be.
- * A value of -1 means that kbdclick has not been initialized yet.
- */
-static int kbdclick = -1;
-
-/*
- * Send command byte to keyboard, if you can.
- */
-static void
-kbdcmd(register queue_t *q, char cmd)
-{
- register mblk_t *bp;
-
- if (canput(q)) {
- if ((bp = allocb(1, BPRI_MED)) == NULL)
- cmn_err(CE_WARN,
- "kbdcmd: Can't allocate block for command");
- else {
- *bp->b_wptr++ = cmd;
- putnext(q, bp);
- if (cmd == KBD_CMD_NOCLICK)
- kbdclick = 0;
- else if (cmd == KBD_CMD_CLICK)
- kbdclick = 1;
- }
- }
-}
-
-/*
- * Update the keyboard LEDs to match the current keyboard state.
- * Do this only on Type 4 keyboards; other keyboards don't support the
- * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs).
- */
-static void
-kbdsetled(register struct kbddata *kbdd)
-{
- if (kbdd->kbdd_state.k_id == KB_SUN4 ||
- kbdd->kbdd_state.k_id == KB_PC) {
- kbdcmd(kbdd->kbdd_writeq, KBD_CMD_SETLED);
- kbdcmd(kbdd->kbdd_writeq, kbdd->led_state);
- }
-}
-
-/*
- * Reset the keyboard
- */
-static void
-kbdreset(register struct kbddata *kbdd, uint_t hard_reset)
-{
- register struct keyboardstate *k;
-
- k = &kbdd->kbdd_state;
- if (kbdd->kbdd_translatable) {
- k->k_idstate = KID_NONE;
- k->k_id = -1;
- k->k_state = NORMAL;
- if (hard_reset)
- kbdcmd(kbdd->kbdd_writeq, KBD_CMD_RESET);
- } else {
- bzero(k, sizeof (struct keyboardstate));
- k->k_id = KB_ASCII;
- k->k_idstate = KID_OK;
- }
-}
-
-/*
- * Old special codes.
- */
-#define OLD_SHIFTKEYS 0x80
-#define OLD_BUCKYBITS 0x90
-#define OLD_FUNNY 0xA0
-#define OLD_FA_UMLAUT 0xA9
-#define OLD_FA_CFLEX 0xAA
-#define OLD_FA_TILDE 0xAB
-#define OLD_FA_CEDILLA 0xAC
-#define OLD_FA_ACUTE 0xAD
-#define OLD_FA_GRAVE 0xAE
-#define OLD_ISOCHAR 0xAF
-#define OLD_STRING 0xB0
-#define OLD_LEFTFUNC 0xC0
-#define OLD_RIGHTFUNC 0xD0
-#define OLD_TOPFUNC 0xE0
-#define OLD_BOTTOMFUNC 0xF0
-
-/*
- * Map old special codes to new ones.
- * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F.
- */
-static ushort_t special_old_to_new[] = {
- SHIFTKEYS,
- BUCKYBITS,
- FUNNY,
- STRING,
- LEFTFUNC,
- RIGHTFUNC,
- TOPFUNC,
- BOTTOMFUNC,
-};
-
-/*
- * Set individual keystation translation from old-style entry.
- * TODO: Have each keyboard own own translation tables.
- */
-static int
-kbdsetkey(register struct kbddata *kbdd, struct kiockey *key, cred_t *cr)
-{
- int strtabindex, i;
- struct keymap *km;
- register int tablemask;
- register ushort_t entry;
-
- if (key->kio_station >= KEYMAP_SIZE)
- return (EINVAL);
- if (kbdd->kbdd_state.k_curkeyboard == NULL)
- return (EINVAL);
- tablemask = key->kio_tablemask;
- if (tablemask == KIOCABORT1) {
- if (secpolicy_console(cr) != 0)
- return (EPERM);
- kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station;
- return (0);
- }
- if (tablemask == KIOCABORT2) {
- if (secpolicy_console(cr) != 0)
- return (EPERM);
- kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station;
- return (0);
- }
- if ((tablemask & ALTGRAPHMASK) ||
- (km = settable(kbdd, (uint_t)tablemask)) == NULL)
- return (EINVAL);
- if (key->kio_entry >= (uchar_t)OLD_STRING &&
- key->kio_entry <= (uchar_t)(OLD_STRING + 15)) {
- strtabindex = key->kio_entry - OLD_STRING;
- for (i = 0; i < KTAB_STRLEN; i++)
- keystringtab[strtabindex][i] = key->kio_string[i];
- keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
- }
- entry = key->kio_entry;
- /*
- * There's nothing we need do with OLD_ISOCHAR.
- */
- if (entry != OLD_ISOCHAR) {
- if (entry & 0x80) {
- if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE)
- entry = FA_CLASS + (entry & 0x0F) - 9;
- else
- entry =
- special_old_to_new[entry >> 4 & 0x07]
- + (entry & 0x0F);
- }
- }
- km->keymap[key->kio_station] = entry;
- return (0);
-}
-
-/*
- * Map new special codes to old ones.
- * Indexed by (new special code) >> 8; add (new special code) & 0xFF.
- */
-static uchar_t special_new_to_old[] = {
- 0, /* normal */
- OLD_SHIFTKEYS, /* SHIFTKEYS */
- OLD_BUCKYBITS, /* BUCKYBITS */
- OLD_FUNNY, /* FUNNY */
- OLD_FA_UMLAUT, /* FA_CLASS */
- OLD_STRING, /* STRING */
- OLD_LEFTFUNC, /* FUNCKEYS */
-};
-
-/*
- * Get individual keystation translation as old-style entry.
- */
-static int
-kbdgetkey(register struct kbddata *kbdd, struct kiockey *key)
-{
- int strtabindex, i;
- struct keymap *km;
- register ushort_t entry;
-
- if (key->kio_station >= KEYMAP_SIZE)
- return (EINVAL);
- if (kbdd->kbdd_state.k_curkeyboard == NULL)
- return (EINVAL);
- if (key->kio_tablemask == KIOCABORT1) {
- key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1;
- return (0);
- }
- if (key->kio_tablemask == KIOCABORT2) {
- key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2;
- return (0);
- }
- if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
- return (EINVAL);
- entry = km->keymap[key->kio_station];
- if (entry & 0xFF00)
- key->kio_entry =
- special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8]
- + (entry & 0x00FF);
- else {
- if (entry & 0x80)
- key->kio_entry = (ushort_t)OLD_ISOCHAR; /* you lose */
- else
- key->kio_entry = (ushort_t)entry;
- }
- if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) {
- strtabindex = entry - STRING;
- for (i = 0; i < KTAB_STRLEN; i++)
- key->kio_string[i] = keystringtab[strtabindex][i];
- }
- return (0);
-}
-
-/*
- * Set individual keystation translation from new-style entry.
- * TODO: Have each keyboard own own translation tables.
- */
-static int
-kbdskey(register struct kbddata *kbdd, struct kiockeymap *key, cred_t *cr)
-{
- int strtabindex, i;
- struct keymap *km;
-
- if (key->kio_station >= KEYMAP_SIZE)
- return (EINVAL);
- if (kbdd->kbdd_state.k_curkeyboard == NULL)
- return (EINVAL);
- if (key->kio_tablemask == KIOCABORT1) {
- if (secpolicy_console(cr) != 0)
- return (EPERM);
- kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station;
- return (0);
- }
- if (key->kio_tablemask == KIOCABORT2) {
- if (secpolicy_console(cr) != 0)
- return (EPERM);
- kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station;
- return (0);
- }
- if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
- return (EINVAL);
- if (key->kio_entry >= STRING &&
- key->kio_entry <= (ushort_t)(STRING + 15)) {
- strtabindex = key->kio_entry-STRING;
- for (i = 0; i < KTAB_STRLEN; i++)
- keystringtab[strtabindex][i] = key->kio_string[i];
- keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
- }
- km->keymap[key->kio_station] = key->kio_entry;
- return (0);
-}
-
-/*
- * Get individual keystation translation as new-style entry.
- */
-static int
-kbdgkey(register struct kbddata *kbdd, struct kiockeymap *key)
-{
- int strtabindex, i;
- struct keymap *km;
-
- if (key->kio_station >= KEYMAP_SIZE)
- return (EINVAL);
- if (kbdd->kbdd_state.k_curkeyboard == NULL)
- return (EINVAL);
- if (key->kio_tablemask == KIOCABORT1) {
- key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1;
- return (0);
- }
- if (key->kio_tablemask == KIOCABORT2) {
- key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2;
- return (0);
- }
- if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
- return (EINVAL);
- key->kio_entry = km->keymap[key->kio_station];
- if (key->kio_entry >= STRING &&
- key->kio_entry <= (ushort_t)(STRING + 15)) {
- strtabindex = key->kio_entry-STRING;
- for (i = 0; i < KTAB_STRLEN; i++)
- key->kio_string[i] = keystringtab[strtabindex][i];
- }
- return (0);
-}
-
-static void
-kbdlayouttimeout(void *arg)
-{
- struct kbddata *kbdd = arg;
- mblk_t *mp;
-
- kbdd->kbdd_layoutid = 0;
-
- /*
- * Timed out waiting for reply to "get keyboard layout" command.
- * Return an ETIME error.
- */
- if ((mp = kbdd->kbdd_replypending) != NULL) {
- kbdd->kbdd_replypending = NULL;
- mp->b_datap->db_type = M_IOCNAK;
- ((struct iocblk *)mp->b_rptr)->ioc_error = ETIME;
- putnext(kbdd->kbdd_readq, mp);
- }
-}
-
-/*
- * Put procedure for input from driver end of stream (read queue).
- */
-static void
-kbdrput(register queue_t *q, register mblk_t *mp)
-{
- struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
- register mblk_t *bp;
- register uchar_t *readp;
- struct iocblk *iocp;
-
- if (kbdd == 0) {
- freemsg(mp); /* nobody's listening */
- return;
- }
-
- switch (mp->b_datap->db_type) {
-
- case M_FLUSH:
- if (*mp->b_rptr & FLUSHW)
- flushq(WR(q), FLUSHDATA);
- if (*mp->b_rptr & FLUSHR)
- flushq(q, FLUSHDATA);
-
- default:
- putnext(q, mp);
- return;
-
- case M_BREAK:
- /*
- * Will get M_BREAK only if this is not the system
- * keyboard, otherwise serial port will eat break
- * and call kmdb/OBP, without passing anything up.
- */
- freemsg(mp);
- return;
-
- case M_IOCACK:
- case M_IOCNAK:
- /*
- * If we are doing an "ioctl" ourselves, check if this
- * is the reply to that code. If so, wake up the
- * "open" routine, and toss the reply, otherwise just
- * pass it up.
- */
- iocp = (struct iocblk *)mp->b_rptr;
- if (!(kbdd->kbdd_flags & KBD_IOCWAIT) ||
- iocp->ioc_id != kbdd->kbdd_iocid) {
- /*
- * This isn't the reply we're looking for. Move along.
- */
- if (kbdd->kbdd_flags & KBD_OPEN)
- putnext(q, mp);
- else
- freemsg(mp); /* not ready to listen */
- } else {
- kbdd->kbdd_flags &= ~KBD_IOCWAIT;
- kbdd->kbdd_iocerror = iocp->ioc_error;
- freemsg(mp);
- }
- return;
-
- case M_DATA:
- if (!(kbdd->kbdd_flags & KBD_OPEN)) {
- freemsg(mp); /* not read to listen */
- return;
- }
- break;
- }
-
- /*
- * A data message, consisting of bytes from the keyboard.
- * Ram them through our state machine.
- */
- bp = mp;
-
- do {
- readp = bp->b_rptr;
- while (readp < bp->b_wptr)
- kbdinput(kbdd, *readp++);
- bp->b_rptr = readp;
- } while ((bp = bp->b_cont) != NULL); /* next block, if any */
-
- freemsg(mp);
-}
-
-/*
- * A keypress was received. Process it through the state machine
- * to check for aborts.
- */
-static void
-kbdinput(register struct kbddata *kbdd, register unsigned key)
-{
- register struct keyboardstate *k;
- register mblk_t *mp;
-
- k = &kbdd->kbdd_state;
-#ifdef KBD_DEBUG
- if (kbd_input_debug)
- printf("kbdinput key %x\n", key);
-#endif
-
- switch (k->k_idstate) {
-
- case KID_NONE:
- if (key == RESETKEY) {
- k->k_idstate = KID_GOT_PREFACE;
- } else {
- kbdreset(kbdd, HARD_RESET);
- /* allows hot plug of kbd after booting without kbd */
- }
- return;
-
- case KID_GOT_PREFACE:
- kbdid(kbdd, (int)key);
-
- /*
- * We just did a reset command to a Type 3 or Type 4
- * keyboard which sets the click back to the default
- * (which is currently ON!). We use the kbdclick
- * variable to see if the keyboard should be turned on
- * or off. If it has not been set, then we use the
- * keyboard-click? property.
- */
- switch (kbdclick) {
- case 0:
- kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK);
- break;
- case 1:
- kbdcmd(kbdd->kbdd_writeq, KBD_CMD_CLICK);
- break;
- case -1:
- default:
- {
- char wrkbuf[8];
- int len;
-
- kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK);
-
- bzero(wrkbuf, 8);
- len = 7;
- if (ddi_getlongprop_buf(DDI_DEV_T_ANY,
- ddi_root_node(), 0, "keyboard-click?",
- (caddr_t)wrkbuf, &len) ==
- DDI_PROP_SUCCESS &&
- len > 0 && len < 8) {
- if (strcmp(wrkbuf, "true") == 0) {
- kbdcmd(kbdd->kbdd_writeq,
- KBD_CMD_CLICK);
- }
- }
- }
- break;
- }
- /*
- * A keyboard reset clears the LEDs.
- * Restore the LEDs from the last value we set
- * them to.
- */
- kbdsetled(kbdd);
- return;
-
- case KID_OK:
- switch (key) {
-
-#if defined(KBD_PRESSED_PREFIX)
- case KBD_PRESSED_PREFIX:
- k->k_idstate = KID_GOT_PRESSED;
- return;
-#endif
-
-#if defined(KBD_RELEASED_PREFIX)
- case KBD_RELEASED_PREFIX:
- k->k_idstate = KID_GOT_RELEASED;
- return;
-#endif
-
- case 0:
- kbdreset(kbdd, HARD_RESET);
- return;
-
- /*
- * we want to check for ID only if we are in
- * translatable mode.
- */
- case RESETKEY:
- kbdreset(kbdd, NO_HARD_RESET);
- if (k->k_idstate == KID_NONE) {
- k->k_idstate = KID_GOT_PREFACE;
- }
- return;
-
- case LAYOUTKEY:
- k->k_idstate = KID_GOT_LAYOUT;
- return;
- }
- break;
-
-#if defined(KBD_PRESSED_PREFIX)
- case KID_GOT_PRESSED:
- key = BUILDKEY(key, PRESSED);
- k->k_idstate = KID_OK;
- break;
-#endif
-#if defined(KBD_RELEASED_PREFIX)
- case KID_GOT_RELEASED:
- key = BUILDKEY(key, RELEASED);
- k->k_idstate = KID_OK;
- break;
-#endif
-
- case KID_GOT_LAYOUT:
- if (kbdd->kbdd_layoutid)
- (void) quntimeout(kbdd->kbdd_readq,
- kbdd->kbdd_layoutid);
- if ((mp = kbdd->kbdd_replypending) != NULL) {
- kbdd->kbdd_replypending = NULL;
- *(int *)mp->b_cont->b_wptr = key;
- mp->b_cont->b_wptr += sizeof (int);
- putnext(kbdd->kbdd_readq, mp);
- }
- k->k_idstate = KID_OK;
- return;
- }
-
- switch (k->k_state) {
-
-#if defined(__sparc)
- normalstate:
- k->k_state = NORMAL;
- /* FALLTHRU */
-#endif
- case NORMAL:
-#if defined(__sparc)
- if (k->k_curkeyboard) {
- if (key == k->k_curkeyboard->k_abort1) {
- k->k_state = ABORT1;
- break;
- }
- if ((key == k->k_curkeyboard->k_newabort1) ||
- (key == k->k_curkeyboard->k_newabort1a)) {
- k->k_state = NEWABORT1;
- kbdd->shiftkey = key;
- }
- }
-#endif
- kbduse(kbdd, key);
- break;
-
-#if defined(__sparc)
- case ABORT1:
- if (k->k_curkeyboard) {
- /*
- * Only recognize this as an abort sequence if
- * the "hardware" console is set to be this device.
- */
- if (key == k->k_curkeyboard->k_abort2 &&
- rconsvp == wsconsvp) {
- DELAY(100000);
- abort_sequence_enter((char *)NULL);
- k->k_state = NORMAL;
- kbduse(kbdd, IDLEKEY); /* fake */
- return;
- } else {
- kbduse(kbdd, k->k_curkeyboard->k_abort1);
- goto normalstate;
- }
- }
- break;
- case NEWABORT1:
- if (k->k_curkeyboard) {
- /*
- * Only recognize this as an abort sequence if
- * the "hardware" console is set to be this device.
- */
- if (key == k->k_curkeyboard->k_newabort2 &&
- rconsvp == wsconsvp) {
- DELAY(100000);
- abort_sequence_enter((char *)NULL);
- k->k_state = NORMAL;
- kbdd->shiftkey |= RELEASED;
- kbduse(kbdd, kbdd->shiftkey);
- kbduse(kbdd, IDLEKEY); /* fake */
- return;
- } else {
- goto normalstate;
- }
- }
- break;
-#endif
-
- case COMPOSE1:
- case COMPOSE2:
- case FLTACCENT:
- if (key != IDLEKEY)
- kbduse(kbdd, key);
- break;
- }
-}
-
-static void
-kbdid(register struct kbddata *kbdd, int id)
-{
- register struct keyboardstate *k;
- int i;
-
- k = &kbdd->kbdd_state;
-
- k->k_idstate = KID_OK;
- k->k_shiftmask = 0;
- k->k_buckybits = 0;
-
- /*
- * Reset k_rptkey to IDLEKEY. We need to cancel
- * the autorepeat feature, if any.
- */
- if (k->k_rptkey != IDLEKEY) {
- if (kbdd->kbdd_rptid)
- (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid);
- kbdd->kbdd_rptid = 0;
- k->k_rptkey = IDLEKEY;
- }
-
- k->k_curkeyboard = NULL;
- for (i = 0; keytables[i].table; i++) {
- if (keytables[i].id == id) {
- k->k_id = id;
- k->k_curkeyboard = keytables[i].table;
- break;
- }
- }
- if (!k->k_curkeyboard) {
- k->k_id = keytables[0].id;
- k->k_curkeyboard = keytables[0].table;
- cmn_err(CE_WARN, "kbd: Unknown keyboard type, "
- "Type %d assumed", k->k_id);
- }
-}
-
-/*
- * This routine determines which table we should look in to decode
- * the current keycode.
- */
-static struct keymap *
-settable(register struct kbddata *kbdd, register uint_t mask)
-{
- register struct keyboard *kp;
-
- kp = kbdd->kbdd_state.k_curkeyboard;
- if (kp == NULL)
- return (NULL);
- if (mask & UPMASK)
- return (kp->k_up);
- if (mask & NUMLOCKMASK)
- return (kp->k_numlock);
- if (mask & CTRLMASK)
- return (kp->k_control);
- if (mask & ALTGRAPHMASK)
- return (kp->k_altgraph);
- if (mask & SHIFTMASK)
- return (kp->k_shifted);
- if (mask & CAPSMASK)
- return (kp->k_caps);
- return (kp->k_normal);
-}
-
-static void
-kbdrpt(void *arg)
-{
- struct kbddata *kbdd = arg;
- struct keyboardstate *k;
-
- k = &kbdd->kbdd_state;
-#ifdef KBD_DEBUG
- if (kbd_rpt_debug)
- printf("kbdrpt key %x\n", k->k_rptkey);
-#endif
- kbdd->kbdd_rptid = 0;
-
- kbdkeyreleased(kbdd, KEYOF(k->k_rptkey));
- kbduse(kbdd, k->k_rptkey);
- if (k->k_rptkey != IDLEKEY) {
- kbdd->kbdd_rptid = qtimeout(kbdd->kbdd_readq, kbdrpt,
- kbdd, kbd_repeatrate);
- }
-}
-
-static void
-kbdcancelrpt(register struct kbddata *kbdd)
-{
- register struct keyboardstate *k;
-
- k = &kbdd->kbdd_state;
- if (k->k_rptkey != IDLEKEY) {
- if (kbdd->kbdd_rptid)
- (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid);
- kbdd->kbdd_rptid = 0;
- k->k_rptkey = IDLEKEY;
- }
- ASSERT(kbdd->kbdd_rptid == 0);
-}
-
-static void
-kbdtranslate(struct kbddata *kbdd, unsigned keycode, queue_t *q)
-{
- register uchar_t key;
- register unsigned newstate;
- unsigned shiftmask;
- register ushort_t entry, entrytype;
- register char *cp, *bufp;
- register struct keyboardstate *k;
- ushort_t result_iso;
- struct keymap *km;
- Firm_event fe;
- int i, ret_val;
- char buf[14];
-
- k = &kbdd->kbdd_state;
- newstate = STATEOF(keycode);
- key = KEYOF(keycode);
-
-#ifdef KBD_DEBUG
- if (kbd_input_debug) {
- printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n",
- keycode, newstate, key);
- }
-#endif
-
- if (kbdd->kbdd_translate == TR_UNTRANS_EVENT) {
- if (newstate == PRESSED) {
- bzero(&fe, sizeof (fe));
- fe.id = key;
- fe.value = 1;
- kbdqueuepress(kbdd, key, &fe);
- } else {
- kbdkeyreleased(kbdd, key);
- }
- return;
- }
-
- shiftmask = k->k_shiftmask;
- if (newstate == RELEASED)
- shiftmask |= UPMASK;
-
- km = settable(kbdd, shiftmask);
- if (km == NULL) { /* gross error */
- kbdcancelrpt(kbdd);
- return;
- }
-
- if (key >= KEYMAP_SIZE)
- return;
- entry = km->keymap[key];
-
- if (entry == NONL) {
- /*
- * NONL appears only in the Num Lock table, and indicates that
- * this key is not affected by Num Lock. This means we should
- * ask for the table we would have gotten had Num Lock not been
- * down, and translate using that table.
- */
- km = settable(kbdd, shiftmask & ~NUMLOCKMASK);
- if (km == NULL) { /* gross error */
- kbdcancelrpt(kbdd);
- return;
- }
- entry = km->keymap[key];
- }
- entrytype = (ushort_t)(entry & 0xFF00) >> 8;
-
- if (entrytype == (SHIFTKEYS >> 8)) {
- /*
- * Handle the state of toggle shifts specially.
- * Ups should be ignored, and downs should be mapped to ups if
- * that shift is currently on.
- */
- if ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts) {
- if ((1 << (entry & 0x0F)) & k->k_togglemask) {
- newstate = RELEASED; /* toggling off */
- } else {
- newstate = PRESSED; /* toggling on */
- }
- }
- } else {
- /*
- * Handle Compose and floating accent key sequences
- */
- if (k->k_state == COMPOSE1) {
- if (newstate == RELEASED)
- return;
- if (entry < ASCII_SET_SIZE) {
- if (kb_compose_map[entry] >= 0) {
- kbdd->compose_key = entry;
- k->k_state = COMPOSE2;
- return;
- }
- }
- k->k_state = NORMAL;
- kbdd->led_state &= ~LED_COMPOSE;
- kbdsetled(kbdd);
- return;
- } else if (k->k_state == COMPOSE2) {
- if (newstate == RELEASED)
- return;
- k->k_state = NORMAL; /* next state is "normal" */
- kbdd->led_state &= ~LED_COMPOSE;
- kbdsetled(kbdd);
- if (entry < ASCII_SET_SIZE) {
- if (kb_compose_map[entry] >= 0) {
- if (kbdd->compose_key <= entry) {
- ret_val = kbd_do_compose(
- kbdd->compose_key,
- entry,
- &result_iso);
- } else {
- ret_val = kbd_do_compose(
- entry,
- kbdd->compose_key,
- &result_iso);
- }
- if (ret_val == 1) {
- if (kbdd->kbdd_translate ==
- TR_EVENT) {
- fe.id =
- (kbdd->kbdd_compat ?
- ISO_FIRST :
- EUC_FIRST)
- + result_iso;
- fe.value = 1;
- kbdqueueevent(
- kbdd,
- &fe);
- } else if (
- kbdd->kbdd_translate ==
- TR_ASCII)
- kbdputcode(
- result_iso,
- q);
- }
- }
- }
- return;
- } else if (k->k_state == FLTACCENT) {
- if (newstate == RELEASED)
- return;
- k->k_state = NORMAL; /* next state is "normal" */
- for (i = 0;
- (kb_fltaccent_table[i].fa_entry
- != kbdd->fltaccent_entry) ||
- (kb_fltaccent_table[i].ascii != entry);
- i++) {
- if (kb_fltaccent_table[i].fa_entry == 0)
- /* Invalid second key: ignore key */
- return;
- }
- if (kbdd->kbdd_translate == TR_EVENT) {
- fe.id = (kbdd->kbdd_compat ?
- ISO_FIRST : EUC_FIRST)
- + kb_fltaccent_table[i].iso;
- fe.value = 1;
- kbdqueueevent(kbdd, &fe);
- } else if (kbdd->kbdd_translate == TR_ASCII)
- kbdputcode(kb_fltaccent_table[i].iso, q);
- return;
- }
- }
-
- /*
- * If the key is going down, and it's not one of the keys that doesn't
- * auto-repeat, set up the auto-repeat timeout.
- *
- * The keys that don't auto-repeat are the Compose key,
- * the shift keys, the "bucky bit" keys, the "floating accent" keys,
- * and the function keys when in TR_EVENT mode.
- */
- if (newstate == PRESSED && entrytype != (SHIFTKEYS >> 8) &&
- entrytype != (BUCKYBITS >> 8) && entrytype != (FUNNY >> 8) &&
- entrytype != (FA_CLASS >> 8) &&
- !((entrytype == (FUNCKEYS >> 8) || entrytype == (PADKEYS >> 8)) &&
- kbdd->kbdd_translate == TR_EVENT)) {
- if (k->k_rptkey != keycode) {
- kbdcancelrpt(kbdd);
- kbdd->kbdd_rptid = qtimeout(q, kbdrpt, kbdd,
- kbd_repeatdelay);
- k->k_rptkey = keycode;
- }
- } else if (key == KEYOF(k->k_rptkey)) /* key going up */
- kbdcancelrpt(kbdd);
- if ((newstate == RELEASED) && (kbdd->kbdd_translate == TR_EVENT))
- kbdkeyreleased(kbdd, key);
-
- /*
- * We assume here that keys other than shift keys and bucky keys have
- * entries in the "up" table that cause nothing to be done, and thus we
- * don't have to check for newstate == RELEASED.
- */
- switch (entrytype) {
-
- case 0x0: /* regular key */
- switch (kbdd->kbdd_translate) {
-
- case TR_EVENT:
- fe.id = entry | k->k_buckybits;
- fe.value = 1;
- kbdkeypressed(kbdd, key, &fe, entry);
- break;
-
- case TR_ASCII:
- kbdputcode(entry | k->k_buckybits, q);
- break;
- }
- break;
-
- case SHIFTKEYS >> 8: {
- uint_t shiftbit = 1 << (entry & 0x0F);
-
- /* Modify toggle state (see toggle processing above) */
- if (shiftbit & k->k_curkeyboard->k_toggleshifts) {
- if (newstate == RELEASED) {
- if (shiftbit == CAPSMASK) {
- kbdd->led_state &= ~LED_CAPS_LOCK;
- kbdsetled(kbdd);
- } else if (shiftbit == NUMLOCKMASK) {
- kbdd->led_state &= ~LED_NUM_LOCK;
- kbdsetled(kbdd);
- }
- k->k_togglemask &= ~shiftbit;
- } else {
- if (shiftbit == CAPSMASK) {
- kbdd->led_state |= LED_CAPS_LOCK;
- kbdsetled(kbdd);
- } else if (shiftbit == NUMLOCKMASK) {
- kbdd->led_state |= LED_NUM_LOCK;
- kbdsetled(kbdd);
- }
- k->k_togglemask |= shiftbit;
- }
- }
-
- if (newstate == RELEASED)
- k->k_shiftmask &= ~shiftbit;
- else
- k->k_shiftmask |= shiftbit;
-
- if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) {
- /*
- * Relying on ordinal correspondence between
- * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
- * kbd.h CAPSLOCK-RIGHTCTRL in order to
- * correctly translate entry into fe.id.
- */
- fe.id = SHIFT_CAPSLOCK + (entry & 0x0F);
- fe.value = 1;
- kbdkeypressed(kbdd, key, &fe, fe.id);
- }
- break;
- }
-
- case BUCKYBITS >> 8:
- k->k_buckybits ^= 1 << (7 + (entry & 0x0F));
- if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) {
- /*
- * Relying on ordinal correspondence between
- * vuid_event.h SHIFT_META-SHIFT_TOP &
- * kbd.h METABIT-SYSTEMBIT in order to
- * correctly translate entry into fe.id.
- */
- fe.id = SHIFT_META + (entry & 0x0F);
- fe.value = 1;
- kbdkeypressed(kbdd, key, &fe, fe.id);
- }
- break;
-
- case FUNNY >> 8:
- switch (entry) {
- case NOP:
- break;
-
- case IDLE:
- /* Fall thru into RESET code */
- /* FALLTHRU */
- case RESET:
- gotreset:
- k->k_shiftmask &= k->k_curkeyboard->k_idleshifts;
- k->k_shiftmask |= k->k_togglemask;
- k->k_buckybits &= k->k_curkeyboard->k_idlebuckys;
- kbdcancelrpt(kbdd);
- kbdreleaseall(kbdd);
- break;
-
- case ERROR:
- cmn_err(CE_WARN, "kbd: Error detected");
- goto gotreset;
-
- case COMPOSE:
- k->k_state = COMPOSE1;
- kbdd->led_state |= LED_COMPOSE;
- kbdsetled(kbdd);
- break;
- /*
- * Remember when adding new entries that,
- * if they should NOT auto-repeat,
- * they should be put into the IF statement
- * just above this switch block.
- */
- default:
- goto badentry;
- }
- break;
-
- case FA_CLASS >> 8:
- if (k->k_state == NORMAL) {
- kbdd->fltaccent_entry = entry;
- k->k_state = FLTACCENT;
- }
- return;
-
- case STRING >> 8:
- cp = &keystringtab[entry & 0x0F][0];
- while (*cp != '\0') {
- switch (kbdd->kbdd_translate) {
-
- case TR_EVENT:
- kbd_send_esc_event(*cp, kbdd);
- break;
-
- case TR_ASCII:
- kbdputcode((uchar_t)*cp, q);
- break;
- }
- cp++;
- }
- break;
-
- case FUNCKEYS >> 8:
- switch (kbdd->kbdd_translate) {
-
- case TR_ASCII:
- bufp = buf;
- cp = strsetwithdecimal(bufp + 2,
- (uint_t)((entry & 0x003F) + 192),
- sizeof (buf) - 5);
- *bufp++ = '\033'; /* Escape */
- *bufp++ = '[';
- while (*cp != '\0')
- *bufp++ = *cp++;
- *bufp++ = 'z';
- *bufp = '\0';
- kbdputbuf(buf, q);
- break;
-
- case TR_EVENT:
- /*
- * Take advantage of the similar
- * ordering of kbd.h function keys and
- * vuid_event.h function keys to do a
- * simple translation to achieve a
- * mapping between the 2 different
- * address spaces.
- */
- fe.id = (entry & 0x003F) + KEY_LEFTFIRST;
- fe.value = 1;
- /*
- * Assume "up" table only generates
- * shift changes.
- */
- kbdkeypressed(kbdd, key, &fe, fe.id);
- /*
- * Function key events can be expanded
- * by terminal emulator software to
- * produce the standard escape sequence
- * generated by the TR_ASCII case above
- * if a function key event is not used
- * by terminal emulator software
- * directly.
- */
- break;
- }
- break;
-
- /*
- * Remember when adding new entries that,
- * if they should NOT auto-repeat,
- * they should be put into the IF statement
- * just above this switch block.
- */
- case PADKEYS >> 8:
- switch (kbdd->kbdd_translate) {
-
- case TR_ASCII:
- kbdputcode(kb_numlock_table[entry&0x1F], q);
- break;
-
- case TR_EVENT:
- /*
- * Take advantage of the similar
- * ordering of kbd.h keypad keys and
- * vuid_event.h keypad keys to do a
- * simple translation to achieve a
- * mapping between the 2 different
- * address spaces.
- */
- fe.id = (entry & 0x001F) + VKEY_FIRSTPAD;
- fe.value = 1;
- /*
- * Assume "up" table only generates
- * shift changes.
- */
- kbdkeypressed(kbdd, key, &fe, fe.id);
- /*
- * Keypad key events can be expanded
- * by terminal emulator software to
- * produce the standard ascii character
- * generated by the TR_ASCII case above
- * if a keypad key event is not used
- * by terminal emulator software
- * directly.
- */
- break;
- }
-
- badentry:
- break;
- }
-}
-
-static int
-kbd_do_compose(ushort_t first_entry, ushort_t second_entry,
- ushort_t *result_iso_ptr)
-{
- struct compose_sequence_t *ptr;
-
- ptr = &kb_compose_table[kb_compose_map[first_entry]];
- while (ptr->first == first_entry) {
- if (ptr->second == second_entry) {
- *result_iso_ptr = ptr->iso;
- return (1);
- }
- ptr++;
- }
- return (0);
-}
-
-static void
-kbd_send_esc_event(char c, register struct kbddata *kbdd)
-{
- Firm_event fe;
-
- fe.id = c;
- fe.value = 1;
- fe.pair_type = FE_PAIR_NONE;
- fe.pair = 0;
- /*
- * Pretend as if each cp pushed and released
- * Calling kbdqueueevent avoids addr translation
- * and pair base determination of kbdkeypressed.
- */
- kbdqueueevent(kbdd, &fe);
- fe.value = 0;
- kbdqueueevent(kbdd, &fe);
-}
-
-char *
-strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs)
-{
- int hradix = 5;
- char *bp;
- int lowbit;
- char *tab = "0123456789abcdef";
-
- bp = buf + maxdigs;
- *(--bp) = '\0';
- while (val) {
- lowbit = val & 1;
- val = (val >> 1);
- *(--bp) = tab[val % hradix * 2 + lowbit];
- val /= hradix;
- }
- return (bp);
-}
-
-static void
-kbdkeypressed(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe,
- ushort_t base)
-{
- register struct keyboardstate *k;
- register short id_addr;
-
- /* Set pair values */
- if (fe->id < (ushort_t)VKEY_FIRST) {
- /*
- * If CTRLed, find the ID that would have been used had it
- * not been CTRLed.
- */
- k = &kbdd->kbdd_state;
- if (k->k_shiftmask & (CTRLMASK | CTLSMASK)) {
- struct keymap *km;
-
- km = settable(kbdd,
- k->k_shiftmask & ~(CTRLMASK | CTLSMASK | UPMASK));
- if (km == NULL)
- return;
- base = km->keymap[key_station];
- }
- if (base != fe->id) {
- fe->pair_type = FE_PAIR_SET;
- fe->pair = base;
- goto send;
- }
- }
- fe->pair_type = FE_PAIR_NONE;
- fe->pair = 0;
-send:
- /* Adjust event id address for multiple keyboard/workstation support */
- switch (vuid_id_addr(fe->id)) {
- case ASCII_FIRST:
- id_addr = kbdd->kbdd_ascii_addr;
- break;
- case TOP_FIRST:
- id_addr = kbdd->kbdd_top_addr;
- break;
- case VKEY_FIRST:
- id_addr = kbdd->kbdd_vkey_addr;
- break;
- default:
- id_addr = vuid_id_addr(fe->id);
- }
- fe->id = vuid_id_offset(fe->id) | id_addr;
- kbdqueuepress(kbdd, key_station, fe);
-}
-
-static void
-kbdqueuepress(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe)
-{
- register struct key_event *ke, *ke_free;
- register int i;
-
- if (key_station == IDLEKEY)
- return;
-#ifdef KBD_DEBUG
- if (kbd_input_debug) printf("KBD PRESSED key=%d\n", key_station);
-#endif
- ke_free = 0;
- /* Scan table of down key stations */
- if (kbdd->kbdd_translate == TR_EVENT ||
- kbdd->kbdd_translate == TR_UNTRANS_EVENT) {
- for (i = 0, ke = kbdd->kbdd_downs;
- i < kbdd->kbdd_downs_entries;
- i++, ke++) {
- /* Keycode already down? */
- if (ke->key_station == key_station) {
-#ifdef KBD_DEBUG
- printf("kbd: Double entry in downs table (%d,%d)!\n", key_station, i);
-#endif
- goto add_event;
- }
- if (ke->key_station == 0)
- ke_free = ke;
- }
- if (ke_free) {
- ke = ke_free;
- goto add_event;
- }
- cmn_err(CE_WARN, "kbd: Too many keys down!");
- ke = kbdd->kbdd_downs;
- }
-add_event:
- ke->key_station = key_station;
- ke->event = *fe;
- kbdqueueevent(kbdd, fe);
-}
-
-static void
-kbdkeyreleased(register struct kbddata *kbdd, uchar_t key_station)
-{
- register struct key_event *ke;
- register int i;
-
- if (key_station == IDLEKEY)
- return;
-#ifdef KBD_DEBUG
- if (kbd_input_debug)
- printf("KBD RELEASE key=%d\n", key_station);
-#endif
- if (kbdd->kbdd_translate != TR_EVENT &&
- kbdd->kbdd_translate != TR_UNTRANS_EVENT)
- return;
- /* Scan table of down key stations */
- for (i = 0, ke = kbdd->kbdd_downs;
- i < kbdd->kbdd_downs_entries;
- i++, ke++) {
- /* Found? */
- if (ke->key_station == key_station) {
- ke->key_station = 0;
- ke->event.value = 0;
- kbdqueueevent(kbdd, &ke->event);
- }
- }
-
- /*
- * Ignore if couldn't find because may be called twice
- * for the same key station in the case of the kbdrpt
- * routine being called unnecessarily.
- */
-}
-
-static void
-kbdreleaseall(struct kbddata *kbdd)
-{
- register struct key_event *ke;
- register int i;
-
-#ifdef KBD_DEBUG
- if (kbd_debug && kbd_ra_debug) printf("KBD RELEASE ALL\n");
-#endif
- /* Scan table of down key stations */
- for (i = 0, ke = kbdd->kbdd_downs;
- i < kbdd->kbdd_downs_entries; i++, ke++) {
- /* Key station not zero */
- if (ke->key_station)
- kbdkeyreleased(kbdd, ke->key_station);
- /* kbdkeyreleased resets kbdd_downs entry */
- }
-}
-
-/*
- * Pass a keycode up the stream, if you can, otherwise throw it away.
- */
-static void
-kbdputcode(uint_t code, queue_t *q)
-{
- register mblk_t *bp;
-
- if (!canput(q))
- cmn_err(CE_WARN, "kbdputcode: Can't put block for keycode");
- else {
- if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL)
- cmn_err(CE_WARN,
- "kbdputcode: Can't allocate block for keycode");
- else {
- *bp->b_wptr++ = code;
- putnext(q, bp);
- }
- }
-}
-
-/*
- * Pass generated keycode sequence to upstream, if possible.
- */
-static void
-kbdputbuf(char *buf, queue_t *q)
-{
- register mblk_t *bp;
-
- if (!canput(q))
- cmn_err(CE_WARN, "kbdputbuf: Can't put block for keycode");
- else {
- if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL)
- cmn_err(CE_WARN,
- "kbdputbuf: Can't allocate block for keycode");
- else {
- while (*buf) {
- *bp->b_wptr++ = *buf;
- buf++;
- }
- putnext(q, bp);
- }
- }
-}
-
-/*
- * Pass a VUID "firm event" up the stream, if you can.
- */
-static void
-kbdqueueevent(struct kbddata *kbdd, Firm_event *fe)
-{
- register queue_t *q;
- register mblk_t *bp;
-
- if ((q = kbdd->kbdd_readq) == NULL)
- return;
- if (!canput(q)) {
- if (kbd_overflow_msg)
- cmn_err(CE_WARN,
- "kbd: Buffer flushed when overflowed");
- kbdflush(kbdd);
- kbd_overflow_cnt++;
- } else {
- if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL)
- cmn_err(CE_WARN,
- "kbdqueueevent: Can't allocate block for event");
- else {
-#if 1 /* XX64 */
- struct timeval now;
-
- /*
- * XX64: This is something of a compromise. It
- * seems justifiable based on the usage of these
- * timestamps as an ordering relation as opposed
- * to a strict timing thing.
- *
- * But should we restore Firm_event's time stamp
- * to be a timeval, and send 32-bit and 64-bit
- * events up the pipe?
- */
- uniqtime(&now);
- TIMEVAL_TO_TIMEVAL32(&fe->time, &now);
-#else
- uniqtime(&fe->time);
-#endif
- *(Firm_event *)bp->b_wptr = *fe;
- bp->b_wptr += sizeof (Firm_event);
- putnext(q, bp);
- }
- }
-}