03dcce7f3d
1) Dell Latitude XPi This laptop has a strange, IMHO broken :-), keyboard controller which wouldn't disable the keyboard interrupt. The kludge is to disable tty intr. during set_keyboard(), used for changing LED and setting typematic. The patch also changes the function name: set_keyboard() -> set_keyboard_param() Although it is a static function, the name corrides with a routine in `syscons' and is confusing when debugging the kernel which has both `syscons' and `pcvt' with DDB. (Suggested by Bruce) 2) doreset() bug doreset() failed to preserve some bits in the keyboard controller's command byte during keyboard reset. This bug may put some keyboard controllers in old motherboards (386 and 486) in a strange state, resulting in complete keyboard lockup or random key input. Reviewed by: Joerg
3317 lines
81 KiB
C
3317 lines
81 KiB
C
/*
|
|
* Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
|
|
*
|
|
* Copyright (c) 1992, 1993 Brian Dunford-Shore and Holger Veit.
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to Berkeley by
|
|
* William Jolitz and Don Ahn.
|
|
*
|
|
* This code is derived from software contributed to 386BSD by
|
|
* Holger Veit.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Hellmuth Michaelis,
|
|
* Brian Dunford-Shore and Joerg Wunsch.
|
|
* 4. The name authors may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*
|
|
* @(#)pcvt_kbd.c, 3.20, Last Edit-Date: [Sun Apr 2 18:59:04 1995]
|
|
*
|
|
*/
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
*
|
|
* pcvt_kbd.c VT220 Driver Keyboard Interface Code
|
|
* ----------------------------------------------------
|
|
* -hm ------------ Release 3.00 --------------
|
|
* -hm integrating NetBSD-current patches
|
|
* -jw introduced kbd_emulate_pc() if scanset > 1
|
|
* -hm patch from joerg for timeout in kbd_emulate_pc()
|
|
* -hm starting to implement alt-shift/ctrl key mappings
|
|
* -hm Gateway 2000 Keyboard fix from Brian Moore
|
|
* -hm some #if adjusting for NetBSD 0.9
|
|
* -hm split off pcvt_kbd.h
|
|
* -hm applying Joerg's patches for FreeBSD 2.0
|
|
* -hm patch from Martin, PCVT_NO_LED_UPDATE
|
|
* -hm PCVT_VT220KEYB patches from Lon Willet
|
|
* -hm PR #399, patch from Bill Sommerfeld: Return with PCVT_META_ESC
|
|
* -hm allow keyboard-less kernel boot for serial consoles and such ..
|
|
* -hm patch from Lon Willett for led-update and showkey()
|
|
* -hm patch from Lon Willett to fix mapping of Control-R scancode
|
|
* -hm delay patch from Martin Husemann after port-i386 ml-discussion
|
|
* -hm added PCVT_NONRESP_KEYB_TRY definition to doreset()
|
|
*
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
#include "vt.h"
|
|
#include "opt_ddb.h"
|
|
|
|
#if NVT > 0
|
|
|
|
#include <i386/isa/pcvt/pcvt_hdr.h> /* global include */
|
|
|
|
#define LEDSTATE_UPDATE_PENDING (1 << 3)
|
|
|
|
static void fkey1(void), fkey2(void), fkey3(void), fkey4(void);
|
|
static void fkey5(void), fkey6(void), fkey7(void), fkey8(void);
|
|
static void fkey9(void), fkey10(void), fkey11(void), fkey12(void);
|
|
|
|
static void sfkey1(void), sfkey2(void), sfkey3(void), sfkey4(void);
|
|
static void sfkey5(void), sfkey6(void), sfkey7(void), sfkey8(void);
|
|
static void sfkey9(void), sfkey10(void), sfkey11(void), sfkey12(void);
|
|
|
|
static void cfkey1(void), cfkey2(void), cfkey3(void), cfkey4(void);
|
|
static void cfkey5(void), cfkey6(void), cfkey7(void), cfkey8(void);
|
|
static void cfkey9(void), cfkey10(void), cfkey11(void), cfkey12(void);
|
|
|
|
static void doreset ( void );
|
|
static void ovlinit ( int force );
|
|
static void settpmrate ( int rate );
|
|
static void setlockkeys ( int snc );
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
static int kbc_8042cmd ( int val );
|
|
#else
|
|
static int set_keyboard_param( int command, int data );
|
|
#endif /* !_I386_ISA_KBDIO_H_ */
|
|
static int getokeydef ( unsigned key, struct kbd_ovlkey *thisdef );
|
|
static int getckeydef ( unsigned key, struct kbd_ovlkey *thisdef );
|
|
static int rmkeydef ( int key );
|
|
static int setkeydef ( struct kbd_ovlkey *data );
|
|
static u_char * xlatkey2ascii( U_short key );
|
|
|
|
static int ledstate = LEDSTATE_UPDATE_PENDING; /* keyboard led's */
|
|
static int tpmrate = KBD_TPD500|KBD_TPM100;
|
|
static u_char altkpflag = 0;
|
|
static u_short altkpval = 0;
|
|
|
|
#if PCVT_SHOWKEYS
|
|
u_char rawkeybuf[80];
|
|
#endif
|
|
|
|
#include <i386/isa/pcvt/pcvt_kbd.h> /* tables etc */
|
|
|
|
#if PCVT_SHOWKEYS
|
|
/*---------------------------------------------------------------------------*
|
|
* keyboard debugging: put kbd communication char into some buffer
|
|
*---------------------------------------------------------------------------*/
|
|
static void showkey (char delim, u_char val)
|
|
{
|
|
int rki;
|
|
|
|
for(rki = 3; rki < 80; rki++) /* shift left buffer */
|
|
rawkeybuf[rki-3] = rawkeybuf[rki];
|
|
|
|
rawkeybuf[77] = delim; /* delimiter */
|
|
|
|
rki = (val & 0xf0) >> 4; /* ms nibble */
|
|
|
|
if(rki <= 9)
|
|
rki = rki + '0';
|
|
else
|
|
rki = rki - 10 + 'A';
|
|
|
|
rawkeybuf[78] = rki;
|
|
|
|
rki = val & 0x0f; /* ls nibble */
|
|
|
|
if(rki <= 9)
|
|
rki = rki + '0';
|
|
else
|
|
rki = rki - 10 + 'A';
|
|
|
|
rawkeybuf[79] = rki;
|
|
}
|
|
#endif /* PCVT_SHOWKEYS */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function to switch to another virtual screen
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
do_vgapage(int page)
|
|
{
|
|
if(critical_scroll) /* executing critical region ? */
|
|
switch_page = page; /* yes, auto switch later */
|
|
else
|
|
vgapage(page); /* no, switch now */
|
|
}
|
|
|
|
|
|
/*
|
|
* This code from Lon Willett enclosed in #if PCVT_UPDLED_LOSES_INTR is
|
|
* abled because it crashes FreeBSD 1.1.5.1 at boot time.
|
|
* The cause is obviously that the timeout queue is not yet initialized
|
|
* timeout is called from here the first time.
|
|
* Anyway it is a pointer in the right direction so it is included for
|
|
* reference here.
|
|
*/
|
|
|
|
#define PCVT_UPDLED_LOSES_INTR 0 /* disabled for now */
|
|
|
|
#if PCVT_UPDLED_LOSES_INTR || defined(_I386_ISA_KBDIO_H_)
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* check for lost keyboard interrupts
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
/*
|
|
* The two commands to change the LEDs generate two KEYB_R_ACK responses
|
|
* from the keyboard, which aren't explicitly checked for (maybe they
|
|
* should be?). However, when a lot of other I/O is happening, one of
|
|
* the interrupts sometimes gets lost (I'm not sure of the details of
|
|
* how and why and what hardware this happens with).
|
|
*
|
|
* This may have had something to do with spltty() previously not being
|
|
* called before the kbd_cmd() calls in update_led().
|
|
*
|
|
* This is a real problem, because normally the keyboard is only polled
|
|
* by pcrint(), and no more interrupts will be generated until the ACK
|
|
* has been read. So the keyboard is hung. This code polls a little
|
|
* while after changing the LEDs to make sure that this hasn't happened.
|
|
*
|
|
* XXX Quite possibly we should poll the kbd on a regular basis anyway,
|
|
* in the interest of robustness. It may be possible that interrupts
|
|
* get lost other times as well.
|
|
*/
|
|
|
|
static int lost_intr_timeout_queued = 0;
|
|
|
|
static void
|
|
check_for_lost_intr (void *arg)
|
|
{
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
lost_intr_timeout_queued = 0;
|
|
if (inb(CONTROLLER_CTRL) & STATUS_OUTPBF)
|
|
{
|
|
int opri = spltty ();
|
|
pcrint ();
|
|
splx (opri);
|
|
}
|
|
#else
|
|
int opri;
|
|
|
|
lost_intr_timeout_queued = 0;
|
|
if (kbdc_lock(kbdc, TRUE)) {
|
|
opri = spltty ();
|
|
kbdc_lock(kbdc, FALSE);
|
|
if (kbdc_data_ready(kbdc))
|
|
pcrint (0);
|
|
splx (opri);
|
|
}
|
|
timeout(check_for_lost_intr, (void *)NULL, hz);
|
|
lost_intr_timeout_queued = 1;
|
|
#endif /* !_I386_ISA_KBDIO_H_ */
|
|
}
|
|
|
|
#endif /* PCVT_UPDLED_LOSES_INTR || defined(_I386_ISA_KBDIO_H_) */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* update keyboard led's
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
update_led(void)
|
|
{
|
|
#if !PCVT_NO_LED_UPDATE
|
|
|
|
/* Don't update LED's unless necessary. */
|
|
|
|
int opri, new_ledstate, response1, response2;
|
|
|
|
opri = spltty();
|
|
new_ledstate = (vsp->scroll_lock) |
|
|
(vsp->num_lock * 2) |
|
|
(vsp->caps_lock * 4);
|
|
|
|
if (new_ledstate != ledstate)
|
|
{
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
|
|
ledstate = LEDSTATE_UPDATE_PENDING;
|
|
|
|
if(kbd_cmd(KEYB_C_LEDS) != 0)
|
|
{
|
|
printf("Keyboard LED command timeout\n");
|
|
splx(opri);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* For some keyboards or keyboard controllers, it is an
|
|
* error to issue a command without waiting long enough
|
|
* for an ACK for the previous command. The keyboard
|
|
* gets confused, and responds with KEYB_R_RESEND, but
|
|
* we ignore that. Wait for the ACK here. The busy
|
|
* waiting doesn't matter much, since we lose anyway by
|
|
* busy waiting to send the command.
|
|
*
|
|
* XXX actually wait for any response, since we can't
|
|
* handle normal scancodes here.
|
|
*
|
|
* XXX all this should be interrupt driven. Issue only
|
|
* one command at a time wait for a ACK before proceeding.
|
|
* Retry after a timeout or on receipt of a KEYB_R_RESEND.
|
|
* KEYB_R_RESENDs seem to be guaranteed by working
|
|
* keyboard controllers with broken (or disconnected)
|
|
* keyboards. There is another code for keyboard
|
|
* reconnects. The keyboard hardware is very simple and
|
|
* well designed :-).
|
|
*/
|
|
response1 = kbd_response();
|
|
|
|
if(kbd_cmd(new_ledstate) != 0) {
|
|
printf("Keyboard LED data timeout\n");
|
|
splx(opri);
|
|
return;
|
|
}
|
|
response2 = kbd_response();
|
|
|
|
if (response1 == KEYB_R_ACK && response2 == KEYB_R_ACK)
|
|
ledstate = new_ledstate;
|
|
else
|
|
printf(
|
|
"Keyboard LED command not ACKed (responses %#x %#x)\n",
|
|
response1, response2);
|
|
#else /* _I386_ISA_KBDIO_H_ */
|
|
|
|
if (kbdc == NULL) {
|
|
ledstate = new_ledstate;
|
|
splx(opri);
|
|
} else {
|
|
ledstate = LEDSTATE_UPDATE_PENDING;
|
|
splx(opri);
|
|
if (set_keyboard_param(KBDC_SET_LEDS, new_ledstate) == 0)
|
|
ledstate = new_ledstate;
|
|
}
|
|
|
|
#endif /* !_I386_ISA_KBDIO_H_ */
|
|
|
|
#if PCVT_UPDLED_LOSES_INTR
|
|
if (lost_intr_timeout_queued)
|
|
untimeout (check_for_lost_intr, (void *)NULL);
|
|
|
|
timeout (check_for_lost_intr, (void *)NULL, hz);
|
|
lost_intr_timeout_queued = 1;
|
|
#endif /* PCVT_UPDLED_LOSES_INTR */
|
|
|
|
}
|
|
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
splx(opri);
|
|
#endif
|
|
|
|
#endif /* !PCVT_NO_LED_UPDATE */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* set typematic rate
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
settpmrate(int rate)
|
|
{
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
tpmrate = rate & 0x7f;
|
|
if(kbd_cmd(KEYB_C_TYPEM) != 0)
|
|
printf("Keyboard TYPEMATIC command timeout\n");
|
|
else if(kbd_cmd(tpmrate) != 0)
|
|
printf("Keyboard TYPEMATIC data timeout\n");
|
|
#else
|
|
tpmrate = rate & 0x7f;
|
|
if (set_keyboard_param(KBDC_SET_TYPEMATIC, tpmrate) != 0)
|
|
printf("pcvt: failed to set keyboard TYPEMATIC.\n");
|
|
#endif /* !_I386_ISA_KBDIO_H_ */
|
|
}
|
|
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
/*---------------------------------------------------------------------------*
|
|
* Pass command to keyboard controller (8042)
|
|
*---------------------------------------------------------------------------*/
|
|
static int
|
|
kbc_8042cmd(int val)
|
|
{
|
|
unsigned timeo;
|
|
|
|
timeo = 100000; /* > 100 msec */
|
|
while (inb(CONTROLLER_CTRL) & STATUS_INPBF)
|
|
if (--timeo == 0)
|
|
return (-1);
|
|
outb(CONTROLLER_CTRL, val);
|
|
return (0);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Pass command to keyboard itself
|
|
*---------------------------------------------------------------------------*/
|
|
int
|
|
kbd_cmd(int val)
|
|
{
|
|
unsigned timeo;
|
|
|
|
timeo = 100000; /* > 100 msec */
|
|
while (inb(CONTROLLER_CTRL) & STATUS_INPBF)
|
|
if (--timeo == 0)
|
|
return (-1);
|
|
outb(CONTROLLER_DATA, val);
|
|
|
|
#if PCVT_SHOWKEYS
|
|
showkey ('>', val);
|
|
#endif /* PCVT_SHOWKEYS */
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Read response from keyboard
|
|
* NB: make sure to call spltty() before kbd_cmd(), kbd_response().
|
|
*---------------------------------------------------------------------------*/
|
|
int
|
|
kbd_response(void)
|
|
{
|
|
u_char ch;
|
|
unsigned timeo;
|
|
|
|
timeo = 500000; /* > 500 msec (KEYB_R_SELFOK requires 87) */
|
|
while (!(inb(CONTROLLER_CTRL) & STATUS_OUTPBF))
|
|
if (--timeo == 0)
|
|
return (-1);
|
|
|
|
PCVT_KBD_DELAY(); /* 7 us delay */
|
|
ch = inb(CONTROLLER_DATA);
|
|
|
|
#if PCVT_SHOWKEYS
|
|
showkey ('<', ch);
|
|
#endif /* PCVT_SHOWKEYS */
|
|
|
|
return ch;
|
|
}
|
|
#else
|
|
static int
|
|
set_keyboard_param(int command, int data)
|
|
{
|
|
int s;
|
|
int c;
|
|
|
|
if (kbdc == NULL)
|
|
return 1;
|
|
|
|
/* prevent the timeout routine from polling the keyboard */
|
|
if (!kbdc_lock(kbdc, TRUE))
|
|
return 1;
|
|
|
|
/* disable the keyboard and mouse interrupt */
|
|
s = spltty();
|
|
#if 0
|
|
c = get_controller_command_byte(kbdc);
|
|
if ((c == -1)
|
|
|| !set_controller_command_byte(kbdc,
|
|
kbdc_get_device_mask(kbdc),
|
|
KBD_DISBLE_KBD_PORT | KBD_DISABLE_KBD_INT
|
|
| KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
|
|
/* CONTROLLER ERROR */
|
|
kbdc_lock(kbdc, FALSE);
|
|
splx(s);
|
|
return 1;
|
|
}
|
|
/*
|
|
* Now that the keyboard controller is told not to generate
|
|
* the keyboard and mouse interrupts, call `splx()' to allow
|
|
* the other tty interrupts. The clock interrupt may also occur,
|
|
* but the timeout routine (`scrn_timer()') will be blocked
|
|
* by the lock flag set via `kbdc_lock()'
|
|
*/
|
|
splx(s);
|
|
#endif
|
|
|
|
if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK)
|
|
send_kbd_command(kbdc, KBDC_ENABLE_KBD);
|
|
|
|
#if 0
|
|
/* restore the interrupts */
|
|
if (!set_controller_command_byte(kbdc,
|
|
kbdc_get_device_mask(kbdc),
|
|
c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
|
|
/* CONTROLLER ERROR */
|
|
}
|
|
#else
|
|
splx(s);
|
|
#endif
|
|
kbdc_lock(kbdc, FALSE);
|
|
|
|
return 0;
|
|
}
|
|
#endif /* !_I386_ISA_KBDIO_H_ */
|
|
|
|
#if PCVT_SCANSET > 1
|
|
/*---------------------------------------------------------------------------*
|
|
* switch PC scan code emulation mode
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
kbd_emulate_pc(int do_emulation)
|
|
{
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
int cmd, timeo = 10000;
|
|
|
|
cmd = COMMAND_SYSFLG|COMMAND_IRQEN; /* common base cmd */
|
|
|
|
#if !PCVT_USEKBDSEC
|
|
cmd |= COMMAND_INHOVR;
|
|
#endif
|
|
|
|
if(do_emulation)
|
|
cmd |= COMMAND_PCSCAN;
|
|
|
|
kbc_8042cmd(CONTR_WRITE);
|
|
while (inb(CONTROLLER_CTRL) & STATUS_INPBF)
|
|
if (--timeo == 0)
|
|
break;
|
|
outb(CONTROLLER_DATA, cmd);
|
|
#else
|
|
set_controller_command_byte(kbdc, KBD_TRANSLATION,
|
|
(do_emulation) ? KBD_TRANSLATION : 0);
|
|
#endif /* !_I386_ISA_KBDIO_H_ */
|
|
}
|
|
|
|
#endif /* PCVT_SCANSET > 1 */
|
|
|
|
|
|
#ifndef PCVT_NONRESP_KEYB_TRY
|
|
#define PCVT_NONRESP_KEYB_TRY 25 /* no of times to try to detect */
|
|
#endif /* a nonresponding keyboard */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* try to force keyboard into a known state ..
|
|
*---------------------------------------------------------------------------*/
|
|
static
|
|
void doreset(void)
|
|
{
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
int again = 0;
|
|
int once = 0;
|
|
int response, opri;
|
|
|
|
/* Enable interrupts and keyboard, etc. */
|
|
if (kbc_8042cmd(CONTR_WRITE) != 0)
|
|
printf("pcvt: doreset() - timeout controller write command\n");
|
|
|
|
#if PCVT_USEKBDSEC /* security enabled */
|
|
|
|
# if PCVT_SCANSET == 2
|
|
# define KBDINITCMD COMMAND_SYSFLG|COMMAND_IRQEN
|
|
# else /* PCVT_SCANSET != 2 */
|
|
# define KBDINITCMD COMMAND_PCSCAN|COMMAND_SYSFLG|COMMAND_IRQEN
|
|
# endif /* PCVT_SCANSET == 2 */
|
|
|
|
#else /* ! PCVT_USEKBDSEC */ /* security disabled */
|
|
|
|
# if PCVT_SCANSET == 2
|
|
# define KBDINITCMD COMMAND_INHOVR|COMMAND_SYSFLG|COMMAND_IRQEN
|
|
# else /* PCVT_SCANSET != 2 */
|
|
# define KBDINITCMD COMMAND_PCSCAN|COMMAND_INHOVR|COMMAND_SYSFLG\
|
|
|COMMAND_IRQEN
|
|
# endif /* PCVT_SCANSET == 2 */
|
|
|
|
#endif /* PCVT_USEKBDSEC */
|
|
|
|
if (kbd_cmd(KBDINITCMD) != 0)
|
|
printf("pcvt: doreset() - timeout writing keyboard init command\n");
|
|
|
|
/*
|
|
* Discard any stale keyboard activity. The 0.1 boot code isn't
|
|
* very careful and sometimes leaves a KEYB_R_RESEND. Versions
|
|
* between 1992 and Oct 1996 didn't have the delay and sometimes
|
|
* left a KEYB_R_RESEND.
|
|
*/
|
|
while (1) {
|
|
if (inb(CONTROLLER_CTRL) & STATUS_OUTPBF)
|
|
kbd_response();
|
|
else {
|
|
DELAY(10000);
|
|
if (!(inb(CONTROLLER_CTRL) & STATUS_OUTPBF))
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Start keyboard reset */
|
|
|
|
opri = spltty ();
|
|
|
|
if (kbd_cmd(KEYB_C_RESET) != 0)
|
|
{
|
|
printf("pcvt: doreset() - timeout for keyboard reset command\n");
|
|
outb(CONTROLLER_DATA, KEYB_C_RESET); /* force */
|
|
}
|
|
|
|
/* Wait for the first response to reset and handle retries */
|
|
while ((response = kbd_response()) != KEYB_R_ACK)
|
|
{
|
|
if (response < 0)
|
|
{
|
|
if(!again) /* print message only once ! */
|
|
printf("pcvt: doreset() - response != ack and response < 0 [one time only msg]\n");
|
|
response = KEYB_R_RESEND;
|
|
}
|
|
else if (response == KEYB_R_RESEND)
|
|
{
|
|
if(!again) /* print message only once ! */
|
|
printf("pcvt: doreset() - got KEYB_R_RESEND response ... [one time only msg]\n");
|
|
}
|
|
if (response == KEYB_R_RESEND)
|
|
{
|
|
if(++again > PCVT_NONRESP_KEYB_TRY)
|
|
{
|
|
printf("pcvt: doreset() - Caution - no PC keyboard detected!\n");
|
|
keyboard_type = KB_UNKNOWN;
|
|
splx(opri);
|
|
return;
|
|
}
|
|
|
|
if((kbd_cmd(KEYB_C_RESET) != 0) && (once == 0))
|
|
{
|
|
once++; /* print message only once ! */
|
|
printf("pcvt: doreset() - timeout for loop keyboard reset command [one time only msg]\n");
|
|
outb(CONTROLLER_DATA, KEYB_C_RESET); /* force */
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Wait for the second response to reset */
|
|
|
|
while ((response = kbd_response()) != KEYB_R_SELFOK)
|
|
{
|
|
if (response < 0)
|
|
{
|
|
printf("pcvt: doreset() - response != OK and resonse < 0\n");
|
|
/*
|
|
* If KEYB_R_SELFOK never arrives, the loop will
|
|
* finish here unless the keyboard babbles or
|
|
* STATUS_OUTPBF gets stuck.
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
|
|
splx (opri);
|
|
|
|
#if PCVT_KEYBDID
|
|
|
|
opri = spltty ();
|
|
|
|
if(kbd_cmd(KEYB_C_ID) != 0)
|
|
{
|
|
printf("pcvt: doreset() - timeout for keyboard ID command\n");
|
|
keyboard_type = KB_UNKNOWN;
|
|
}
|
|
else
|
|
{
|
|
|
|
r_entry:
|
|
|
|
if((response = kbd_response()) == KEYB_R_MF2ID1)
|
|
{
|
|
if((response = kbd_response()) == KEYB_R_MF2ID2)
|
|
{
|
|
keyboard_type = KB_MFII;
|
|
}
|
|
else if(response == KEYB_R_MF2ID2HP)
|
|
{
|
|
keyboard_type = KB_MFII;
|
|
}
|
|
else
|
|
{
|
|
printf("\npcvt: doreset() - kbdid, response 2 = [%d]\n",
|
|
response);
|
|
keyboard_type = KB_UNKNOWN;
|
|
}
|
|
}
|
|
else if (response == KEYB_R_ACK)
|
|
{
|
|
goto r_entry;
|
|
}
|
|
else if (response == -1)
|
|
{
|
|
keyboard_type = KB_AT;
|
|
}
|
|
else
|
|
{
|
|
printf("\npcvt: doreset() - kbdid, response 1 = [%d]\n", response);
|
|
}
|
|
}
|
|
|
|
splx (opri);
|
|
|
|
#else /* PCVT_KEYBDID */
|
|
|
|
keyboard_type = KB_MFII; /* force it .. */
|
|
|
|
#endif /* PCVT_KEYBDID */
|
|
|
|
#else /* _I386_ISA_KBDIO_H_ */
|
|
int c;
|
|
int m;
|
|
int s;
|
|
|
|
if (!reset_keyboard) /* no, we are not ready to reset */
|
|
return;
|
|
|
|
if (lost_intr_timeout_queued) {
|
|
untimeout(check_for_lost_intr, (void *)NULL);
|
|
lost_intr_timeout_queued = 0;
|
|
}
|
|
|
|
if (kbdc == NULL)
|
|
kbdc = kbdc_open(IO_KBD);
|
|
|
|
if (!kbdc_lock(kbdc, TRUE)) /* strange, somebody got there first */
|
|
return;
|
|
|
|
/* remove any noise */
|
|
empty_both_buffers(kbdc, 10);
|
|
|
|
s = spltty();
|
|
|
|
/* save the current controller command byte */
|
|
m = kbdc_get_device_mask(kbdc) & ~KBD_KBD_CONTROL_BITS;
|
|
c = get_controller_command_byte(kbdc);
|
|
if (c == -1) {
|
|
/* CONTROLLER ERROR */
|
|
kbdc_set_device_mask(kbdc, m);
|
|
kbdc_lock(kbdc, FALSE);
|
|
kbdc = NULL;
|
|
splx(s);
|
|
printf("pcvt: unable to get the command byte.\n");
|
|
return;
|
|
}
|
|
|
|
#if PCVT_USEKBDSEC /* security enabled */
|
|
|
|
# if PCVT_SCANSET == 2
|
|
# define KBDINITCMD 0
|
|
# else /* PCVT_SCANSET != 2 */
|
|
# define KBDINITCMD KBD_TRANSLATION
|
|
# endif /* PCVT_SCANSET == 2 */
|
|
|
|
#else /* ! PCVT_USEKBDSEC */ /* security disabled */
|
|
|
|
# if PCVT_SCANSET == 2
|
|
# define KBDINITCMD KBD_OVERRIDE_KBD_LOCK
|
|
# else /* PCVT_SCANSET != 2 */
|
|
# define KBDINITCMD KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK
|
|
# endif /* PCVT_SCANSET == 2 */
|
|
|
|
#endif /* PCVT_USEKBDSEC */
|
|
|
|
/* disable the keyboard interrupt and the aux port and interrupt */
|
|
if (!set_controller_command_byte(kbdc,
|
|
KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK,
|
|
KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT | KBDINITCMD)) {
|
|
/* CONTROLLER ERROR: there is very little we can do... */
|
|
kbdc_set_device_mask(kbdc, m);
|
|
kbdc_lock(kbdc, FALSE);
|
|
kbdc = NULL;
|
|
splx(s);
|
|
printf("pcvt: unable to set the command byte.\n");
|
|
return;
|
|
}
|
|
splx(s);
|
|
|
|
/* reset keyboard hardware */
|
|
ledstate = LEDSTATE_UPDATE_PENDING;
|
|
if (!reset_kbd(kbdc)) {
|
|
/* KEYBOARD ERROR */
|
|
empty_both_buffers(kbdc, 10);
|
|
test_controller(kbdc);
|
|
test_kbd_port(kbdc);
|
|
/*
|
|
* We could disable the keyboard port and interrupt now...
|
|
* but, the keyboard may still exist.
|
|
*/
|
|
printf("pcvt: failed to reset the keyboard.\n");
|
|
/* try to restore the original command byte */
|
|
set_controller_command_byte(kbdc, 0xff, c);
|
|
kbdc_set_device_mask(kbdc, m);
|
|
kbdc_lock(kbdc, FALSE);
|
|
kbdc = NULL;
|
|
return;
|
|
}
|
|
|
|
#if PCVT_KEYBDID
|
|
|
|
keyboard_type = KB_UNKNOWN;
|
|
if (send_kbd_command(kbdc, KBDC_SEND_DEV_ID) == KBD_ACK) {
|
|
DELAY(10000); /* 10msec delay */
|
|
switch (read_kbd_data(kbdc)) {
|
|
case KEYB_R_MF2ID1:
|
|
switch (read_kbd_data(kbdc)) {
|
|
case KEYB_R_MF2ID2:
|
|
case KEYB_R_MF2ID2HP:
|
|
keyboard_type = KB_MFII;
|
|
break;
|
|
case -1:
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case -1:
|
|
keyboard_type = KB_AT;
|
|
/* fall through */
|
|
default:
|
|
/* XXX: should we read the second byte? */
|
|
empty_both_buffers(kbdc, 10); /* XXX */
|
|
break;
|
|
}
|
|
} else {
|
|
/*
|
|
* The send ID command failed. This error is considered
|
|
* benign, but may need recovery.
|
|
*/
|
|
empty_both_buffers(kbdc, 10);
|
|
test_controller(kbdc);
|
|
test_kbd_port(kbdc);
|
|
}
|
|
|
|
#else /* PCVT_KEYBDID */
|
|
|
|
keyboard_type = KB_MFII; /* force it .. */
|
|
|
|
#endif /* PCVT_KEYBDID */
|
|
|
|
/* enable the keyboard port and intr. */
|
|
if (!set_controller_command_byte(kbdc,
|
|
KBD_KBD_CONTROL_BITS,
|
|
KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) {
|
|
/* CONTROLLER ERROR
|
|
* This is serious; we are left with the disabled
|
|
* keyboard intr.
|
|
*/
|
|
printf("pcvt: failed to enable the keyboard port and intr.\n");
|
|
kbdc_set_device_mask(kbdc, m);
|
|
kbdc_lock(kbdc, FALSE);
|
|
kbdc = NULL;
|
|
return;
|
|
}
|
|
|
|
kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS);
|
|
kbdc_lock(kbdc, FALSE);
|
|
|
|
update_led();
|
|
|
|
timeout(check_for_lost_intr, (void *)NULL, hz);
|
|
lost_intr_timeout_queued = 1;
|
|
|
|
#endif /* !_I386_ISA_KBDIO_H_ */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* init keyboard code
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
kbd_code_init(void)
|
|
{
|
|
doreset();
|
|
ovlinit(0);
|
|
keyboard_is_initialized = 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* init keyboard code, this initializes the keyboard subsystem
|
|
* just "a bit" so the very very first ddb session is able to
|
|
* get proper keystrokes - in other words, it's a hack ....
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
kbd_code_init1(void)
|
|
{
|
|
doreset();
|
|
keyboard_is_initialized = 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* init keyboard overlay table
|
|
*---------------------------------------------------------------------------*/
|
|
static
|
|
void ovlinit(int force)
|
|
{
|
|
register i;
|
|
|
|
if(force || ovlinitflag==0)
|
|
{
|
|
if(ovlinitflag == 0 &&
|
|
(ovltbl = (Ovl_tbl *)malloc(sizeof(Ovl_tbl) * OVLTBL_SIZE,
|
|
M_DEVBUF, M_WAITOK)) == NULL)
|
|
panic("pcvt_kbd: malloc of Ovl_tbl failed");
|
|
|
|
for(i=0; i<OVLTBL_SIZE; i++)
|
|
{
|
|
ovltbl[i].keynum =
|
|
ovltbl[i].type = 0;
|
|
ovltbl[i].unshift[0] =
|
|
ovltbl[i].shift[0] =
|
|
ovltbl[i].ctrl[0] =
|
|
ovltbl[i].altgr[0] = 0;
|
|
ovltbl[i].subu =
|
|
ovltbl[i].subs =
|
|
ovltbl[i].subc =
|
|
ovltbl[i].suba = KBD_SUBT_STR; /* just strings .. */
|
|
}
|
|
for(i=0; i<=MAXKEYNUM; i++)
|
|
key2ascii[i].type &= KBD_MASK;
|
|
ovlinitflag = 1;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* get original key definition
|
|
*---------------------------------------------------------------------------*/
|
|
static int
|
|
getokeydef(unsigned key, Ovl_tbl *thisdef)
|
|
{
|
|
if(key == 0 || key > MAXKEYNUM)
|
|
return EINVAL;
|
|
|
|
thisdef->keynum = key;
|
|
thisdef->type = key2ascii[key].type;
|
|
|
|
if(key2ascii[key].unshift.subtype == STR)
|
|
{
|
|
bcopy((u_char *)(key2ascii[key].unshift.what.string),
|
|
thisdef->unshift, CODE_SIZE);
|
|
thisdef->subu = KBD_SUBT_STR;
|
|
}
|
|
else
|
|
{
|
|
bcopy("", thisdef->unshift, CODE_SIZE);
|
|
thisdef->subu = KBD_SUBT_FNC;
|
|
}
|
|
|
|
if(key2ascii[key].shift.subtype == STR)
|
|
{
|
|
bcopy((u_char *)(key2ascii[key].shift.what.string),
|
|
thisdef->shift, CODE_SIZE);
|
|
thisdef->subs = KBD_SUBT_STR;
|
|
}
|
|
else
|
|
{
|
|
bcopy("",thisdef->shift,CODE_SIZE);
|
|
thisdef->subs = KBD_SUBT_FNC;
|
|
}
|
|
|
|
if(key2ascii[key].ctrl.subtype == STR)
|
|
{
|
|
bcopy((u_char *)(key2ascii[key].ctrl.what.string),
|
|
thisdef->ctrl, CODE_SIZE);
|
|
thisdef->subc = KBD_SUBT_STR;
|
|
}
|
|
else
|
|
{
|
|
bcopy("",thisdef->ctrl,CODE_SIZE);
|
|
thisdef->subc = KBD_SUBT_FNC;
|
|
}
|
|
|
|
/* deliver at least anything for ALTGR settings ... */
|
|
|
|
if(key2ascii[key].unshift.subtype == STR)
|
|
{
|
|
bcopy((u_char *)(key2ascii[key].unshift.what.string),
|
|
thisdef->altgr, CODE_SIZE);
|
|
thisdef->suba = KBD_SUBT_STR;
|
|
}
|
|
else
|
|
{
|
|
bcopy("",thisdef->altgr, CODE_SIZE);
|
|
thisdef->suba = KBD_SUBT_FNC;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* get current key definition
|
|
*---------------------------------------------------------------------------*/
|
|
static int
|
|
getckeydef(unsigned key, Ovl_tbl *thisdef)
|
|
{
|
|
u_short type = key2ascii[key].type;
|
|
|
|
if(key>MAXKEYNUM)
|
|
return EINVAL;
|
|
|
|
if(type & KBD_OVERLOAD)
|
|
*thisdef = ovltbl[key2ascii[key].ovlindex];
|
|
else
|
|
getokeydef(key,thisdef);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* translate keynumber and returns ptr to associated ascii string
|
|
* if key is bound to a function, executes it, and ret empty ptr
|
|
*---------------------------------------------------------------------------*/
|
|
static u_char *
|
|
xlatkey2ascii(U_short key)
|
|
{
|
|
static u_char capchar[2] = {0, 0};
|
|
#if PCVT_META_ESC
|
|
static u_char metachar[3] = {0x1b, 0, 0};
|
|
#else
|
|
static u_char metachar[2] = {0, 0};
|
|
#endif
|
|
static Ovl_tbl thisdef;
|
|
int n;
|
|
void (*fnc)(void);
|
|
|
|
if(key==0) /* ignore the NON-KEY */
|
|
return 0;
|
|
|
|
getckeydef(key&0x7F, &thisdef); /* get the current ASCII value */
|
|
|
|
thisdef.type &= KBD_MASK;
|
|
|
|
if(key&0x80) /* special handling of ALT-KEYPAD */
|
|
{
|
|
/* is the ALT Key released? */
|
|
if(thisdef.type==KBD_META || thisdef.type==KBD_ALTGR)
|
|
{
|
|
if(altkpflag) /* have we been in altkp mode? */
|
|
{
|
|
capchar[0] = altkpval;
|
|
altkpflag = 0;
|
|
altkpval = 0;
|
|
return capchar;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
switch(thisdef.type) /* convert the keys */
|
|
{
|
|
case KBD_BREAK:
|
|
case KBD_ASCII:
|
|
case KBD_FUNC:
|
|
fnc = NULL;
|
|
more_chars = NULL;
|
|
|
|
if(altgr_down)
|
|
{
|
|
more_chars = (u_char *)thisdef.altgr;
|
|
}
|
|
else if(!ctrl_down && (shift_down || vsp->shift_lock))
|
|
{
|
|
if(key2ascii[key].shift.subtype == STR)
|
|
more_chars = (u_char *)thisdef.shift;
|
|
else
|
|
fnc = key2ascii[key].shift.what.func;
|
|
}
|
|
|
|
else if(ctrl_down)
|
|
{
|
|
if(key2ascii[key].ctrl.subtype == STR)
|
|
more_chars = (u_char *)thisdef.ctrl;
|
|
else
|
|
fnc = key2ascii[key].ctrl.what.func;
|
|
}
|
|
|
|
else
|
|
{
|
|
if(key2ascii[key].unshift.subtype == STR)
|
|
more_chars = (u_char *)thisdef.unshift;
|
|
else
|
|
fnc = key2ascii[key].unshift.what.func;
|
|
}
|
|
|
|
if(fnc)
|
|
(*fnc)(); /* execute function */
|
|
|
|
if((more_chars != NULL) && (more_chars[1] == 0))
|
|
{
|
|
if(vsp->caps_lock && more_chars[0] >= 'a'
|
|
&& more_chars[0] <= 'z')
|
|
{
|
|
capchar[0] = *more_chars - ('a'-'A');
|
|
more_chars = capchar;
|
|
}
|
|
if(meta_down)
|
|
{
|
|
#if PCVT_META_ESC
|
|
metachar[1] = *more_chars;
|
|
#else
|
|
metachar[0] = *more_chars | 0x80;
|
|
#endif
|
|
more_chars = metachar;
|
|
}
|
|
}
|
|
return(more_chars);
|
|
|
|
case KBD_KP:
|
|
fnc = NULL;
|
|
more_chars = NULL;
|
|
|
|
if(meta_down)
|
|
{
|
|
switch(key)
|
|
{
|
|
case 95: /* / */
|
|
altkpflag = 0;
|
|
more_chars =
|
|
(u_char *)"\033OQ";
|
|
return(more_chars);
|
|
|
|
case 100: /* * */
|
|
altkpflag = 0;
|
|
more_chars =
|
|
(u_char *)"\033OR";
|
|
return(more_chars);
|
|
|
|
case 105: /* - */
|
|
altkpflag = 0;
|
|
more_chars =
|
|
(u_char *)"\033OS";
|
|
return(more_chars);
|
|
}
|
|
}
|
|
|
|
if(meta_down || altgr_down)
|
|
{
|
|
if((n = keypad2num[key-91]) >= 0)
|
|
{
|
|
if(!altkpflag)
|
|
{
|
|
/* start ALT-KP mode */
|
|
altkpflag = 1;
|
|
altkpval = 0;
|
|
}
|
|
altkpval *= 10;
|
|
altkpval += n;
|
|
}
|
|
else
|
|
altkpflag = 0;
|
|
return 0;
|
|
}
|
|
|
|
if(!(vsp->num_lock))
|
|
{
|
|
if(key2ascii[key].shift.subtype == STR)
|
|
more_chars = (u_char *)thisdef.shift;
|
|
else
|
|
fnc = key2ascii[key].shift.what.func;
|
|
}
|
|
else
|
|
{
|
|
if(key2ascii[key].unshift.subtype == STR)
|
|
more_chars = (u_char *)thisdef.unshift;
|
|
else
|
|
fnc = key2ascii[key].unshift.what.func;
|
|
}
|
|
|
|
if(fnc)
|
|
(*fnc)(); /* execute function */
|
|
return(more_chars);
|
|
|
|
case KBD_CURSOR:
|
|
fnc = NULL;
|
|
more_chars = NULL;
|
|
|
|
if(vsp->ckm)
|
|
{
|
|
if(key2ascii[key].shift.subtype == STR)
|
|
more_chars = (u_char *)thisdef.shift;
|
|
else
|
|
fnc = key2ascii[key].shift.what.func;
|
|
}
|
|
else
|
|
{
|
|
if(key2ascii[key].unshift.subtype == STR)
|
|
more_chars = (u_char *)thisdef.unshift;
|
|
else
|
|
fnc = key2ascii[key].unshift.what.func;
|
|
}
|
|
|
|
if(fnc)
|
|
(*fnc)(); /* execute function */
|
|
return(more_chars);
|
|
|
|
case KBD_NUM: /* special kp-num handling */
|
|
more_chars = NULL;
|
|
|
|
if(meta_down)
|
|
{
|
|
more_chars = (u_char *)"\033OP"; /* PF1 */
|
|
}
|
|
else
|
|
{
|
|
vsp->num_lock ^= 1;
|
|
update_led();
|
|
}
|
|
return(more_chars);
|
|
|
|
case KBD_RETURN:
|
|
more_chars = NULL;
|
|
|
|
if(!(vsp->num_lock))
|
|
{
|
|
more_chars = (u_char *)thisdef.shift;
|
|
}
|
|
else
|
|
{
|
|
more_chars = (u_char *)thisdef.unshift;
|
|
}
|
|
if(vsp->lnm && (*more_chars == '\r'))
|
|
{
|
|
more_chars = (u_char *)"\r\n"; /* CR LF */
|
|
}
|
|
if(meta_down)
|
|
{
|
|
#if PCVT_META_ESC
|
|
metachar[1] = *more_chars;
|
|
#else
|
|
metachar[0] = *more_chars | 0x80;
|
|
#endif
|
|
more_chars = metachar;
|
|
}
|
|
return(more_chars);
|
|
|
|
case KBD_META: /* these keys are */
|
|
case KBD_ALTGR: /* handled directly */
|
|
case KBD_SCROLL: /* by the keyboard */
|
|
case KBD_CAPS: /* handler - they are */
|
|
case KBD_SHFTLOCK: /* ignored here */
|
|
case KBD_CTL:
|
|
case KBD_NONE:
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* get keystrokes from the keyboard.
|
|
* if noblock = 0, wait until a key is pressed.
|
|
* else return NULL if no characters present.
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
#if PCVT_KBD_FIFO
|
|
extern u_char pcvt_kbd_fifo[];
|
|
extern int pcvt_kbd_rptr;
|
|
extern short pcvt_kbd_count;
|
|
#endif
|
|
|
|
u_char *
|
|
sgetc(int noblock)
|
|
{
|
|
u_char *cp;
|
|
u_char dt;
|
|
u_char key;
|
|
u_short type;
|
|
|
|
#if PCVT_KBD_FIFO && PCVT_SLOW_INTERRUPT
|
|
int s;
|
|
#endif
|
|
|
|
static u_char kbd_lastkey = 0; /* last keystroke */
|
|
|
|
static struct
|
|
{
|
|
u_char extended: 1; /* extended prefix seen */
|
|
u_char ext1: 1; /* extended prefix 1 seen */
|
|
u_char breakseen: 1; /* break code seen */
|
|
u_char vshift: 1; /* virtual shift pending */
|
|
u_char vcontrol: 1; /* virtual control pending */
|
|
u_char sysrq: 1; /* sysrq pressed */
|
|
} kbd_status = {0};
|
|
|
|
#ifdef XSERVER
|
|
static char keybuf[2] = {0}; /* the second 0 is a delimiter! */
|
|
#endif /* XSERVER */
|
|
|
|
#ifdef _I386_ISA_KBDIO_H_
|
|
int c;
|
|
#endif /* _I386_ISA_KBDIO_H_ */
|
|
|
|
loop:
|
|
|
|
#ifdef XSERVER
|
|
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
|
|
#if PCVT_KBD_FIFO
|
|
|
|
/* see if there is data from the keyboard available either from */
|
|
/* the keyboard fifo or from the 8042 keyboard controller */
|
|
|
|
if (pcvt_kbd_count || (inb(CONTROLLER_CTRL) & STATUS_OUTPBF))
|
|
{
|
|
if (!pcvt_kbd_count) /* source = 8042 */
|
|
{
|
|
PCVT_KBD_DELAY(); /* 7 us delay */
|
|
dt = inb(CONTROLLER_DATA); /* get from obuf */
|
|
}
|
|
else /* source = keyboard fifo */
|
|
{
|
|
dt = pcvt_kbd_fifo[pcvt_kbd_rptr++];
|
|
PCVT_DISABLE_INTR();
|
|
pcvt_kbd_count--;
|
|
PCVT_ENABLE_INTR();
|
|
if (pcvt_kbd_rptr >= PCVT_KBD_FIFO_SZ)
|
|
pcvt_kbd_rptr = 0;
|
|
}
|
|
|
|
#else /* !PCVT_KB_FIFO */
|
|
|
|
/* see if there is data from the keyboard available from the 8042 */
|
|
|
|
if (inb(CONTROLLER_CTRL) & STATUS_OUTPBF)
|
|
{
|
|
PCVT_KBD_DELAY(); /* 7 us delay */
|
|
dt = inb(CONTROLLER_DATA); /* yes, get data */
|
|
|
|
#endif /* !PCVT_KBD_FIFO */
|
|
|
|
#else /* _I386_ISA_KBDIO_H_ */
|
|
|
|
#if PCVT_KBD_FIFO
|
|
if (pcvt_kbd_count) {
|
|
dt = pcvt_kbd_fifo[pcvt_kbd_rptr++];
|
|
PCVT_DISABLE_INTR();
|
|
pcvt_kbd_count--;
|
|
PCVT_ENABLE_INTR();
|
|
if (pcvt_kbd_rptr >= PCVT_KBD_FIFO_SZ)
|
|
pcvt_kbd_rptr = 0;
|
|
} else
|
|
#endif /* PCVT_KBD_FIFO */
|
|
if (!noblock) {
|
|
while ((c = read_kbd_data(kbdc)) == -1)
|
|
;
|
|
dt = c;
|
|
} else {
|
|
if ((c = read_kbd_data_no_wait(kbdc)) == -1)
|
|
return NULL;
|
|
dt = c;
|
|
}
|
|
|
|
{
|
|
|
|
#endif /* !_I386_ISA_KBDIO_H_ */
|
|
|
|
/*
|
|
* If x mode is active, only care for locking keys, then
|
|
* return the scan code instead of any key translation.
|
|
* Additionally, this prevents us from any attempts to
|
|
* execute pcvt internal functions caused by keys (such
|
|
* as screen flipping).
|
|
* XXX For now, only the default locking key definitions
|
|
* are recognized (i.e. if you have overloaded you "A" key
|
|
* as NUMLOCK, that wont effect X mode:-)
|
|
* Changing this would be nice, but would require modifi-
|
|
* cations to the X server. After having this, X will
|
|
* deal with the LEDs itself, so we are committed.
|
|
*/
|
|
/*
|
|
* Iff PCVT_USL_VT_COMPAT is defined, the behaviour has
|
|
* been fixed. We need not care about any keys here, since
|
|
* there are ioctls that deal with the lock key / LED stuff.
|
|
*/
|
|
if (pcvt_kbd_raw)
|
|
{
|
|
keybuf[0] = dt;
|
|
|
|
#if PCVT_FREEBSD > 210
|
|
add_keyboard_randomness(dt);
|
|
#endif /* PCVT_FREEBSD > 210 */
|
|
|
|
#if !PCVT_USL_VT_COMPAT
|
|
if ((dt & 0x80) == 0)
|
|
/* key make */
|
|
switch(dt)
|
|
{
|
|
case 0x45:
|
|
/* XXX on which virt screen? */ vsp->num_lock ^= 1;
|
|
update_led();
|
|
break;
|
|
|
|
case 0x3a:
|
|
vsp->caps_lock ^= 1;
|
|
update_led();
|
|
break;
|
|
|
|
case 0x46:
|
|
vsp->scroll_lock ^= 1;
|
|
update_led();
|
|
break;
|
|
}
|
|
#endif /* !PCVT_USL_VT_COMPAT */
|
|
|
|
#if PCVT_EMU_MOUSE
|
|
/*
|
|
* The (mouse systems) mouse emulator. The mouse
|
|
* device allocates the first device node that is
|
|
* not used by a virtual terminal. (E.g., you have
|
|
* eight vtys, /dev/ttyv0 thru /dev/ttyv7, so the
|
|
* mouse emulator were /dev/ttyv8.)
|
|
* Currently the emulator only works if the keyboard
|
|
* is in raw (PC scan code) mode. This is the typic-
|
|
* al case when running the X server.
|
|
* It is activated if the num locks LED is active
|
|
* for the current vty, and if the mouse device
|
|
* has been opened by at least one process. It
|
|
* grabs the numerical keypad events (but only
|
|
* the "non-extended", so the separate arrow keys
|
|
* continue to work), and three keys for the "mouse
|
|
* buttons", preferrably F1 thru F3. Any of the
|
|
* eight directions (N, NE, E, SE, S, SW, W, NW)
|
|
* is supported, and frequent key presses (less
|
|
* than e.g. half a second between key presses)
|
|
* cause the emulator to accelerate the pointer
|
|
* movement by 6, while single presses result in
|
|
* single moves, so each point can be reached.
|
|
*/
|
|
/*
|
|
* NB: the following code is spagghetti.
|
|
* Only eat it with lotta tomato ketchup and
|
|
* Parmesan cheese:-)
|
|
*/
|
|
/*
|
|
* look whether we will have to steal the keys
|
|
* and cook them into mouse events
|
|
*/
|
|
if(vsp->num_lock && mouse.opened)
|
|
{
|
|
int button, accel, i;
|
|
enum mouse_dir
|
|
{
|
|
MOUSE_NW, MOUSE_N, MOUSE_NE,
|
|
MOUSE_W, MOUSE_0, MOUSE_E,
|
|
MOUSE_SW, MOUSE_S, MOUSE_SE
|
|
}
|
|
move;
|
|
struct timeval now;
|
|
dev_t dummy = makedev(0, mouse.minor);
|
|
struct tty *mousetty = get_pccons(dummy);
|
|
/*
|
|
* strings to send for each mouse event,
|
|
* indexed by the movement direction and
|
|
* the "accelerator" value (TRUE for frequent
|
|
* key presses); note that the first byte
|
|
* of each string is actually overwritten
|
|
* by the current button value before sending
|
|
* the string
|
|
*/
|
|
static u_char mousestrings[2][MOUSE_SE+1][5] =
|
|
{
|
|
{
|
|
/* first, the non-accelerated strings*/
|
|
{0x87, -1, 1, 0, 0}, /* NW */
|
|
{0x87, 0, 1, 0, 0}, /* N */
|
|
{0x87, 1, 1, 0, 0}, /* NE */
|
|
{0x87, -1, 0, 0, 0}, /* W */
|
|
{0x87, 0, 0, 0, 0}, /* 0 */
|
|
{0x87, 1, 0, 0, 0}, /* E */
|
|
{0x87, -1, -1, 0, 0}, /* SW */
|
|
{0x87, 0, -1, 0, 0}, /* S */
|
|
{0x87, 1, -1, 0, 0} /* SE */
|
|
},
|
|
{
|
|
/* now, 6 steps at once */
|
|
{0x87, -4, 4, 0, 0}, /* NW */
|
|
{0x87, 0, 6, 0, 0}, /* N */
|
|
{0x87, 4, 4, 0, 0}, /* NE */
|
|
{0x87, -6, 0, 0, 0}, /* W */
|
|
{0x87, 0, 0, 0, 0}, /* 0 */
|
|
{0x87, 6, 0, 0, 0}, /* E */
|
|
{0x87, -4, -4, 0, 0}, /* SW */
|
|
{0x87, 0, -6, 0, 0}, /* S */
|
|
{0x87, 4, -4, 0, 0} /* SE */
|
|
}
|
|
};
|
|
|
|
if(dt == 0xe0)
|
|
{
|
|
/* ignore extended scan codes */
|
|
mouse.extendedseen = 1;
|
|
goto no_mouse_event;
|
|
}
|
|
if(mouse.extendedseen)
|
|
{
|
|
mouse.extendedseen = 0;
|
|
goto no_mouse_event;
|
|
}
|
|
mouse.extendedseen = 0;
|
|
|
|
/*
|
|
* Note that we cannot use a switch here
|
|
* since we want to have the keycodes in
|
|
* a variable
|
|
*/
|
|
if((dt & 0x7f) == mousedef.leftbutton) {
|
|
button = 4;
|
|
goto do_button;
|
|
}
|
|
else if((dt & 0x7f) == mousedef.middlebutton) {
|
|
button = 2;
|
|
goto do_button;
|
|
}
|
|
else if((dt & 0x7f) == mousedef.rightbutton) {
|
|
button = 1;
|
|
do_button:
|
|
|
|
/*
|
|
* i would really like to give
|
|
* some acustical support
|
|
* (pling/plong); i am not sure
|
|
* whether it is safe to call
|
|
* sysbeep from within an intr
|
|
* service, since it calls
|
|
* timeout in turn which mani-
|
|
* pulates the spl mask - jw
|
|
*/
|
|
|
|
# define PLING sysbeep(PCVT_SYSBEEPF / 1500, 2)
|
|
# define PLONG sysbeep(PCVT_SYSBEEPF / 1200, 2)
|
|
|
|
if(mousedef.stickybuttons)
|
|
{
|
|
if(dt & 0x80) {
|
|
mouse.breakseen = 1;
|
|
return (u_char *)0;
|
|
}
|
|
else if(mouse.buttons == button
|
|
&& !mouse.breakseen) {
|
|
/* ignore repeats */
|
|
return (u_char *)0;
|
|
}
|
|
else
|
|
mouse.breakseen = 0;
|
|
if(mouse.buttons == button) {
|
|
/* release it */
|
|
mouse.buttons = 0;
|
|
PLONG;
|
|
} else {
|
|
/*
|
|
* eventually, release
|
|
* any other button,
|
|
* and stick this one
|
|
*/
|
|
mouse.buttons = button;
|
|
PLING;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(dt & 0x80) {
|
|
mouse.buttons &=
|
|
~button;
|
|
PLONG;
|
|
}
|
|
else if((mouse.buttons
|
|
& button) == 0) {
|
|
mouse.buttons |=
|
|
button;
|
|
PLING;
|
|
}
|
|
/*else: ignore same btn press*/
|
|
}
|
|
move = MOUSE_0;
|
|
accel = 0;
|
|
}
|
|
# undef PLING
|
|
# undef PLONG
|
|
else switch(dt & 0x7f)
|
|
{
|
|
/* the arrow keys - KP 1 thru KP 9 */
|
|
case 0x47: move = MOUSE_NW; goto do_move;
|
|
case 0x48: move = MOUSE_N; goto do_move;
|
|
case 0x49: move = MOUSE_NE; goto do_move;
|
|
case 0x4b: move = MOUSE_W; goto do_move;
|
|
case 0x4c: move = MOUSE_0; goto do_move;
|
|
case 0x4d: move = MOUSE_E; goto do_move;
|
|
case 0x4f: move = MOUSE_SW; goto do_move;
|
|
case 0x50: move = MOUSE_S; goto do_move;
|
|
case 0x51: move = MOUSE_SE;
|
|
do_move:
|
|
if(dt & 0x80)
|
|
/*
|
|
* arrow key break events are
|
|
* of no importance for us
|
|
*/
|
|
return (u_char *)0;
|
|
/*
|
|
* see whether the last move did
|
|
* happen "recently", i.e. before
|
|
* less than half a second
|
|
*/
|
|
gettime(&now);
|
|
timevalsub(&now, &mouse.lastmove);
|
|
mouse.lastmove = time;
|
|
accel = (now.tv_sec == 0
|
|
&& now.tv_usec
|
|
< mousedef.acceltime);
|
|
break;
|
|
|
|
default: /* not a mouse-emulating key */
|
|
goto no_mouse_event;
|
|
}
|
|
mousestrings[accel][move][0] =
|
|
0x80 + (~mouse.buttons & 7);
|
|
/* finally, send the string */
|
|
for(i = 0; i < 5; i++)
|
|
(*linesw[mousetty->t_line].l_rint)
|
|
(mousestrings[accel][move][i],
|
|
mousetty);
|
|
return (u_char *)0; /* not a kbd event */
|
|
}
|
|
no_mouse_event:
|
|
|
|
#endif /* PCVT_EMU_MOUSE */
|
|
|
|
return ((u_char *)keybuf);
|
|
}
|
|
}
|
|
|
|
#else /* !XSERVER */
|
|
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
|
|
# if PCVT_KBD_FIFO
|
|
|
|
/* see if there is data from the keyboard available either from */
|
|
/* the keyboard fifo or from the 8042 keyboard controller */
|
|
|
|
if (pcvt_kbd_count || (inb(CONTROLLER_CTRL) & STATUS_OUTPBF))
|
|
{
|
|
if (!noblock || kbd_polling) /* source = 8042 */
|
|
{
|
|
PCVT_KBD_DELAY(); /* 7 us delay */
|
|
dt = inb(CONTROLLER_DATA);
|
|
}
|
|
else /* source = keyboard fifo */
|
|
{
|
|
dt = pcvt_kbd_fifo[pcvt_kbd_rptr++]; /* yes, get it ! */
|
|
PCVT_DISABLE_INTR();
|
|
pcvt_kbd_count--;
|
|
PCVT_ENABLE_INTR();
|
|
if (pcvt_kbd_rptr >= PCVT_KBD_FIFO_SZ)
|
|
pcvt_kbd_rptr = 0;
|
|
}
|
|
}
|
|
|
|
#else /* !PCVT_KBD_FIFO */
|
|
|
|
/* see if there is data from the keyboard available from the 8042 */
|
|
|
|
if(inb(CONTROLLER_CTRL) & STATUS_OUTPBF)
|
|
{
|
|
PCVT_KBD_DELAY(); /* 7 us delay */
|
|
dt = inb(CONTROLLER_DATA); /* yes, get data ! */
|
|
}
|
|
|
|
#endif /* !PCVT_KBD_FIFO */
|
|
|
|
#else /* _I386_ISA_KBDIO_H_ */
|
|
|
|
#if PCVT_KBD_FIFO
|
|
if (pcvt_kbd_count) {
|
|
dt = pcvt_kbd_fifo[pcvt_kbd_rptr++];
|
|
PCVT_DISABLE_INTR();
|
|
pcvt_kbd_count--;
|
|
PCVT_ENABLE_INTR();
|
|
if (pcvt_kbd_rptr >= PCVT_KBD_FIFO_SZ)
|
|
pcvt_kbd_rptr = 0;
|
|
} else
|
|
#endif /* PCVT_KBD_FIFO */
|
|
if (!noblock) {
|
|
while ((c = read_kbd_data(kbdc)) == -1)
|
|
;
|
|
dt = c;
|
|
} else {
|
|
if ((c = read_kbd_data_no_wait(kbdc)) == -1)
|
|
return NULL;
|
|
dt = c;
|
|
}
|
|
|
|
#endif /* !_I386_ISA_KBDIO_H_ */
|
|
|
|
#endif /* !XSERVER */
|
|
|
|
#ifndef _I386_ISA_KBDIO_H_
|
|
else
|
|
{
|
|
if(noblock)
|
|
return NULL;
|
|
else
|
|
goto loop;
|
|
}
|
|
#endif /* !_I386_ISA_KBDIO_H_ */
|
|
|
|
#if PCVT_SHOWKEYS
|
|
showkey (' ', dt);
|
|
#endif /* PCVT_SHOWKEYS */
|
|
|
|
/* lets look what we got */
|
|
switch(dt)
|
|
{
|
|
case KEYB_R_OVERRUN0: /* keyboard buffer overflow */
|
|
|
|
#if PCVT_SCANSET == 2
|
|
case KEYB_R_SELFOK: /* keyboard selftest ok */
|
|
#endif /* PCVT_SCANSET == 2 */
|
|
|
|
case KEYB_R_ECHO: /* keyboard response to KEYB_C_ECHO */
|
|
case KEYB_R_ACK: /* acknowledge after command has rx'd*/
|
|
case KEYB_R_SELFBAD: /* keyboard selftest FAILED */
|
|
case KEYB_R_DIAGBAD: /* keyboard self diagnostic failure */
|
|
case KEYB_R_RESEND: /* keyboard wants us to resend cmnd */
|
|
case KEYB_R_OVERRUN1: /* keyboard buffer overflow */
|
|
break;
|
|
|
|
case KEYB_R_EXT1: /* keyboard extended scancode pfx 2 */
|
|
kbd_status.ext1 = 1;
|
|
/* FALLTHROUGH */
|
|
case KEYB_R_EXT0: /* keyboard extended scancode pfx 1 */
|
|
kbd_status.extended = 1;
|
|
break;
|
|
|
|
#if PCVT_SCANSET == 2
|
|
case KEYB_R_BREAKPFX: /* break code prefix for set 2 and 3 */
|
|
kbd_status.breakseen = 1;
|
|
break;
|
|
#endif /* PCVT_SCANSET == 2 */
|
|
|
|
default:
|
|
goto regular; /* regular key */
|
|
}
|
|
|
|
if(noblock)
|
|
return NULL;
|
|
else
|
|
goto loop;
|
|
|
|
/* got a normal scan key */
|
|
regular:
|
|
|
|
#if PCVT_FREEBSD > 210
|
|
add_keyboard_randomness(dt);
|
|
#endif /* PCVT_FREEBSD > 210 */
|
|
|
|
#if PCVT_SCANSET == 1
|
|
kbd_status.breakseen = dt & 0x80 ? 1 : 0;
|
|
dt &= 0x7f;
|
|
#endif /* PCVT_SCANSET == 1 */
|
|
|
|
/* make a keycode from scan code */
|
|
if(dt >= sizeof scantokey / sizeof(u_char))
|
|
key = 0;
|
|
else
|
|
key = kbd_status.extended ? extscantokey[dt] : scantokey[dt];
|
|
|
|
if(kbd_status.ext1 && key == 64)
|
|
/* virtual control key */
|
|
key = 129;
|
|
|
|
kbd_status.extended = kbd_status.ext1 = 0;
|
|
|
|
#if PCVT_CTRL_ALT_DEL /* Check for cntl-alt-del */
|
|
if((key == 76) && ctrl_down && (meta_down||altgr_down))
|
|
shutdown_nice();
|
|
#endif /* PCVT_CTRL_ALT_DEL */
|
|
|
|
#if !(PCVT_NETBSD || PCVT_FREEBSD >= 200)
|
|
#include "ddb.h"
|
|
#endif /* !(PCVT_NETBSD || PCVT_FREEBSD >= 200) */
|
|
|
|
#if NDDB > 0 || defined(DDB) /* Check for cntl-alt-esc */
|
|
|
|
if((key == 110) && ctrl_down && (meta_down || altgr_down))
|
|
{
|
|
static u_char in_Debugger;
|
|
|
|
if(!in_Debugger)
|
|
{
|
|
in_Debugger = 1;
|
|
#if PCVT_FREEBSD
|
|
/* the string is actually not used... */
|
|
Debugger("kbd");
|
|
#else
|
|
Debugger();
|
|
#endif
|
|
in_Debugger = 0;
|
|
if(noblock)
|
|
return NULL;
|
|
else
|
|
goto loop;
|
|
}
|
|
}
|
|
#endif /* NDDB > 0 || defined(DDB) */
|
|
|
|
/* look for keys with special handling */
|
|
if(key == 128)
|
|
{
|
|
/*
|
|
* virtual shift; sent around PrtScr, and around the arrow
|
|
* keys if the NumLck LED is on
|
|
*/
|
|
kbd_status.vshift = !kbd_status.breakseen;
|
|
key = 0; /* no key */
|
|
}
|
|
else if(key == 129)
|
|
{
|
|
/*
|
|
* virtual control - the most ugly thingie at all
|
|
* the Pause key sends:
|
|
* <virtual control make> <numlock make> <virtual control
|
|
* break> <numlock break>
|
|
*/
|
|
if(!kbd_status.breakseen)
|
|
kbd_status.vcontrol = 1;
|
|
/* else: let the numlock hook clear this */
|
|
key = 0; /* no key */
|
|
}
|
|
else if(key == 90)
|
|
{
|
|
/* NumLock, look whether this is rather a Pause */
|
|
if(kbd_status.vcontrol)
|
|
key = 126;
|
|
/*
|
|
* if this is the final break code of a Pause key,
|
|
* clear the virtual control status, too
|
|
*/
|
|
if(kbd_status.vcontrol && kbd_status.breakseen)
|
|
kbd_status.vcontrol = 0;
|
|
}
|
|
else if(key == 127)
|
|
{
|
|
/*
|
|
* a SysRq; some keyboards are brain-dead enough to
|
|
* repeat the SysRq key make code by sending PrtScr
|
|
* make codes; other keyboards do not repeat SysRq
|
|
* at all. We keep track of the SysRq state here.
|
|
*/
|
|
kbd_status.sysrq = !kbd_status.breakseen;
|
|
}
|
|
else if(key == 124)
|
|
{
|
|
/*
|
|
* PrtScr; look whether this is really PrtScr or rather
|
|
* a silly repeat of a SysRq key
|
|
*/
|
|
if(kbd_status.sysrq)
|
|
/* ignore the garbage */
|
|
key = 0;
|
|
}
|
|
|
|
/* in NOREPEAT MODE ignore the key if it was the same as before */
|
|
|
|
if(!kbrepflag && key == kbd_lastkey && !kbd_status.breakseen)
|
|
{
|
|
if(noblock)
|
|
return NULL;
|
|
else
|
|
goto loop;
|
|
}
|
|
|
|
type = key2ascii[key].type;
|
|
|
|
if(type & KBD_OVERLOAD)
|
|
type = ovltbl[key2ascii[key].ovlindex].type;
|
|
|
|
type &= KBD_MASK;
|
|
|
|
switch(type)
|
|
{
|
|
case KBD_SHFTLOCK:
|
|
if(!kbd_status.breakseen && key != kbd_lastkey)
|
|
{
|
|
vsp->shift_lock ^= 1;
|
|
}
|
|
break;
|
|
|
|
case KBD_CAPS:
|
|
if(!kbd_status.breakseen && key != kbd_lastkey)
|
|
{
|
|
vsp->caps_lock ^= 1;
|
|
update_led();
|
|
}
|
|
break;
|
|
|
|
case KBD_SCROLL:
|
|
if(!kbd_status.breakseen && key != kbd_lastkey)
|
|
{
|
|
vsp->scroll_lock ^= 1;
|
|
update_led();
|
|
|
|
if(!(vsp->scroll_lock))
|
|
{
|
|
/* someone may be sleeping */
|
|
wakeup((caddr_t)&(vsp->scroll_lock));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KBD_SHIFT:
|
|
shift_down = kbd_status.breakseen ? 0 : 1;
|
|
break;
|
|
|
|
case KBD_META:
|
|
meta_down = kbd_status.breakseen ? 0 : 0x80;
|
|
break;
|
|
|
|
case KBD_ALTGR:
|
|
altgr_down = kbd_status.breakseen ? 0 : 1;
|
|
break;
|
|
|
|
case KBD_CTL:
|
|
ctrl_down = kbd_status.breakseen ? 0 : 1;
|
|
break;
|
|
|
|
case KBD_NONE:
|
|
default:
|
|
break; /* deliver a key */
|
|
}
|
|
|
|
if(kbd_status.breakseen)
|
|
{
|
|
key |= 0x80;
|
|
kbd_status.breakseen = 0;
|
|
kbd_lastkey = 0; /* -hv- I know this is a bug with */
|
|
} /* N-Key-Rollover, but I ignore that */
|
|
else /* because avoidance is too complicated */
|
|
kbd_lastkey = key;
|
|
|
|
cp = xlatkey2ascii(key); /* have a key */
|
|
|
|
if(cp == NULL && !noblock)
|
|
goto loop;
|
|
|
|
return cp;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* reflect status of locking keys & set led's
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
setlockkeys(int snc)
|
|
{
|
|
vsp->scroll_lock = snc & 1;
|
|
vsp->num_lock = (snc & 2) ? 1 : 0;
|
|
vsp->caps_lock = (snc & 4) ? 1 : 0;
|
|
update_led();
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* remove a key definition
|
|
*---------------------------------------------------------------------------*/
|
|
static int
|
|
rmkeydef(int key)
|
|
{
|
|
register Ovl_tbl *ref;
|
|
|
|
if(key==0 || key > MAXKEYNUM)
|
|
return EINVAL;
|
|
|
|
if(key2ascii[key].type & KBD_OVERLOAD)
|
|
{
|
|
ref = &ovltbl[key2ascii[key].ovlindex];
|
|
ref->keynum = 0;
|
|
ref->type = 0;
|
|
ref->unshift[0] =
|
|
ref->shift[0] =
|
|
ref->ctrl[0] =
|
|
ref->altgr[0] = 0;
|
|
key2ascii[key].type &= KBD_MASK;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* overlay a key
|
|
*---------------------------------------------------------------------------*/
|
|
static int
|
|
setkeydef(Ovl_tbl *data)
|
|
{
|
|
register i;
|
|
|
|
if( data->keynum > MAXKEYNUM ||
|
|
(data->type & KBD_MASK) == KBD_BREAK ||
|
|
(data->type & KBD_MASK) > KBD_SHFTLOCK)
|
|
return EINVAL;
|
|
|
|
data->unshift[KBDMAXOVLKEYSIZE] =
|
|
data->shift[KBDMAXOVLKEYSIZE] =
|
|
data->ctrl[KBDMAXOVLKEYSIZE] =
|
|
data->altgr[KBDMAXOVLKEYSIZE] = 0;
|
|
|
|
data->subu =
|
|
data->subs =
|
|
data->subc =
|
|
data->suba = KBD_SUBT_STR; /* just strings .. */
|
|
|
|
data->type |= KBD_OVERLOAD; /* mark overloaded */
|
|
|
|
/* if key already overloaded, use that slot else find free slot */
|
|
|
|
if(key2ascii[data->keynum].type & KBD_OVERLOAD)
|
|
{
|
|
i = key2ascii[data->keynum].ovlindex;
|
|
}
|
|
else
|
|
{
|
|
for(i=0; i<OVLTBL_SIZE; i++)
|
|
if(ovltbl[i].keynum==0)
|
|
break;
|
|
|
|
if(i==OVLTBL_SIZE)
|
|
return ENOSPC; /* no space, abuse of ENOSPC(!) */
|
|
}
|
|
|
|
ovltbl[i] = *data; /* copy new data string */
|
|
|
|
key2ascii[data->keynum].type |= KBD_OVERLOAD; /* mark key */
|
|
key2ascii[data->keynum].ovlindex = i;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* keyboard ioctl's entry
|
|
*---------------------------------------------------------------------------*/
|
|
int
|
|
kbdioctl(Dev_t dev, int cmd, caddr_t data, int flag)
|
|
{
|
|
int key;
|
|
|
|
switch(cmd)
|
|
{
|
|
case KBDRESET:
|
|
doreset();
|
|
ovlinit(1);
|
|
settpmrate(KBD_TPD500|KBD_TPM100);
|
|
setlockkeys(0);
|
|
break;
|
|
|
|
case KBDGTPMAT:
|
|
*(int *)data = tpmrate;
|
|
break;
|
|
|
|
case KBDSTPMAT:
|
|
settpmrate(*(int *)data);
|
|
break;
|
|
|
|
case KBDGREPSW:
|
|
*(int *)data = kbrepflag;
|
|
break;
|
|
|
|
case KBDSREPSW:
|
|
kbrepflag = (*(int *)data) & 1;
|
|
break;
|
|
|
|
case KBDGLEDS:
|
|
*(int *)data = ledstate;
|
|
break;
|
|
|
|
case KBDSLEDS:
|
|
update_led(); /* ??? */
|
|
break;
|
|
|
|
case KBDGLOCK:
|
|
*(int *)data = ( (vsp->scroll_lock) |
|
|
(vsp->num_lock * 2) |
|
|
(vsp->caps_lock * 4));
|
|
break;
|
|
|
|
case KBDSLOCK:
|
|
setlockkeys(*(int *)data);
|
|
break;
|
|
|
|
case KBDGCKEY:
|
|
key = ((Ovl_tbl *)data)->keynum;
|
|
return getckeydef(key,(Ovl_tbl *)data);
|
|
|
|
case KBDSCKEY:
|
|
key = ((Ovl_tbl *)data)->keynum;
|
|
return setkeydef((Ovl_tbl *)data);
|
|
|
|
case KBDGOKEY:
|
|
key = ((Ovl_tbl *)data)->keynum;
|
|
return getokeydef(key,(Ovl_tbl *)data);
|
|
|
|
case KBDRMKEY:
|
|
key = *(int *)data;
|
|
return rmkeydef(key);
|
|
|
|
case KBDDEFAULT:
|
|
ovlinit(1);
|
|
break;
|
|
|
|
default:
|
|
/* proceed with vga ioctls */
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#if PCVT_EMU_MOUSE
|
|
/*--------------------------------------------------------------------------*
|
|
* mouse emulator ioctl
|
|
*--------------------------------------------------------------------------*/
|
|
int
|
|
mouse_ioctl(Dev_t dev, int cmd, caddr_t data)
|
|
{
|
|
struct mousedefs *def = (struct mousedefs *)data;
|
|
|
|
switch(cmd)
|
|
{
|
|
case KBDMOUSEGET:
|
|
*def = mousedef;
|
|
break;
|
|
|
|
case KBDMOUSESET:
|
|
mousedef = *def;
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif /* PCVT_EMU_MOUSE */
|
|
|
|
#if PCVT_USL_VT_COMPAT
|
|
/*---------------------------------------------------------------------------*
|
|
* convert ISO-8859 style keycode into IBM 437
|
|
*---------------------------------------------------------------------------*/
|
|
static inline u_char
|
|
iso2ibm(u_char c)
|
|
{
|
|
if(c < 0x80)
|
|
return c;
|
|
return iso2ibm437[c - 0x80];
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* build up a USL style keyboard map
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
get_usl_keymap(keymap_t *map)
|
|
{
|
|
int i;
|
|
|
|
bzero((caddr_t)map, sizeof(keymap_t));
|
|
|
|
map->n_keys = 0x59; /* that many keys we know about */
|
|
|
|
for(i = 1; i < N_KEYNUMS; i++)
|
|
{
|
|
Ovl_tbl kdef;
|
|
u_char c;
|
|
int j;
|
|
int idx = key2scan1[i];
|
|
|
|
if(idx == 0 || idx >= map->n_keys)
|
|
continue;
|
|
|
|
getckeydef(i, &kdef);
|
|
kdef.type &= KBD_MASK;
|
|
switch(kdef.type)
|
|
{
|
|
case KBD_ASCII:
|
|
case KBD_RETURN:
|
|
map->key[idx].map[0] = iso2ibm(kdef.unshift[0]);
|
|
map->key[idx].map[1] = iso2ibm(kdef.shift[0]);
|
|
map->key[idx].map[2] = map->key[idx].map[3] =
|
|
iso2ibm(kdef.ctrl[0]);
|
|
map->key[idx].map[4] = map->key[idx].map[5] =
|
|
iso2ibm(c = kdef.altgr[0]);
|
|
/*
|
|
* XXX this is a hack
|
|
* since we currently do not map strings to AltGr +
|
|
* shift, we attempt to use the unshifted AltGr
|
|
* definition here and try to toggle the case
|
|
* this should at least work for ISO8859 letters,
|
|
* but also for (e.g.) russian KOI-8 style
|
|
*/
|
|
if((c & 0x7f) >= 0x40)
|
|
map->key[idx].map[5] = iso2ibm(c ^ 0x20);
|
|
break;
|
|
|
|
case KBD_FUNC:
|
|
/* we are only interested in F1 thru F12 here */
|
|
if(i >= 112 && i <= 123) {
|
|
map->key[idx].map[0] = i - 112 + 27;
|
|
map->key[idx].spcl = 0x80;
|
|
}
|
|
break;
|
|
|
|
case KBD_SHIFT:
|
|
c = i == 44? 2 /* lSh */: 3 /* rSh */; goto special;
|
|
|
|
case KBD_CAPS:
|
|
c = 4; goto special;
|
|
|
|
case KBD_NUM:
|
|
c = 5; goto special;
|
|
|
|
case KBD_SCROLL:
|
|
c = 6; goto special;
|
|
|
|
case KBD_META:
|
|
c = 7; goto special;
|
|
|
|
case KBD_CTL:
|
|
c = 9; goto special;
|
|
special:
|
|
for(j = 0; j < NUM_STATES; j++)
|
|
map->key[idx].map[j] = c;
|
|
map->key[idx].spcl = 0xff;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* PCVT_USL_VT_COMPAT */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* switch keypad to numeric mode
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
vt_keynum(struct video_state *svsp)
|
|
{
|
|
svsp->num_lock = 1;
|
|
update_led();
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* switch keypad to application mode
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
vt_keyappl(struct video_state *svsp)
|
|
{
|
|
svsp->num_lock = 0;
|
|
update_led();
|
|
}
|
|
|
|
#if !PCVT_VT220KEYB /* !PCVT_VT220KEYB, HP-like Keyboard layout */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 1
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey1(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if((vsp->vt_pure_mode == M_HPVT)
|
|
&& (vsp->which_fkl == SYS_FKL))
|
|
toggl_columns(vsp);
|
|
else
|
|
more_chars = (u_char *)"\033[17~"; /* F6 */
|
|
}
|
|
else
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT
|
|
|| (vsp->which_fkl == USR_FKL))
|
|
more_chars = (u_char *)"\033[26~"; /* F14 */
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 2
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey2(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if((vsp->vt_pure_mode == M_HPVT)
|
|
&& (vsp->which_fkl == SYS_FKL))
|
|
vt_ris(vsp);
|
|
else
|
|
more_chars = (u_char *)"\033[18~"; /* F7 */
|
|
}
|
|
else
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT
|
|
|| (vsp->which_fkl == USR_FKL))
|
|
more_chars = (u_char *)"\033[28~"; /* HELP */
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 3
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey3(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if((vsp->vt_pure_mode == M_HPVT)
|
|
&& (vsp->which_fkl == SYS_FKL))
|
|
toggl_24l(vsp);
|
|
else
|
|
more_chars = (u_char *)"\033[19~"; /* F8 */
|
|
}
|
|
else
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT
|
|
|| (vsp->which_fkl == USR_FKL))
|
|
more_chars = (u_char *)"\033[29~"; /* DO */
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 4
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey4(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
|
|
#if PCVT_SHOWKEYS
|
|
if((vsp->vt_pure_mode == M_HPVT)
|
|
&& (vsp->which_fkl == SYS_FKL))
|
|
toggl_kbddbg(vsp);
|
|
else
|
|
more_chars = (u_char *)"\033[20~"; /* F9 */
|
|
#else
|
|
if(vsp->vt_pure_mode == M_PUREVT
|
|
|| (vsp->which_fkl == USR_FKL))
|
|
more_chars = (u_char *)"\033[20~"; /* F9 */
|
|
#endif /* PCVT_SHOWKEYS */
|
|
|
|
}
|
|
else
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT
|
|
|| (vsp->which_fkl == USR_FKL))
|
|
more_chars = (u_char *)"\033[31~"; /* F17 */
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 5
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey5(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if((vsp->vt_pure_mode == M_HPVT)
|
|
&& (vsp->which_fkl == SYS_FKL))
|
|
toggl_bell(vsp);
|
|
else
|
|
more_chars = (u_char *)"\033[21~"; /* F10 */
|
|
}
|
|
else
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT
|
|
|| (vsp->which_fkl == USR_FKL))
|
|
more_chars = (u_char *)"\033[32~"; /* F18 */
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 6
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey6(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if((vsp->vt_pure_mode == M_HPVT)
|
|
&& (vsp->which_fkl == SYS_FKL))
|
|
toggl_sevenbit(vsp);
|
|
else
|
|
more_chars = (u_char *)"\033[23~"; /* F11 */
|
|
}
|
|
else
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT
|
|
|| (vsp->which_fkl == USR_FKL))
|
|
more_chars = (u_char *)"\033[33~"; /* F19 */
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 7
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey7(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if((vsp->vt_pure_mode == M_HPVT)
|
|
&& (vsp->which_fkl == SYS_FKL))
|
|
toggl_dspf(vsp);
|
|
else
|
|
more_chars = (u_char *)"\033[24~"; /* F12 */
|
|
}
|
|
else
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT
|
|
|| (vsp->which_fkl == USR_FKL))
|
|
more_chars = (u_char *)"\033[34~"; /* F20 */
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 8
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey8(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if((vsp->vt_pure_mode == M_HPVT)
|
|
&& (vsp->which_fkl == SYS_FKL))
|
|
toggl_awm(vsp);
|
|
else
|
|
more_chars = (u_char *)"\033[25~"; /* F13 */
|
|
}
|
|
else
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT
|
|
|| (vsp->which_fkl == USR_FKL))
|
|
more_chars = (u_char *)"\033[35~"; /* F21 ??!! */
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 9
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey9(void)
|
|
{
|
|
if(meta_down)
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT)
|
|
return;
|
|
|
|
if(vsp->labels_on) /* toggle label display on/off */
|
|
fkl_off(vsp);
|
|
else
|
|
fkl_on(vsp);
|
|
}
|
|
else
|
|
{
|
|
do_vgapage(0);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 10
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey10(void)
|
|
{
|
|
if(meta_down)
|
|
{
|
|
if(vsp->vt_pure_mode != M_PUREVT && vsp->labels_on)
|
|
{
|
|
if(vsp->which_fkl == USR_FKL)
|
|
sw_sfkl(vsp);
|
|
else if(vsp->which_fkl == SYS_FKL)
|
|
sw_ufkl(vsp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
do_vgapage(1);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 11
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey11(void)
|
|
{
|
|
if(meta_down)
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT)
|
|
set_emulation_mode(vsp, M_HPVT);
|
|
else if(vsp->vt_pure_mode == M_HPVT)
|
|
set_emulation_mode(vsp, M_PUREVT);
|
|
}
|
|
else
|
|
{
|
|
do_vgapage(2);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 12
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey12(void)
|
|
{
|
|
if(meta_down)
|
|
{
|
|
if(current_video_screen + 1 > totalscreens-1)
|
|
do_vgapage(0);
|
|
else
|
|
do_vgapage(current_video_screen + 1);
|
|
}
|
|
else
|
|
{
|
|
do_vgapage(3);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 1
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey1(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[0]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[0]]);
|
|
}
|
|
else
|
|
{
|
|
if(vsp->ukt.length[9]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[9]]);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 2
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey2(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[1]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[1]]);
|
|
}
|
|
else
|
|
{
|
|
if(vsp->ukt.length[11]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[11]]);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 3
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey3(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[2]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[2]]);
|
|
}
|
|
else
|
|
{
|
|
if(vsp->ukt.length[12]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[12]]);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 4
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey4(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[3]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[3]]);
|
|
}
|
|
else
|
|
{
|
|
if(vsp->ukt.length[13]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[13]]);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 5
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey5(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[4]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[4]]);
|
|
}
|
|
else
|
|
{
|
|
if(vsp->ukt.length[14]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[14]]);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 6
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey6(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[6]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[6]]);
|
|
}
|
|
else
|
|
{
|
|
if(vsp->ukt.length[15]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[15]]);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 7
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey7(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[7]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[7]]);
|
|
}
|
|
else
|
|
{
|
|
if(vsp->ukt.length[16]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[16]]);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 8
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey8(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[8]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[8]]);
|
|
}
|
|
else
|
|
{
|
|
if(vsp->ukt.length[17]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[17]]);
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 9
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey9(void)
|
|
{
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 10
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey10(void)
|
|
{
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 11
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey11(void)
|
|
{
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 12
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey12(void)
|
|
{
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 1
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey1(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(0);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 2
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey2(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(1);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 3
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey3(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(2);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 4
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey4(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(3);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 5
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey5(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(4);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 6
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey6(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(5);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 7
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey7(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(6);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 8
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey8(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(7);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 9
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey9(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(8);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 10
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey10(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(9);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 11
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey11(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(10);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 12
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey12(void)
|
|
{
|
|
if(meta_down)
|
|
do_vgapage(11);
|
|
}
|
|
|
|
#else /* PCVT_VT220 - VT220-like Keyboard layout */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 1
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey1(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\033[23~"; /* F11 */
|
|
else
|
|
do_vgapage(0);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 2
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey2(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\033[24~"; /* F12 */
|
|
else
|
|
do_vgapage(1);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 3
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey3(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\033[25~"; /* F13 */
|
|
else
|
|
do_vgapage(2);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 4
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey4(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\033[26~"; /* F14 */
|
|
else
|
|
do_vgapage(3);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 5
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey5(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\033[28~"; /* Help */
|
|
else
|
|
{
|
|
if((current_video_screen + 1) > totalscreens-1)
|
|
do_vgapage(0);
|
|
else
|
|
do_vgapage(current_video_screen + 1);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 6
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey6(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\033[29~"; /* DO */
|
|
else
|
|
more_chars = (u_char *)"\033[17~"; /* F6 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 7
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey7(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\033[31~"; /* F17 */
|
|
else
|
|
more_chars = (u_char *)"\033[18~"; /* F7 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 8
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey8(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\033[32~"; /* F18 */
|
|
else
|
|
more_chars = (u_char *)"\033[19~"; /* F8 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 9
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey9(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\033[33~"; /* F19 */
|
|
else
|
|
more_chars = (u_char *)"\033[20~"; /* F9 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 10
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey10(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\033[34~"; /* F20 */
|
|
else
|
|
more_chars = (u_char *)"\033[21~"; /* F10 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 11
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey11(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\0x8FP"; /* PF1 */
|
|
else
|
|
more_chars = (u_char *)"\033[23~"; /* F11 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to function key 12
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
fkey12(void)
|
|
{
|
|
if(meta_down)
|
|
more_chars = (u_char *)"\0x8FQ"; /* PF2 */
|
|
else
|
|
more_chars = (u_char *)"\033[24~"; /* F12 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 1
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey1(void)
|
|
{
|
|
if(meta_down)
|
|
{
|
|
if(vsp->ukt.length[6]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[6]]);
|
|
else
|
|
more_chars = (u_char *)"\033[23~"; /* F11 */
|
|
}
|
|
else
|
|
{
|
|
do_vgapage(4);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 2
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey2(void)
|
|
{
|
|
if(meta_down)
|
|
{
|
|
if(vsp->ukt.length[7]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[7]]);
|
|
else
|
|
more_chars = (u_char *)"\033[24~"; /* F12 */
|
|
}
|
|
else
|
|
{
|
|
do_vgapage(5);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 3
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey3(void)
|
|
{
|
|
if(meta_down)
|
|
{
|
|
if(vsp->ukt.length[8]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[8]]);
|
|
else
|
|
more_chars = (u_char *)"\033[25~"; /* F13 */
|
|
}
|
|
else
|
|
{
|
|
do_vgapage(6);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 4
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey4(void)
|
|
{
|
|
if(meta_down)
|
|
{
|
|
if(vsp->ukt.length[9]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[9]]);
|
|
else
|
|
more_chars = (u_char *)"\033[26~"; /* F14 */
|
|
}
|
|
else
|
|
{
|
|
do_vgapage(7);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 5
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey5(void)
|
|
{
|
|
if(meta_down)
|
|
{
|
|
if(vsp->ukt.length[11]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[11]]);
|
|
else
|
|
more_chars = (u_char *)"\033[28~"; /* Help */
|
|
}
|
|
else
|
|
{
|
|
if(current_video_screen <= 0)
|
|
do_vgapage(totalscreens-1);
|
|
else
|
|
do_vgapage(current_video_screen - 1);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 6
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey6(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[0]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[0]]);
|
|
else
|
|
more_chars = (u_char *)"\033[17~"; /* F6 */
|
|
}
|
|
else if(vsp->ukt.length[12]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[12]]);
|
|
else
|
|
more_chars = (u_char *)"\033[29~"; /* DO */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 7
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey7(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[1]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[1]]);
|
|
else
|
|
more_chars = (u_char *)"\033[18~"; /* F7 */
|
|
}
|
|
else if(vsp->ukt.length[14]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[14]]);
|
|
else
|
|
more_chars = (u_char *)"\033[31~"; /* F17 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 8
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey8(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[2]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[2]]);
|
|
else
|
|
more_chars = (u_char *)"\033[19~"; /* F8 */
|
|
}
|
|
else if(vsp->ukt.length[14]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[15]]);
|
|
else
|
|
more_chars = (u_char *)"\033[32~"; /* F18 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 9
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey9(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[3]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[3]]);
|
|
else
|
|
more_chars = (u_char *)"\033[20~"; /* F9 */
|
|
}
|
|
else if(vsp->ukt.length[16]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[16]]);
|
|
else
|
|
more_chars = (u_char *)"\033[33~"; /* F19 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 10
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey10(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[4]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[4]]);
|
|
else
|
|
more_chars = (u_char *)"\033[21~"; /* F10 */
|
|
}
|
|
else if(vsp->ukt.length[17]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[17]]);
|
|
else
|
|
more_chars = (u_char *)"\033[34~"; /* F20 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 11
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey11(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[6]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[6]]);
|
|
else
|
|
more_chars = (u_char *)"\033[23~"; /* F11 */
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to SHIFTED function key 12
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
sfkey12(void)
|
|
{
|
|
if(!meta_down)
|
|
{
|
|
if(vsp->ukt.length[7]) /* entry available ? */
|
|
more_chars = (u_char *)
|
|
&(vsp->udkbuf[vsp->ukt.first[7]]);
|
|
else
|
|
more_chars = (u_char *)"\033[24~"; /* F12 */
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 1
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey1(void)
|
|
{
|
|
if(vsp->which_fkl == SYS_FKL)
|
|
toggl_columns(vsp);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 2
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey2(void)
|
|
{
|
|
if(vsp->which_fkl == SYS_FKL)
|
|
vt_ris(vsp);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 3
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey3(void)
|
|
{
|
|
if(vsp->which_fkl == SYS_FKL)
|
|
toggl_24l(vsp);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 4
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey4(void)
|
|
{
|
|
|
|
#if PCVT_SHOWKEYS
|
|
if(vsp->which_fkl == SYS_FKL)
|
|
toggl_kbddbg(vsp);
|
|
#endif /* PCVT_SHOWKEYS */
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 5
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey5(void)
|
|
{
|
|
if(vsp->which_fkl == SYS_FKL)
|
|
toggl_bell(vsp);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 6
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey6(void)
|
|
{
|
|
if(vsp->which_fkl == SYS_FKL)
|
|
toggl_sevenbit(vsp);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 7
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey7(void)
|
|
{
|
|
if(vsp->which_fkl == SYS_FKL)
|
|
toggl_dspf(vsp);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 8
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey8(void)
|
|
{
|
|
if(vsp->which_fkl == SYS_FKL)
|
|
toggl_awm(vsp);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 9
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey9(void)
|
|
{
|
|
if(vsp->labels_on) /* toggle label display on/off */
|
|
fkl_off(vsp);
|
|
else
|
|
fkl_on(vsp);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 10
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey10(void)
|
|
{
|
|
if(vsp->labels_on) /* toggle user/system fkey labels */
|
|
{
|
|
if(vsp->which_fkl == USR_FKL)
|
|
sw_sfkl(vsp);
|
|
else if(vsp->which_fkl == SYS_FKL)
|
|
sw_ufkl(vsp);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 11
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey11(void)
|
|
{
|
|
if(vsp->vt_pure_mode == M_PUREVT)
|
|
set_emulation_mode(vsp, M_HPVT);
|
|
else if(vsp->vt_pure_mode == M_HPVT)
|
|
set_emulation_mode(vsp, M_PUREVT);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* function bound to control function key 12
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
cfkey12(void)
|
|
{
|
|
}
|
|
|
|
#endif /* PCVT_VT220KEYB */
|
|
|
|
#endif /* NVT > 0 */
|
|
|
|
/* ------------------------------- EOF -------------------------------------*/
|