kbd.c revision b05bac8e3171690365f0d91f592439932999c312
/*
* 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
* 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 */
/*
* ASCII or event format.
*/
#include <sys/sysmacros.h>
#include <sys/vuid_event.h>
"kb",
&kbd_info,
};
/*
* Module linkage information for the kernel.
*/
static struct modlstrmod modlstrmod = {
};
static struct modlinkage modlinkage = {
};
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}
int
{
}
/*
* 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 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 {
} Key_event;
struct kbddata {
int kbdd_flags; /* random flags */
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 */
char led_state; /* current state of LEDs */
unsigned char shiftkey; /* used for the new abort keys */
};
#define NO_HARD_RESET 0 /* don't 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 */
#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 struct module_info kbdmiinfo = {
0,
"kb",
0,
2048,
128
};
(int (*)())kbdrput,
(int (*)())NULL,
(int (*)())NULL,
};
static struct module_info kbdmoinfo = {
0,
"kb",
0,
2048,
128
};
(int (*)())kbdwput,
(int (*)())NULL,
(int (*)())NULL,
};
&kbdrinit,
&kbdwinit,
NULL,
NULL,
};
static void kbdreioctl(void *);
static void kbdlayouttimeout(void *);
static void kbdrpt(void *);
static void kbdcancelrpt(struct kbddata *);
static void kbd_send_esc_event(char, struct kbddata *);
ushort_t);
static void kbdreleaseall(struct kbddata *);
/*
* 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
* 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
{
register int error;
/* Set these up only once so that they could be changed from adb */
if (!kbd_repeatrate) {
}
return (0); /* already attached */
/*
* Only allow open requests to succeed for privileged users. This
* necessary to prevent users from pushing the "kb" module again
*/
if (secpolicy_console(crp) != 0) {
return (EPERM);
}
switch (sflag) {
case MODOPEN:
break;
case CLONEOPEN:
return (EINVAL); /* No Bozos! */
}
/* allocate keyboard */
/*
* Set up queue pointers, so that the "put" procedure will accept
* the reply to the "ioctl" message we send down.
*/
qprocson(q);
/*
* Setup tty modes.
*/
if (!qwait_sig(q)) {
qunbufcall(q, id);
qprocsoff(q);
return (EINTR);
}
}
NULL) {
if (!qwait_sig(q)) {
qunbufcall(q, id);
qprocsoff(q);
return (EINTR);
}
}
/*
* Now wait for it. Let our read queue put routine wake us up
* when it arrives.
*/
if (!qwait_sig(q)) {
goto error;
}
}
goto error;
/*
* Set up private data.
*/
kbdd->kbdd_readq = q;
/* Allocate dynamic memory for downs table */
/*
* Reset kbd.
*/
return (0);
qprocsoff(q);
return (error);
}
/*
* Close a keyboard.
*/
/* ARGSUSED1 */
static int
{
qprocsoff(q);
/*
* 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;
/*
* There was a KIOCLAYOUT pending; presumably, it timed out.
* Throw the reply away.
*/
}
/* clear all timeouts */
if (kbdd->kbdd_bufcallid)
if (kbdd->kbdd_rptid)
if (kbdd->kbdd_layoutid)
return (0);
}
/*
* Line discipline output queue put procedure: handles M_IOCTL
* messages.
*/
static void
{
/*
* Process M_FLUSH, and some M_IOCTL, messages here; pass
* everything else down.
*/
case M_FLUSH:
default:
break;
case M_IOCTL:
break;
}
}
static void
kbdreioctl(void *kbdd_addr)
{
queue_t *q;
kbdd->kbdd_bufcallid = 0;
q = kbdd->kbdd_writeq;
}
}
static void
{
register short new_translate;
register Vuid_addr_probe *addr_probe;
register short *addr_ptr;
int err = 0;
case VUIDSFORMAT:
if (err != 0)
break;
break;
goto output_format_change;
case KIOCTRANS:
if (err != 0)
break;
break;
goto output_format_change;
case KIOCCMD:
if (err != 0)
break;
break;
case KIOCSLED:
if (err != 0)
break;
break;
case KIOCGLED:
ioctlrespsize = sizeof (int);
goto allocfailure;
}
break;
case VUIDGFORMAT:
ioctlrespsize = sizeof (int);
goto allocfailure;
}
break;
case KIOCGTRANS:
ioctlrespsize = sizeof (int);
goto allocfailure;
}
break;
case VUIDSADDR:
if (err != 0)
break;
switch (addr_probe->base) {
case ASCII_FIRST:
break;
case TOP_FIRST:
break;
case VKEY_FIRST:
break;
default:
}
goto output_format_change;
}
break;
case VUIDGADDR:
if (err != 0)
break;
switch (addr_probe->base) {
case ASCII_FIRST:
break;
case TOP_FIRST:
break;
case VKEY_FIRST:
break;
default:
}
break;
case KIOCTRANSABLE:
if (err != 0)
break;
goto output_format_change;
}
break;
case KIOCGTRANSABLE:
ioctlrespsize = sizeof (int);
goto allocfailure;
}
break;
case KIOCSCOMPAT:
if (err != 0)
break;
break;
case KIOCGCOMPAT:
ioctlrespsize = sizeof (int);
goto allocfailure;
}
break;
case KIOCSETKEY:
if (err != 0)
break;
/*
* 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:
if (err != 0)
break;
break;
case KIOCSKEY:
if (err != 0)
break;
/*
* 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:
if (err != 0)
break;
break;
case KIOCSDIRECT:
goto output_format_change;
case KIOCGDIRECT:
ioctlrespsize = sizeof (int);
goto allocfailure;
}
break;
case KIOCTYPE:
ioctlrespsize = sizeof (int);
goto allocfailure;
}
break;
case KIOCLAYOUT:
/*
* There was an earlier KIOCLAYOUT pending; presumably,
* it timed out. Throw the reply away.
*/
}
ioctlrespsize = sizeof (int);
goto allocfailure;
}
kbdcmd(q, (char)KBD_CMD_GETLAYOUT);
if (kbdd->kbdd_layoutid)
return; /* wait for reply from keyboard */
} else {
/*
* Not a Type 4 keyboard; return an immediate error.
*/
break;
}
case KIOCGRPTDELAY:
/*
* Report the autorepeat delay, unit in millisecond
*/
ioctlrespsize = sizeof (int);
goto allocfailure;
}
/* free msg to prevent memory leak */
break;
case KIOCSRPTDELAY:
/*
* Set the autorepeat delay
*/
if (err != 0)
break;
/* validate the input */
break;
}
if (kbd_repeatdelay <= 0)
kbd_repeatdelay = 1;
break;
case KIOCGRPTRATE:
/*
* Report the autorepeat rate
*/
ioctlrespsize = sizeof (int);
goto allocfailure;
}
/* free msg to prevent memory leak */
break;
case KIOCSRPTRATE:
/*
* Set the autorepeat rate
*/
if (err != 0)
break;
/* validate the input */
break;
}
if (kbd_repeatrate <= 0)
kbd_repeatrate = 1;
break;
default:
return;
}
goto done;
done:
if (err != 0) {
} else {
}
return;
/*
* 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_bufcallid)
kbdreioctl, kbdd);
}
static void
{
register queue_t *q;
/* Flush pending data already sent upstream */
/* Flush pending ups */
}
/*
* Pass keycode upstream, either translated or untranslated.
*/
static void
{
#ifdef KBD_DEBUG
#endif
return;
if (!kbdd->kbdd_translatable ||
else
}
/*
* 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
{
if (canput(q)) {
"kbdcmd: Can't allocate block for command");
else {
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
{
}
}
/*
* Reset the keyboard
*/
static void
{
register struct keyboardstate *k;
k = &kbdd->kbdd_state;
if (kbdd->kbdd_translatable) {
k->k_id = -1;
if (hard_reset)
} else {
bzero(k, sizeof (struct keyboardstate));
}
}
/*
* 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[] = {
};
/*
* Set individual keystation translation from old-style entry.
* TODO: Have each keyboard own own translation tables.
*/
static int
{
int strtabindex, i;
register int tablemask;
return (EINVAL);
return (EINVAL);
if (tablemask == KIOCABORT1) {
if (secpolicy_console(cr) != 0)
return (EPERM);
return (0);
}
if (tablemask == KIOCABORT2) {
if (secpolicy_console(cr) != 0)
return (EPERM);
return (0);
}
if ((tablemask & ALTGRAPHMASK) ||
return (EINVAL);
for (i = 0; i < KTAB_STRLEN; i++)
}
/*
* There's nothing we need do with OLD_ISOCHAR.
*/
if (entry != OLD_ISOCHAR) {
if (entry & 0x80) {
else
entry =
+ (entry & 0x0F);
}
}
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
{
int strtabindex, i;
return (EINVAL);
return (EINVAL);
return (0);
}
return (0);
}
return (EINVAL);
if (entry & 0xFF00)
+ (entry & 0x00FF);
else {
if (entry & 0x80)
else
}
for (i = 0; i < KTAB_STRLEN; i++)
}
return (0);
}
/*
* Set individual keystation translation from new-style entry.
* TODO: Have each keyboard own own translation tables.
*/
static int
{
int strtabindex, i;
return (EINVAL);
return (EINVAL);
if (secpolicy_console(cr) != 0)
return (EPERM);
return (0);
}
if (secpolicy_console(cr) != 0)
return (EPERM);
return (0);
}
return (EINVAL);
for (i = 0; i < KTAB_STRLEN; i++)
}
return (0);
}
/*
* Get individual keystation translation as new-style entry.
*/
static int
{
int strtabindex, i;
return (EINVAL);
return (EINVAL);
return (0);
}
return (0);
}
return (EINVAL);
for (i = 0; i < KTAB_STRLEN; i++)
}
return (0);
}
static void
kbdlayouttimeout(void *arg)
{
kbdd->kbdd_layoutid = 0;
/*
* Timed out waiting for reply to "get keyboard layout" command.
* Return an ETIME error.
*/
}
}
/*
* Put procedure for input from driver end of stream (read queue).
*/
static void
{
if (kbdd == 0) {
return;
}
case M_FLUSH:
default:
return;
case M_BREAK:
/*
* Will get M_BREAK only if this is not the system
* keyboard, otherwise serial port will eat break
*/
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.
*/
/*
* This isn't the reply we're looking for. Move along.
*/
else
} else {
}
return;
case M_DATA:
return;
}
break;
}
/*
* A data message, consisting of bytes from the keyboard.
* Ram them through our state machine.
*/
do {
}
/*
* A keypress was received. Process it through the state machine
* to check for aborts.
*/
static void
{
register struct keyboardstate *k;
k = &kbdd->kbdd_state;
#ifdef KBD_DEBUG
if (kbd_input_debug)
#endif
switch (k->k_idstate) {
case KID_NONE:
k->k_idstate = KID_GOT_PREFACE;
} else {
/* allows hot plug of kbd after booting without kbd */
}
return;
case KID_GOT_PREFACE:
/*
* 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:
break;
case 1:
break;
case -1:
default:
{
char wrkbuf[8];
int len;
len = 7;
ddi_root_node(), 0, "keyboard-click?",
}
}
}
break;
}
/*
* A keyboard reset clears the LEDs.
* Restore the LEDs from the last value we set
* them to.
*/
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:
return;
/*
* we want to check for ID only if we are in
* translatable mode.
*/
case RESETKEY:
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:
break;
#endif
#if defined(KBD_RELEASED_PREFIX)
case KID_GOT_RELEASED:
break;
#endif
case KID_GOT_LAYOUT:
if (kbdd->kbdd_layoutid)
}
return;
}
switch (k->k_state) {
#if defined(__sparc)
/* FALLTHRU */
#endif
case NORMAL:
#if defined(__sparc)
if (k->k_curkeyboard) {
break;
}
}
}
#endif
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.
*/
DELAY(100000);
abort_sequence_enter((char *)NULL);
return;
} else {
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.
*/
DELAY(100000);
abort_sequence_enter((char *)NULL);
return;
} else {
goto normalstate;
}
}
break;
#endif
case COMPOSE1:
case COMPOSE2:
case FLTACCENT:
break;
}
}
static void
{
register struct keyboardstate *k;
int i;
k = &kbdd->kbdd_state;
k->k_shiftmask = 0;
k->k_buckybits = 0;
/*
* Reset k_rptkey to IDLEKEY. We need to cancel
* the autorepeat feature, if any.
*/
if (kbdd->kbdd_rptid)
kbdd->kbdd_rptid = 0;
}
k->k_curkeyboard = NULL;
break;
}
}
if (!k->k_curkeyboard) {
"Type %d assumed", k->k_id);
}
}
/*
* This routine determines which table we should look in to decode
* the current keycode.
*/
static struct keymap *
{
return (NULL);
if (mask & NUMLOCKMASK)
if (mask & ALTGRAPHMASK)
return (kp->k_altgraph);
}
static void
{
struct keyboardstate *k;
k = &kbdd->kbdd_state;
#ifdef KBD_DEBUG
if (kbd_rpt_debug)
#endif
kbdd->kbdd_rptid = 0;
}
}
static void
{
register struct keyboardstate *k;
k = &kbdd->kbdd_state;
if (kbdd->kbdd_rptid)
kbdd->kbdd_rptid = 0;
}
}
static void
{
register unsigned newstate;
unsigned shiftmask;
register struct keyboardstate *k;
int i, ret_val;
char buf[14];
k = &kbdd->kbdd_state;
#ifdef KBD_DEBUG
if (kbd_input_debug) {
printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n",
}
#endif
} else {
}
return;
}
shiftmask = k->k_shiftmask;
return;
}
if (key >= KEYMAP_SIZE)
return;
/*
* 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.
*/
return;
}
}
/*
* Handle the state of toggle shifts specially.
* Ups should be ignored, and downs should be mapped to ups if
* that shift is currently on.
*/
} else {
}
}
} else {
/*
* Handle Compose and floating accent key sequences
*/
return;
if (entry < ASCII_SET_SIZE) {
if (kb_compose_map[entry] >= 0) {
return;
}
}
return;
return;
if (entry < ASCII_SET_SIZE) {
if (kb_compose_map[entry] >= 0) {
&result_iso);
} else {
&result_iso);
}
if (ret_val == 1) {
if (kbdd->kbdd_translate ==
TR_EVENT) {
(kbdd->kbdd_compat ?
+ result_iso;
kbdd,
&fe);
} else if (
kbdd->kbdd_translate ==
q);
}
}
}
return;
return;
for (i = 0;
!= kbdd->fltaccent_entry) ||
i++) {
if (kb_fltaccent_table[i].fa_entry == 0)
/* Invalid second key: ignore key */
return;
}
+ kb_fltaccent_table[i].iso;
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.
*/
}
/*
* 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:
break;
case TR_ASCII:
break;
}
break;
case SHIFTKEYS >> 8: {
/* Modify toggle state (see toggle processing above) */
} else if (shiftbit == NUMLOCKMASK) {
}
k->k_togglemask &= ~shiftbit;
} else {
} else if (shiftbit == NUMLOCKMASK) {
}
k->k_togglemask |= shiftbit;
}
}
k->k_shiftmask &= ~shiftbit;
else
k->k_shiftmask |= shiftbit;
/*
* 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.
*/
}
break;
}
case BUCKYBITS >> 8:
/*
* 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.
*/
}
break;
case FUNNY >> 8:
switch (entry) {
case NOP:
break;
case IDLE:
/* Fall thru into RESET code */
/* FALLTHRU */
case RESET:
k->k_shiftmask |= k->k_togglemask;
break;
case ERROR:
goto gotreset;
case COMPOSE:
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:
}
return;
case STRING >> 8:
while (*cp != '\0') {
switch (kbdd->kbdd_translate) {
case TR_EVENT:
break;
case TR_ASCII:
break;
}
cp++;
}
break;
case FUNCKEYS >> 8:
switch (kbdd->kbdd_translate) {
case TR_ASCII:
sizeof (buf) - 5);
*bufp++ = '[';
while (*cp != '\0')
*bufp++ = 'z';
*bufp = '\0';
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.
*/
/*
* Assume "up" table only generates
* shift changes.
*/
/*
* 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:
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.
*/
/*
* Assume "up" table only generates
* shift changes.
*/
/*
* 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;
}
break;
}
}
static int
{
struct compose_sequence_t *ptr;
return (1);
}
ptr++;
}
return (0);
}
static void
{
/*
* Pretend as if each cp pushed and released
* Calling kbdqueueevent avoids addr translation
* and pair base determination of kbdkeypressed.
*/
}
char *
{
int hradix = 5;
char *bp;
int lowbit;
char *tab = "0123456789abcdef";
*(--bp) = '\0';
while (val) {
}
return (bp);
}
static void
{
register struct keyboardstate *k;
register short id_addr;
/* Set pair values */
/*
* If CTRLed, find the ID that would have been used had it
* not been CTRLed.
*/
k = &kbdd->kbdd_state;
return;
}
goto send;
}
}
send:
/* Adjust event id address for multiple keyboard/workstation support */
case ASCII_FIRST:
break;
case TOP_FIRST:
break;
case VKEY_FIRST:
break;
default:
}
}
static void
{
register int i;
if (key_station == IDLEKEY)
return;
#ifdef KBD_DEBUG
#endif
ke_free = 0;
/* Scan table of down key stations */
i < kbdd->kbdd_downs_entries;
i++, ke++) {
/* Keycode already down? */
#ifdef KBD_DEBUG
#endif
goto add_event;
}
if (ke->key_station == 0)
}
if (ke_free) {
goto add_event;
}
}
}
static void
{
register int i;
if (key_station == IDLEKEY)
return;
#ifdef KBD_DEBUG
if (kbd_input_debug)
#endif
return;
/* Scan table of down key stations */
i < kbdd->kbdd_downs_entries;
i++, ke++) {
/* Found? */
ke->key_station = 0;
}
}
/*
* 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
{
register int i;
#ifdef KBD_DEBUG
#endif
/* Scan table of down key stations */
/* Key station not zero */
if (ke->key_station)
/* kbdkeyreleased resets kbdd_downs entry */
}
}
/*
* Pass a keycode up the stream, if you can, otherwise throw it away.
*/
static void
{
if (!canput(q))
else {
"kbdputcode: Can't allocate block for keycode");
else {
}
}
}
/*
* Pass generated keycode sequence to upstream, if possible.
*/
static void
{
if (!canput(q))
else {
"kbdputbuf: Can't allocate block for keycode");
else {
while (*buf) {
buf++;
}
}
}
}
/*
* Pass a VUID "firm event" up the stream, if you can.
*/
static void
{
register queue_t *q;
return;
if (!canput(q)) {
if (kbd_overflow_msg)
"kbd: Buffer flushed when overflowed");
} else {
"kbdqueueevent: Can't allocate block for event");
else {
#if 1 /* XX64 */
/*
* 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?
*/
#else
#endif
}
}
}