From: brad@Cayman.COM (Brad Parker)
Newsgroups: comp.unix.bsd
Subject: new ioctl for keyboard flags
Date: 21 Jul 92 13:55:35 GMT
Organization: Cayman Systems Inc., Cambridge, MA


I was tired of the caps lock key not being a control key and the shift key
makeing "control+'-'" not work, so I added to ioctl's and a wrote a little
program to wack the "keyboard flags".  It also allows you to change the
cursor from "fat" to "slim".  This was the simplest way I could find to
affect the desired result.

I have heard to SCO and other 386 unixes have up to three (3!) levels of
keyboard mapping which makes doing things like this easier.
The kern/pccons.c code looks like it wants to go this direction, but is not
quite there yet.

oh yes, this also fixes a bug where "control+'2'" would not produce the
desired "0x0" code.  Since 0x0 is overloaded already in the map to mean
"end of string", I overload 0xff to mean "send 0x0". hi ho.

-brad


--- cut here ---
#!/bin/sh
# This is a shell archive (shar 3.47)
# made 07/21/1992 13:42 UTC by brad@haiti
# Source directory /tmp_mnt/home/caicos/brad/pccons
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#    105 -rw-r--r-- Makefile
#   4472 -rw-r--r-- diffs
#   1044 -r--r--r-- pccons.8
#   1604 -rw-r--r-- pccons.c
#
# ============= Makefile ==============
if test -f 'Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping Makefile (File already exists)'
else
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
#
X
PROG=	pccons
MAN8=	pccons.0
BINDIR=	/usr/local/bin
MANDIR=	/usr/local/man/man
X
.include <bsd.prog.mk>
SHAR_EOF
chmod 0644 Makefile ||
echo 'restore of Makefile failed'
Wc_c="`wc -c < 'Makefile'`"
test 105 -eq "$Wc_c" ||
	echo 'Makefile: original size 105, current size' "$Wc_c"
fi
# ============= diffs ==============
if test -f 'diffs' -a X"$1" != X"-c"; then
	echo 'x - skipping diffs (File already exists)'
else
echo 'x - extracting diffs (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'diffs' &&
*** pccons.c.orig	Sun Jul 19 05:22:34 1992
--- pccons.c	Sun Jul 19 07:27:25 1992
***************
*** 99,108 ****
X  	pcprobe, pcattach, "pc",
X  };
X  
- /* block cursor so wfj does not go blind on laptop hunting for
- 	the verdamnt cursor -wfj */
- #define	FAT_CURSOR
- 
X  #define	COL		80
X  #define	ROW		25
X  #define	CHR		2
--- 99,104 ----
***************
*** 120,125 ****
--- 116,126 ----
X  static	char	*more_chars;
X  static	int	char_count;
X  
+ static	int	keybd_flags;
+ #define IGNORE_SHIFT		(!(keybd_flags & TIOCKEYBD_SHIFT))
+ #define IGNORE_CAPS_LOCK	(keybd_flags & TIOCKEYBD_CAPSLOCK)
+ #define FAT_CURSOR		(keybd_flags & TIOCKEYBD_CURSOR_BLOCK)
+ 
X  /*
X   * We check the console periodically to make sure
X   * that it hasn't wedged.  Unfortunately, if an XOFF
***************
*** 280,287 ****
X  #endif
X  	if (!openf)
X  		return;
! 	while (*cp)
! 		(*linesw[pccons.t_line].l_rint)(*cp++ & 0xff, &pccons);
X  }
X  
X  pcioctl(dev, cmd, data, flag)
--- 281,290 ----
X  #endif
X  	if (!openf)
X  		return;
! 	while (c = *cp++ & 0xff) {
! 		if (c == 0xff) c = 0;
! 		(*linesw[pccons.t_line].l_rint)(c, &pccons);
! 	}
X  }
X  
X  pcioctl(dev, cmd, data, flag)
***************
*** 297,302 ****
--- 300,313 ----
X  	error = ttioctl(tp, cmd, data, flag);
X  	if (error >= 0)
X  		return (error);
+ 	switch (cmd) {
+ 	case TIOCKEYBDG:
+ 	  *(int *)data = keybd_flags;
+ 	  return 0;
+ 	case TIOCKEYBDS:
+ 	  keybd_flags = *(int *)data;
+ 	  return 0;
+ 	}
X  	return (ENOTTY);
X  }
X  
***************
*** 470,481 ****
X  	outb(addr_6845+1, pos>> 8);
X  	outb(addr_6845, 15);
X  	outb(addr_6845+1, pos);
! #ifdef	FAT_CURSOR
X  	outb(addr_6845, 10);
X  	outb(addr_6845+1, 0);
X  	outb(addr_6845, 11);
X  	outb(addr_6845+1, 18);
! #endif	FAT_CURSOR
X  	if (a == 0)
X  		timeout(cursor, 0, hz/10);
X  }
--- 481,494 ----
X  	outb(addr_6845+1, pos>> 8);
X  	outb(addr_6845, 15);
X  	outb(addr_6845+1, pos);
! 
! 	if (FAT_CURSOR) {
X  	outb(addr_6845, 10);
X  	outb(addr_6845+1, 0);
X  	outb(addr_6845, 11);
X  	outb(addr_6845+1, 18);
! 	}
! 
X  	if (a == 0)
X  		timeout(cursor, 0, hz/10);
X  }
***************
*** 1095,1101 ****
X  	NONE,	"",		"",		"",		/* 0 unused */
X  	ASCII,	"\033",		"\033",		"\033",		/* 1 ESCape */
X  	ASCII,	"1",		"!",		"!",		/* 2 1 */
! 	ASCII,	"2",		"@",		"\000",		/* 3 2 */
X  	ASCII,	"3",		"#",		"#",		/* 4 3 */
X  	ASCII,	"4",		"$",		"$",		/* 5 4 */
X  	ASCII,	"5",		"%",		"%",		/* 6 5 */
--- 1108,1114 ----
X  	NONE,	"",		"",		"",		/* 0 unused */
X  	ASCII,	"\033",		"\033",		"\033",		/* 1 ESCape */
X  	ASCII,	"1",		"!",		"!",		/* 2 1 */
! 	ASCII,	"2",		"@",		"\377",		/* 3 2 */
X  	ASCII,	"3",		"#",		"#",		/* 4 3 */
X  	ASCII,	"4",		"$",		"$",		/* 5 4 */
X  	ASCII,	"5",		"%",		"%",		/* 6 5 */
***************
*** 1301,1306 ****
--- 1314,1323 ----
X  			case CTL:
X  				ctrl_down = 0;
X  				break;
+ 			case CAPS:
+ 				if (IGNORE_CAPS_LOCK)
+ 				  ctrl_down = 0;
+ 				break;
X  		}
X  	}
X  	else
***************
*** 1319,1326 ****
X  				update_led();
X  				break;
X  			case CAPS:
! 				caps ^= 1;
! 				update_led();
X  				break;
X  			case SCROLL:
X  				scroll ^= 1;
--- 1336,1346 ----
X  				update_led();
X  				break;
X  			case CAPS:
! 				if (!IGNORE_CAPS_LOCK) {
! 				  caps ^= 1;
! 				  update_led();
! 				} else
! 				  ctrl_down = 1;
X  				break;
X  			case SCROLL:
X  				scroll ^= 1;
***************
*** 1342,1349 ****
X  			case ASCII:
X  			case NONE:
X  			case FUNC:
! 				if (shift_down)
! 					more_chars = scan_codes[dt].shift;
X  				else if (ctrl_down)
X  					more_chars = scan_codes[dt].ctrl;
X  				else
--- 1362,1369 ----
X  			case ASCII:
X  			case NONE:
X  			case FUNC:
! 				if (shift_down && (IGNORE_SHIFT || !ctrl_down))
! 				    	more_chars = scan_codes[dt].shift;
X  				else if (ctrl_down)
X  					more_chars = scan_codes[dt].ctrl;
X  				else
*** ioctl.h.orig	Sun Jul 19 05:25:29 1992
--- ioctl.h	Sun Jul 19 05:55:05 1992
***************
*** 146,151 ****
--- 146,157 ----
X  #define	TIOCSIG		_IO('t', 95)		/* pty: generate signal */
X  #define TIOCDRAIN	_IO('t', 94)		/* wait till output drained */
X  
+ #define	TIOCKEYBDG	_IOR('t', 90, int)	/* get keyboard flags */
+ #define	TIOCKEYBDS	_IOW('t', 90, int)	/* set keyboard flags */
+ #define		TIOCKEYBD_SHIFT		0x01	/* shift looses to cntrl */
+ #define		TIOCKEYBD_CAPSLOCK	0x02	/* caps lock becomes shift */
+ #define		TIOCKEYBD_CURSOR_BLOCK	0x10	/* cursor is block */
+ 
X  #define TTYDISC		0		/* termios tty line discipline */
X  #define	TABLDISC	3		/* tablet discipline */
X  #define	SLIPDISC	4		/* serial IP discipline */
SHAR_EOF
chmod 0644 diffs ||
echo 'restore of diffs failed'
Wc_c="`wc -c < 'diffs'`"
test 4472 -eq "$Wc_c" ||
	echo 'diffs: original size 4472, current size' "$Wc_c"
fi
# ============= pccons.8 ==============
if test -f 'pccons.8' -a X"$1" != X"-c"; then
	echo 'x - skipping pccons.8 (File already exists)'
else
echo 'x - extracting pccons.8 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'pccons.8' &&
.\"
.\"	@(#)pccons.8
.\"
.Dd July 19, 1992
.Dt PCCONS 8
.Os
.Sh NAME
.Nm pccons
.Nd set PC console attributes
.Sh SYNOPSIS
.Nm pccons
.Op Ar options ...
.Sh DESCRIPTION
.Pp
.Nm pccons
allows the user to set, reset and view various PC console attributes
by name.
.Ar options
are words describing each attribute.  If an option is "negated" with
a "-",  the option is turned off.
.Pp
The following options are available:
.Bl -tag -width flag
.It shift
Ignore the shift key if the control key is pressed.  Helpful for
hitting keys like "control+shift+underscore".
.It caps-lock
Turn the "CapsLock" key into a substitute for the "control" key.
.It block-cursor
Make the cursor into a large block.  Helpful for LCD screens with poor
contrast.
.El
.Sh ERRORS
.Pp
If /dev/console does not support the proper ioctl() calls, 
.Er ENOTTY
will be returned and 
.Nm pccons
will return 1.
.Sh DIAGNOSTICS
.Pp
The
.Nm pccons
utility exits 0 on success, and >0 if an error occurs.
.Sh SEE ALSO
.Xr console 4
.Sh BUGS
does not handle partial matches of keywords
SHAR_EOF
chmod 0444 pccons.8 ||
echo 'restore of pccons.8 failed'
Wc_c="`wc -c < 'pccons.8'`"
test 1044 -eq "$Wc_c" ||
	echo 'pccons.8: original size 1044, current size' "$Wc_c"
fi
# ============= pccons.c ==============
if test -f 'pccons.c' -a X"$1" != X"-c"; then
	echo 'x - skipping pccons.c (File already exists)'
else
echo 'x - extracting pccons.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'pccons.c' &&
/*
X  pccons.c - get/set/clear pc console and keyboard attributes
X
X  Brad Parker <brad@cayman.com>
*/
X
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
X
struct {
X	char	*word;
X	int	bits;
} flag_words[] = {
X	"shift",	TIOCKEYBD_SHIFT,
X	"caps-lock",	TIOCKEYBD_CAPSLOCK,
X	"block-cursor",	TIOCKEYBD_CURSOR_BLOCK,
X	"", 0
X	};
X
main(argc, argv)
int argc;
char *argv[];
{
X	int fd, result, i, j;
X	int flags;
X
X	if ((fd = open("/dev/console", O_RDWR)) < 0) {
X		perror("/dev/console");
X		exit(1);
X	}
X
X	result = ioctl(fd, TIOCKEYBDG, &flags);
X	if (result != 0) {
X		perror("TIOCKEYBDG");
X		exit(1);
X	}
X
X	if (argc == 1)
X		show(flags);
X	else {
X		for (i = 1; i < argc; i++) {
X			int set = 1;
X
X			if (argv[i][0] == '-') {
X				set = 0;
X				argv[i]++;
X			}
X
X			for (j = 0; flag_words[j].word[0]; j++) {
X				if (strcmp(argv[i], flag_words[j].word) == 0) {
X					if (set)
X						flags |= flag_words[j].bits;
X					else
X						flags &= ~flag_words[j].bits;
X					break;
X				}
X			}
X
X			if (flag_words[j].word[0] == 0)
X				help();
X		}
X
X		result = ioctl(fd, TIOCKEYBDS, &flags);
X		if (result != 0) {
X			perror("TIOCKEYBDS");
X			exit(1);
X		}
X	}
X
X	return 0;
}
X
help()
{
X	int j;
X
X	printf("set/clear/view pc console flags\n");
X	printf("usage: pccons [ <flags> ]\n");
X	printf("valid flags: ");
X	for (j = 0; flag_words[j].word[0]; j++)
X		printf("%s ", flag_words[j].word);
X	printf("\n");
}
X
show(flags)
int flags;
{
X	int j;
X
X	printf("pc console flags: ");
X	if (flags == 0)
X		printf("<none>");
X	else
X		for (j = 0; flag_words[j].word[0]; j++)
X			if (flags & flag_words[j].bits)
X				printf("%s ", flag_words[j].word);
X	printf("\n");
}
SHAR_EOF
chmod 0644 pccons.c ||
echo 'restore of pccons.c failed'
Wc_c="`wc -c < 'pccons.c'`"
test 1604 -eq "$Wc_c" ||
	echo 'pccons.c: original size 1604, current size' "$Wc_c"
fi
exit 0
--
A metaphor is like a simile.

Brad Parker	Cayman Systems, Inc., Cambridge, Ma.	brad@cayman.com
Newsgroups: comp.unix.bsd