9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* Re: [9fans] keyboad maps revisited
@ 2002-02-08 15:53 Fco.J.Ballesteros
  0 siblings, 0 replies; 3+ messages in thread
From: Fco.J.Ballesteros @ 2002-02-08 15:53 UTC (permalink / raw)
  To: boyd, 9fans

: True, but I like the generality of being able to dynamically map.

Wouldn't pipefile be enough for those cases?
In any case, it's probably a matter of taste...


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [9fans] keyboad maps revisited
  2002-02-08 15:42 Fco.J.Ballesteros
@ 2002-02-08 15:49 ` Boyd Roberts
  0 siblings, 0 replies; 3+ messages in thread
From: Boyd Roberts @ 2002-02-08 15:49 UTC (permalink / raw)
  To: 9fans

"Fco.J.Ballesteros" wrote:
> Although this does not permit using the same kernel for different keyboard
> layouts I think that most of the times that is not a problem.

True, but I like the generality of being able to dynamically map.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [9fans] keyboad maps revisited
@ 2002-02-08 15:42 Fco.J.Ballesteros
  2002-02-08 15:49 ` Boyd Roberts
  0 siblings, 1 reply; 3+ messages in thread
From: Fco.J.Ballesteros @ 2002-02-08 15:42 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 1585 bytes --]

Hi,

	I changed the pc kbd.c to allow for keyboard maps (eg. spanish
keyboards) in a simple way. IMHO, this is enough to get users happy,
yet it does not complicate the kernel with another device.

The idea is simple:

— the kbtab*[]s are moved to a separate file: kbdus.c kbdsp.c etc.

— in the configuration file you specify one of kbdus, kbdsp, ... as an option.

— Besides, to aid in the construction of new kbd{us,sp,...}.c files
   kbd.c is changed to let you know the scancodes that your keys generate
   (press f1 to get the code for each key you press, press f2 to stop
    scan code messages)

Although this does not permit using the same kernel for different keyboard
layouts I think that most of the times that is not a problem.

I tested it here and it works nicely.
BTW, I only send the kbdus.c map, since the kbdsp.c I used to test this
thing does not really match the spanish keyboard (yes, don't ask me why but I
use us keyboards despite being in Madrid). I'll make a kbdsp.c in a few
days if no one does it before, though.

The attached files are:
/sys/src/9/pc/kbd.c : 
	now including kbd.h, and playing the f1/f2 dump scancode game.
/sys/src/9/pc/kbd.h :
	new, just w/ declarations for external kbmaps[]
/sys/src/9/pc/kbdus.c :
	tables for the us keyboard (the ones in the distribution, actually)
/sys/src/9/pc/pcdisk
	example of config file using kbdus.

hope this helps

PS: It would be great if those of us using non-us keyboards could contribute
kbd*.c maps so that new Plan 9 users could just borrow our tables.


[-- Attachment #2: kbd.c --]
[-- Type: text/plain, Size: 6057 bytes --]

#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"io.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"kbd.h"

enum {
	Data=		0x60,		/* data port */

	Status=		0x64,		/* status port */
	 Inready=	0x01,		/*  input character ready */
	 Outbusy=	0x02,		/*  output busy */
	 Sysflag=	0x04,		/*  system flag */
	 Cmddata=	0x08,		/*  cmd==0, data==1 */
	 Inhibit=	0x10,		/*  keyboard/mouse inhibited */
	 Minready=	0x20,		/*  mouse character ready */
	 Rtimeout=	0x40,		/*  general timeout */
	 Parity=	0x80,

	Cmd=		0x64,		/* command port (write only) */

};


enum
{
	/* controller command byte */
	Cscs1=		(1<<6),		/* scan code set 1 */
	Cauxdis=	(1<<5),		/* mouse disable */
	Ckbddis=	(1<<4),		/* kbd disable */
	Csf=		(1<<2),		/* system flag */
	Cauxint=	(1<<1),		/* mouse interrupt enable */
	Ckbdint=	(1<<0),		/* kbd interrupt enable */
};
#define Nscan 0x80

static Lock i8042lock;
static uchar ccc;
static void (*auxputc)(int, int);
static int dumpsc;

/*
 *  wait for output no longer busy
 */
static int
outready(void)
{
	int tries;

	for(tries = 0; (inb(Status) & Outbusy); tries++){
		if(tries > 500)
			return -1;
		delay(2);
	}
	return 0;
}

/*
 *  wait for input
 */
static int
inready(void)
{
	int tries;

	for(tries = 0; !(inb(Status) & Inready); tries++){
		if(tries > 500)
			return -1;
		delay(2);
	}
	return 0;
}

/*
 *  ask 8042 to reset the machine
 */
void
i8042reset(void)
{
	ushort *s = KADDR(0x472);
	int i, x;

	*s = 0x1234;		/* BIOS warm-boot flag */

	/*
	 *  newer reset the machine command
	 */
	outready();
	outb(Cmd, 0xFE);
	outready();

	/*
	 *  Pulse it by hand (old somewhat reliable)
	 */
	x = 0xDF;
	for(i = 0; i < 5; i++){
		x ^= 1;
		outready();
		outb(Cmd, 0xD1);
		outready();
		outb(Data, x);	/* toggle reset */
		delay(100);
	}
}

int
i8042auxcmd(int cmd)
{
	unsigned int c;
	int tries;

	c = 0;
	tries = 0;

	ilock(&i8042lock);
	do{
		if(tries++ > 2)
			break;
		if(outready() < 0)
			break;
		outb(Cmd, 0xD4);
		if(outready() < 0)
			break;
		outb(Data, cmd);
		if(outready() < 0)
			break;
		if(inready() < 0)
			break;
		c = inb(Data);
	} while(c == 0xFE || c == 0);
	iunlock(&i8042lock);

	if(c != 0xFA){
		print("i8042: %2.2ux returned to the %2.2ux command\n", c, cmd);
		return -1;
	}
	return 0;
}

/*
 *  keyboard interrupt
 */
static void
i8042intr(Ureg*, void*)
{
	int s, c, i, sc;
	static int esc1, esc2;
	static int alt, caps, ctl, num, shift;
	static int collecting, nk;
	static Rune kc[5];
	int keyup;

	/*
	 *  get status
	 */
	lock(&i8042lock);
	s = inb(Status);
	if(!(s&Inready)){
		unlock(&i8042lock);
		return;
	}

	/*
	 *  get the character
	 */
	sc = c = inb(Data);
	unlock(&i8042lock);

	/*
	 *  if it's the aux port...
	 */
	if(s & Minready){
		if(auxputc != nil)
			auxputc(c, shift);
		return;
	}

	/*
	 *  e0's is the first of a 2 character sequence
	 */
	if(c == 0xe0){
		esc1 = 1;
		return;
	} else if(c == 0xe1){
		esc2 = 2;
		return;
	}

	keyup = c&0x80;
	c &= 0x7f;
	if(c > Kbsize){
		c |= keyup;
		if(c != 0xFF)	/* these come fairly often: CAPSLOCK U Y */
			print("unknown key %ux\n", c);
		return;
	}

	if(dumpsc){
		print("kbd scan: 0x%ux\n", sc);
	}
	if(esc1){
		c = kbtabesc1[c];
		esc1 = 0;
	} else if(esc2){
		esc2--;
		return;
	} else if(shift)
		c = kbtabshift[c];
	else
		c = kbtab[c];

	if(caps && c<='z' && c>='a')
		c += 'A' - 'a';

	/*
	 *  keyup only important for shifts
	 */
	if(keyup){
		switch(c){
		case Latin:
			alt = 0;
			break;
		case Shift:
			shift = 0;
			break;
		case Ctrl:
			ctl = 0;
			break;
		}
		return;
	}

	/*
 	 *  normal character
	 */
	if(!(c & (Spec|KF))){
		if (dumpsc)
			return;
		if(ctl){
			if(alt && c == Del)
				exit(0);
			c &= 0x1f;
		}
		if(!collecting){
			kbdputc(kbdq, c);
			return;
		}
		kc[nk++] = c;
		c = latin1(kc, nk);
		if(c < -1)	/* need more keystrokes */
			return;
		if(c != -1)	/* valid sequence */
			kbdputc(kbdq, c);
		else	/* dump characters */
			for(i=0; i<nk; i++)
				kbdputc(kbdq, kc[i]);
		nk = 0;
		collecting = 0;
		return;
	} else {
		switch(c){
		case KF1:
			dumpsc = 1;
			return;
		case KF2:
			dumpsc = 0;
			return;
		case Caps:
			caps ^= 1;
			return;
		case Num:
			num ^= 1;
			return;
		case Shift:
			shift = 1;
			return;
		case Latin:
			alt = 1;
			collecting = 1;
			nk = 0;
			return;
		case Ctrl:
			ctl = 1;
			return;
		}
	}
	kbdputc(kbdq, c);
}

void
i8042auxenable(void (*putc)(int, int))
{
	char *err = "i8042: aux init failed\n";

	/* enable kbd/aux xfers and interrupts */
	ccc &= ~Cauxdis;
	ccc |= Cauxint;

	ilock(&i8042lock);
	if(outready() < 0)
		print(err);
	outb(Cmd, 0x60);			/* write control register */
	if(outready() < 0)
		print(err);
	outb(Data, ccc);
	if(outready() < 0)
		print(err);
	outb(Cmd, 0xA8);			/* auxilliary device enable */
	if(outready() < 0){
		iunlock(&i8042lock);
		return;
	}
	auxputc = putc;
	intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux");
	iunlock(&i8042lock);
}

void
kbdinit(void)
{
	int c;

	kbdq = qopen(4*1024, 0, 0, 0);
	if(kbdq == nil)
		panic("kbdinit");
	qnoblock(kbdq, 1);

	ioalloc(Data, 1, 0, "kbd");
	ioalloc(Cmd, 1, 0, "kbd");

	intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd");

	/* wait for a quiescent controller */
	while((c = inb(Status)) & (Outbusy | Inready))
		if(c & Inready)
			inb(Data);

	/* get current controller command byte */
	outb(Cmd, 0x20);
	if(inready() < 0){
		print("kbdinit: can't read ccc\n");
		ccc = 0;
	} else
		ccc = inb(Data);

	/* enable kbd xfers and interrupts */
	/* disable mouse */
	ccc &= ~Ckbddis;
	ccc |= Csf | Ckbdint | Cscs1;
	if(outready() < 0)
		print("kbd init failed\n");
	outb(Cmd, 0x60);
	if(outready() < 0)
		print("kbd init failed\n");
	outb(Data, ccc);
	outready();
}

[-- Attachment #3: kbd.h --]
[-- Type: text/plain, Size: 695 bytes --]

enum
{
	Spec=		0x80,

	PF=		Spec|0x20,	/* num pad function key */
	View=		Spec|0x00,	/* view (shift window up) */
	KF=		0xF000,	/* function key (begin Unicode private space) */
	Shift=		Spec|0x60,
	Break=		Spec|0x61,
	Ctrl=		Spec|0x62,
	Latin=		Spec|0x63,
	Caps=		Spec|0x64,
	Num=		Spec|0x65,
	Middle=		Spec|0x66,
	No=		0x00,		/* peter */

	Home=		KF|13,
	Up=		KF|14,
	Pgup=		KF|15,
	Print=		KF|16,
	Left=		KF|17,
	Right=		KF|18,
	End=		'\r',
	Down=		View,
	Pgdown=		KF|19,
	Ins=		KF|20,
	Del=		0x7F,
	Scroll=		KF|21,
	KF1=		KF|1,
	KF2=		KF|2,


};

#define Kbsize	(0x7f*sizeof(Rune))
extern Rune kbtab[];
extern Rune kbtabshift[];
extern Rune kbtabesc1[];

[-- Attachment #4: kbdus.c --]
[-- Type: text/plain, Size: 2460 bytes --]

/*
 * The codes at 0x79 and 0x81 are produed by the PFU Happy Hacking keyboard.
 * A 'standard' keyboard doesn't produce anything above 0x58.
 */

#include "u.h"
#include "kbd.h"

Rune kbtab[] = 
{
[0x00]	No,	0x1b,	'1',	'2',	'3',	'4',	'5',	'6',
[0x08]	'7',	'8',	'9',	'0',	'-',	'=',	'\b',	'\t',
[0x10]	'q',	'w',	'e',	'r',	't',	'y',	'u',	'i',
[0x18]	'o',	'p',	'[',	']',	'\n',	Ctrl,	'a',	's',
[0x20]	'd',	'f',	'g',	'h',	'j',	'k',	'l',	';',
[0x28]	'\'',	'`',	Shift,	'\\',	'z',	'x',	'c',	'v',
[0x30]	'b',	'n',	'm',	',',	'.',	'/',	Shift,	'*',
[0x38]	Latin,	' ',	Ctrl,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	Scroll,	'7',
[0x48]	'8',	'9',	'-',	'4',	'5',	'6',	'+',	'1',
[0x50]	'2',	'3',	'0',	'.',	No,	No,	No,	KF|11,
[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
[0x60]	No,	No,	No,	No,	No,	No,	No,	No,
[0x68]	No,	No,	No,	No,	No,	No,	No,	No,
[0x70]	No,	No,	No,	No,	No,	No,	No,	No,
[0x78]	No,	View,	No,	Up,	No,	No,	No,	No,
};

Rune kbtabshift[] =
{
[0x00]	No,	0x1b,	'!',	'@',	'#',	'$',	'%',	'^',
[0x08]	'&',	'*',	'(',	')',	'_',	'+',	'\b',	'\t',
[0x10]	'Q',	'W',	'E',	'R',	'T',	'Y',	'U',	'I',
[0x18]	'O',	'P',	'{',	'}',	'\n',	Ctrl,	'A',	'S',
[0x20]	'D',	'F',	'G',	'H',	'J',	'K',	'L',	':',
[0x28]	'"',	'~',	Shift,	'|',	'Z',	'X',	'C',	'V',
[0x30]	'B',	'N',	'M',	'<',	'>',	'?',	Shift,	'*',
[0x38]	Latin,	' ',	Ctrl,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	Scroll,	'7',
[0x48]	'8',	'9',	'-',	'4',	'5',	'6',	'+',	'1',
[0x50]	'2',	'3',	'0',	'.',	No,	No,	No,	KF|11,
[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
[0x60]	No,	No,	No,	No,	No,	No,	No,	No,
[0x68]	No,	No,	No,	No,	No,	No,	No,	No,
[0x70]	No,	No,	No,	No,	No,	No,	No,	No,
[0x78]	No,	Up,	No,	Up,	No,	No,	No,	No,
};

Rune kbtabesc1[] =
{
[0x00]	No,	No,	No,	No,	No,	No,	No,	No,
[0x08]	No,	No,	No,	No,	No,	No,	No,	No,
[0x10]	No,	No,	No,	No,	No,	No,	No,	No,
[0x18]	No,	No,	No,	No,	'\n',	Ctrl,	No,	No,
[0x20]	No,	No,	No,	No,	No,	No,	No,	No,
[0x28]	No,	No,	Shift,	No,	No,	No,	No,	No,
[0x30]	No,	No,	No,	No,	No,	'/',	No,	Print,
[0x38]	Latin,	No,	No,	No,	No,	No,	No,	No,
[0x40]	No,	No,	No,	No,	No,	No,	Break,	Home,
[0x48]	Up,	Pgup,	No,	Left,	No,	Right,	No,	End,
[0x50]	Down,	Pgdown,	Ins,	Del,	No,	No,	No,	No,
[0x58]	No,	No,	No,	No,	No,	No,	No,	No,
[0x60]	No,	No,	No,	No,	No,	No,	No,	No,
[0x68]	No,	No,	No,	No,	No,	No,	No,	No,
[0x70]	No,	No,	No,	No,	No,	No,	No,	No,
[0x78]	No,	Up,	No,	No,	No,	No,	No,	No,
};

[-- Attachment #5: pcdisk --]
[-- Type: text/plain, Size: 641 bytes --]

dev
	root
	cons
	arch
	env
	pipe
	proc
	mnt
	srv
	dup
	rtc
	ssl
	bridge
	loopback
	kprof

	ether	netif
	ip	arp chandial ip ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno

	draw	screen vga vgax
	mouse	mouse
	vga

	sd
	floppy	dma

	audio	dma
	i82365	cis
	lpt
	ns16552



link
	apm		apmjump
	etherwavelan
	ethermedium
	loopbackmedium
	pcmciamodem

misc
	archmp		mp apic
	cfs.root
	kfs.root
	ppp.root
	ipconfig.root
	sdata		pci sdscsi
	kbdus
	vgamach64xx	+cur

ip
	il
	tcp
	udp
	rudp
	ipifc
	icmp
	gre
	ipmux

port
	int cpuserver = 0;

boot boot #S/sdC0/
	il
	local

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2002-02-08 15:53 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-02-08 15:53 [9fans] keyboad maps revisited Fco.J.Ballesteros
  -- strict thread matches above, loose matches on Subject: below --
2002-02-08 15:42 Fco.J.Ballesteros
2002-02-08 15:49 ` Boyd Roberts

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).