* - loads a specific national keyboard mapping into the
* - displays the current mapping
* - sets/displays key repetition rate
* - enables/disables screensaver
* Contributed to 386bsd 0.1 and later versions
* Copyright 1992,1993 by Holger Veit
* May be freely used with Bill Jolitz's port of
* 386bsd and may be included in a 386bsd collection
* as long as binary and source are available and reproduce the above
* You may freely modify this code and contribute improvements based
* on this code as long as you don't claim to be the original author.
* Commercial use of this source requires permittance of the copyright
* holder. A general license for 386bsd will override this restriction.
* Use at your own risk. The copyright holder or any person who makes
* this code available for the public (administrators of public archives
* for instance) are not responsible for any harm to hardware or software
* that might happen due to wrong application or program faults.
* You must have the codriver driver in the same package generated
* into the 386bsd kernel, otherwise this program does not work.
* @(#)keymap.c 1.1 (386bsd contribution) 24-oct-92
/* Oh, this has become a hack, this could have been done better. hv */
* 29/07/92 -hv- First version
* 24/10/92 -hv- fixes + screensaver
* 01/12/92-vak- -T and -a flags, new output format,
* new keycap extensions for Meta and ShiftAltgr keys.
* 04/27/93 -hv- extensions for special function keys
* keymap [-l] [-t+|-t-] [-d#] [-r#] [-m mapping]
* keymap -a "keydef" keyid
* -l list the current key mapping
* -t+ enable key repetition (typematic)
* -t- disable key repetion
* -d# set delay after which a key is repeated (includes -t+)
* -r# set rate of repetition of keys (includes -t+)
* -s# set screensaver timeout (in seconds, 0 to disable)
* -m mapping load a key map from the keycap file
#include <sys/ioctl_pc.h>
extern int kgetent(char*, char*);
extern int kgetnum(char*);
extern int kgetflag(char*);
extern char *kgetstr(char*,char**);
struct kbd_ovlkey kmap
[128];
main(int argc
,char *argv
[])
while ((c
=getopt(argc
,argv
,"lTat:d:r:m:s:"))!=EOF
) {
if ((lf
+tf
+df
+rf
+mf
+sf
+Tf
+af
)==0)
if (Tf
&& (lf
+tf
+df
+rf
+mf
+sf
+af
)!=0)
if ((lf
+tf
+df
+rf
+mf
+sf
+Tf
)!=0)
/* we use /dev/kbd here, because this will block if the keymap
* command is tried from an xterm. Use xmodmap/xset for these
if ((kbd
=open(_PATH_KEYBOARD
, 0)) < 0)
else if (af
) assign (argv
[optind
], argv
[optind
+1]);
if (tf
|| df
|| rf
) tpm(tf
,delay
,rate
);
fprintf(stderr
,"%s: ",progname
);
fprintf(stderr
,"%s: %s\n",progname
,msg
);
fprintf (stderr
, "Usage:\n");
fprintf (stderr
, "\t%s [-l] [-t+|-t-] [-d#] [-r#] [-s#] [-m mapping]\n",
fprintf (stderr
, "\t -l list the current keyboard map\n");
fprintf (stderr
, "\t -t[+-] enable/disable key repetition\n");
fprintf (stderr
, "\t -d# set key repetition delay, 0..3 * 250ms\n");
fprintf (stderr
, "\t -r# set key repetition rate, 0..31, 0 fastest\n");
fprintf (stderr
, "\t -s# set screen saver delay, in seconds\n");
fprintf (stderr
, "\t -m ent remap keyboard according to the keycap(5) entry\n");
fprintf (stderr
, "or\n\t%s -T\n", progname
);
fprintf (stderr
, "\t test key codes\n");
fprintf (stderr
, "or\n\t%s -a \"keydef\" keyid\n", progname
);
fprintf (stderr
, "\t remap the single keyid, F1..F12, KP0..KP9, KP+..KP/, or 0xNUM\n");
fprintf (stderr
, "\t with zero or one prefix: SHIFT-, CTRL-, ALTGR-, META\n");
static char *type2str
[] = {
if (s
[i
]>' ' && s
[i
]<0177) {
} else if ((s
[i
] & 0xff) < ' ')
sprintf(s2
, "^%c", s
[i
]+'@');
sprintf(s2
, "\\%03o", s
[i
] & 0xff);
for (i
=0, ke
=kmap
; i
<128; ke
++,i
++) {
if (ioctl(kbd
,KBDGCKEY
,ke
)<0)
/* scan the saved keys */
for (i
=0, ke
=kmap
; i
<128; ke
++,i
++) {
switch (ke
->type
& KBD_MASK
) {
/* get the entry of key 0. This is a nonexisting key for some
* reasons, so we can use it to hold the current keyboard name
printf("Current mapping is: %s\n",kmap
[0].unshift
);
printf(" # type unshift shifted ctrl meta");
printf(" altgr shiftaltgr");
for (i
=1, ke
=&kmap
[1]; i
<128; ke
++,i
++) {
printf("%3d%c %8s", i
, (kt
& KBD_OVERLOAD
) ? '*' : ' ',
type2str
[kt
& KBD_MASK
]);
printf("%c%-10s", (kt
& KBD_DOCAPS
) ? '~' : ' ',
printf(" %-10s", trl (ke
->shift
));
else if ((kt
&KBD_MASK
) == KBD_ASCII
||
(kt
&KBD_MASK
) == KBD_FUNC
)
p
= (char*)trl (ke
->meta
);
else if ((kt
&KBD_MASK
) == KBD_ASCII
||
(kt
&KBD_MASK
) == KBD_FUNC
) {
XCHAR buf
[KBDMAXOVLKEYSIZE
+1];
XC_strcpy (buf
, ke
->unshift
);
if (has_altgr
&& ke
->altgr
[0]) {
printf("%c%-10s", (kt
& KBD_DOALTCAPS
) ? '~' : ' ',
printf(" %s", trl (ke
->shiftaltgr
));
tpm(int onoff
, int delay
, int rate
)
if (ioctl(kbd
,KBDSREPSW
,&tpm_sw
)<0)
fatal("Set key repetition OFF");
if (ioctl(kbd
,KBDSREPSW
,&tpm_sw
)<0)
fatal("Set key repetition ON");
/* do we need to set new values */
if (delay
== -1 && rate
== -1) return;
/* get current setting */
if (ioctl(kbd
,KBDGTPMAT
,¤t_tpm
)<0)
fatal("Get typematic value");
delay
= (delay
== -1) ? (current_tpm
& 0x60) : ((delay
& 0x3)<<5);
rate
= (rate
== -1) ? (current_tpm
& 0x1F) : (rate
& 0x1F);
/* set the new setting */
if (ioctl(kbd
,KBDSTPMAT
,&new_tpm
)<0)
fatal("Set typematic value");
if ((fv
=open(_PATH_VIDEO
,0)) <= 0)
fatal("Open video device");
if (ioctl(fv
,VGASBLANK
,&stime
)<0)
fatal("Set timeout value");
error("Duplicate key def");
int m0flag
=0,a0flag
,c0flag
,ledflag
,clflag
;
&key
.unshift
[0], 'K', KBD_EXT_N
,
&key
.shift
[0], 'S', KBD_EXT_S
,
&key
.ctrl
[0], 'C', KBD_EXT_C
,
&key
.meta
[0], 'M', KBD_EXT_SK
,
&key
.altgr
[0], 'A', KBD_EXT_A
,
&key
.shiftaltgr
[0], 'X', KBD_EXT_CA
,
/* try to find the entry */
switch(kgetent(cap
,map
)) {
error("Keycap database not found");
error("No such keymap entry");
/* set default mapping */
if (ioctl(kbd
,KBDDEFAULT
)<0)
error("Cannot reset to default mapping");
if (kgetflag("de")) return;
/* Caps LED assignments */
for (i
=0; i
<128; i
++) keyflag
[i
] = 0;
/* check for locking keys */
for (k
=0; k
<NLOCKKEYS
; k
++) {
sprintf(code
,"%s",lockkeys
[k
].ch
);
key
.type
= lockkeys
[k
].typ
;
if (ioctl(kbd
,KBDSCKEY
,&key
)<0)
error("Cannot set lockkey");
/* check for special keys */
for (k
=0; k
<NSPECIAL
; k
++) {
sprintf(code
,"%c%d",special
[k
].ch
,i
);
key
.type
= special
[k
].typ
;
if (ioctl(kbd
,KBDSCKEY
,&key
)<0)
error("Cannot set specialkey");
/* check diacritical flags */
/* handle and collect standard keys */
if (ioctl(kbd
,KBDGOKEY
,&key
)<0)
error("Cannot get key setting");
/* XXX this will defeat the different semantic of
* KBD_KP, KBD_ASCII, etc. Will be corrected some day
for (k
=0; k
<9 && diac
[k
]; k
++)
for (k
=0; k
<NSTANDARD
; k
++) {
sprintf(code
,"%c%d",standard
[k
].ch
,i
);
if (k
==0 && kgetflag(code
)) {
if (ap1
=kgetstr(code
,(char**)&ap
)) {
if (strlen(ap1
)>KBDMAXOVLKEYSIZE
)
error("String too long in keymap");
/* process alphalock flag */
} else if (ap
==key
.altgr
) {
key
.type
|= KBD_DOALTCAPS
;
/* process special hotkeys */
case '-': func
= KBD_HOTKEYDELETE
; break;
case 'R': func
= KBD_RESETKEY
; break;
case 'D': func
= KBD_DEBUGKEY
; break;
case 'P': func
= KBD_VTYDOWN
; break;
case 'N': func
= KBD_VTYUP
; break;
case 'B': func
= KBD_VTY11
; break;
case 'A': func
= KBD_VTY10
; break;
if (ap
[1]>='0' && ap
[1]<=9)
/* convert the layer to trigger */
if (modifier
) modifier
= standard
[k
].modifier
;
if (ioctl(kbd
,KBDSSPECF
,&s
) <0)
error("KBDSSPECF ioctl failed");
key
.meta
[0] = key
.unshift
[0] ^ 0x80;
if (ioctl(kbd
,KBDSCKEY
,&key
)<0)
error("Cannot set stdkey");
/* set the behavior for unassigned keys (clear layer) */
clflag
= a0flag
| (c0flag
<<1) | (m0flag
<<2);
if (ioctl(kbd
,KBDSCLRLYR
,&clflag
) < 0)
error("KBDSCLRLYR ioctl failed");
/* now mark the current keyboard setting in the 0 entry */
XC_strncpy(key
.unshift
,map
,KBDMAXOVLKEYSIZE
);
key
.unshift
[KBDMAXOVLKEYSIZE
] = 0;
if (ioctl(kbd
,KBDSCKEY
,&key
)<0)
error("Cannot set keymap code");
if (ioctl(kbd
,KBDSCAPSLED
,&ledflag
)<0)
error("Cannot assign LEDs");
if (setfont(fp
,1,0)) return;
if (setfont(fp
,1,1)) return;
* simple program to test KEY NUMBERS
* leave this program by hitting the ESC key twice, followed by the SPACE bar
/* should be fixed on all keyboards */
printf ("Key number test.\n");
printf ("Press different combinations of keys.\n");
printf ("Leave program with sequence ESC,ESC,SPACE (with release).\n");
if (read (kbd
, &c
, 1) != 1)
printf ("Got key %02x %s\n", c
& 0xff,
c
& 0x80 ? "(release)" : "");
#define SHIFTALTFLAG 0x0800
/* The code in codrv uses a double \0\0 to identify a NULL byte to return
* from a pressed key, but we want to have nothing for this key, and
* don't want to disable this key entirely
static XCHAR notanullbyte
[] = { 0,-1,0 };
#define NOTANULLBYTE notanullbyte
else { /* start parsing backslash */
/* could add some more here */
for (i
=n
=0; i
<3; i
++,p
++) {
if (*p
>='0' && *p
<='9') {
struct kbd_ovlkey keynow
,keyorg
;
if (strlen(keydef
) > 15) {
fprintf(stderr
,"%s: String \"%s\" too long\n",
keynum
= def2num(keycode
);
fprintf(stderr
,"%s: No such key: \"%s\"\n",
/* check whether the key should be deleted or returned to default */
if (!strcmp(keydef
,"DEFAULT")) defflag
= 1;
else if (!strcmp(keydef
,"DELETE")) delflag
= 1;
keydef
= parse_bsl(keydef
);
keynow
.keynum
= keyorg
.keynum
= keynum
& 0x7F;
if (ioctl(kbd
,KBDGCKEY
,&keynow
)<0 ||
ioctl(kbd
,KBDGOKEY
,&keyorg
)<0) {
XC_strncpy(keynow
.shift
,NOTANULLBYTE
,3);
XC_strcpy(keynow
.shift
,keyorg
.shift
);
XC_strcpy(keynow
.shift
,keydef
);
XC_strncpy(keynow
.meta
,NOTANULLBYTE
,3);
XC_strcpy(keynow
.meta
,keyorg
.meta
);
XC_strcpy(keynow
.meta
,keydef
);
XC_strncpy(keynow
.ctrl
,NOTANULLBYTE
,3);
XC_strcpy(keynow
.ctrl
,keyorg
.ctrl
);
XC_strcpy(keynow
.ctrl
,keydef
);
XC_strncpy(keynow
.altgr
,NOTANULLBYTE
,3);
XC_strcpy(keynow
.altgr
,keyorg
.altgr
);
XC_strcpy(keynow
.altgr
,keydef
);
XC_strncpy(keynow
.shiftaltgr
,NOTANULLBYTE
,3);
XC_strcpy(keynow
.shiftaltgr
,keyorg
.shiftaltgr
);
XC_strcpy(keynow
.shiftaltgr
,keydef
);
XC_strncpy(keynow
.unshift
,NOTANULLBYTE
,3);
XC_strcpy(keynow
.unshift
,keyorg
.unshift
);
XC_strcpy(keynow
.unshift
,keydef
);
if (ioctl(kbd
,KBDSCKEY
,&keynow
)<0) {
/* std. */ /* X11 naming */
"kp.", 104, "kp_decimal", 104,
"kp+", 106, "kp_add", 106,
"kp-", 105, "kp_subtract", 105,
"kp*", 100, "kp_multiply", 100,
"kp/", 95, "kp_divide", 95,
"shiftaltgr", SHIFTALTFLAG
,
/* and some misspellings: */
char *token
,*strtok(),*ep
;
token
= strtok(keycode
,"-");
if (ep
!=token
) { /* got a number */
for (i
=0; tbl
[i
].str
; i
++) {
if (!strcasecmp(keycode
,tbl
[i
].str
)) {
if (tbl
[i
].num
< 128) flag2
++;
if (flag1
> 1 || flag2
!= 1) return -1;
if ((keynum
& 0x7F)==0) return -1;