code: 9ferno

Download patch

ref: 98272cae8aa58fd0254d184aae33e371670b9862
parent: 702ddcd8846c7c9b64e95e93e035003d1cab38d8
author: 9ferno <gophone2015@gmail.com>
date: Sat Aug 7 12:41:33 EDT 2021

temporary hack until kbdfs

--- a/os/init/disinit.b
+++ b/os/init/disinit.b
@@ -31,6 +31,7 @@
 
 	# set up basic devices, ignoring errors
 	# 9front does this in the shell. Can move them to dis/init later
+	sys->bind("#b", "/dev", sys->MAFTER);	# kbd
 	sys->bind("#c", "/dev", sys->MAFTER);	# console device
 	sys->bind("#d", "/fd", Sys->MREPL);		# dup(3)
 	sys->bind("#e", "/env", sys->MAFTER);	# env
--- a/os/pc/devkbd.c
+++ b/os/pc/devkbd.c
@@ -229,6 +229,7 @@
 
 	b = c & 0xff;
 	qproduce(kbd.q, &b, 1);
+	kbdprocesschar(b); /* hack until kbdfs is built */
 }
 
 void
--- a/os/port/devcons.c
+++ b/os/port/devcons.c
@@ -24,6 +24,27 @@
 
 int	panicking;
 
+/* below until kbdfs */
+int mouseshifted;
+Queue*  kbdq;                   /* unprocessed console input */
+Queue*  lineq;                  /* processed console input */
+static struct
+{
+        QLock;
+
+        int     raw;            /* true if we shouldn't process input */
+        int     ctl;            /* number of opens to the control file */
+        int     kbdr;           /* number of open reads to the keyboard */
+        int     scan;           /* true if reading raw scancodes */
+        int     x;              /* index into line */
+        char    line[1024];     /* current input line */
+
+        char    c;
+        int     count;
+        int     repeat;
+} kbd;
+/* above until kbdfs */
+
 char*	sysname;
 char*	eve;
 
@@ -490,6 +511,21 @@
 static void
 consinit(void)
 {
+	/* below until kbdfs is built */
+	if(lineq == nil){
+        lineq = qopen(2*1024, 0, nil, nil);
+        if(lineq == nil)
+                panic("consinit");
+        qnoblock(lineq, 1);
+	}
+	if(kbdq == nil){
+		kbdq = qopen(4*1024, 0, 0, 0);
+		if(kbdq == nil)
+			panic("consinit");
+		qnoblock(kbdq, 1);
+	}
+	/* above until kbdfs is built */
+
 	todinit();
 	randominit();
 /*
@@ -574,7 +610,61 @@
 	case Qsysctl:
 		return readstr(offset, buf, n, VERSION);
 	case Qcons:
-		error(Egreg);
+		/* below belongs in kbdfs */
+		qlock(&kbd);
+		if(waserror()) {
+			qunlock(&kbd);
+			nexterror();
+		}
+		if(kbd.raw || kbd.kbdr) {
+			if(qcanread(lineq))
+				n = qread(lineq, buf, n);
+			else {
+				/* read as much as possible */
+				char *cbuf = buf;
+				do {
+					i = qread(kbdq, cbuf, n);
+					cbuf += i;
+					n -= i;
+				} while(n>0 && qcanread(kbdq));
+				n = cbuf - (char*)buf;
+			}
+		} else {
+			int ch, eol;
+			while(!qcanread(lineq)) {
+				qread(kbdq, &kbd.line[kbd.x], 1);
+				ch = kbd.line[kbd.x];
+				eol = 0;
+				switch(ch){
+					case '\b':
+						if(kbd.x)
+						kbd.x--;
+						break;
+					case 0x15:
+						kbd.x = 0;
+						break;
+					case '\n':
+					case 0x04:
+						eol = 1;
+					default:
+						kbd.line[kbd.x++] = ch;
+						break;
+				}
+				if(kbd.x == sizeof(kbd.line) || eol) {
+					if(ch == 0x04)
+						kbd.x--;
+					qwrite(lineq, kbd.line, kbd.x);
+					kbd.x = 0;
+				}
+			}
+			n = qread(lineq, buf, n);
+		}
+		qunlock(&kbd);
+		poperror();
+		return n;
+		/* above belongs in kbdfs */
+		/* commented until the above is removed
+		error(Egreg); */
 
 	case Qtime:
 		snprint(tmp, sizeof(tmp), "%.lld", (vlong)mseconds()*1000);
@@ -841,4 +931,295 @@
 
 	randomread(&x, sizeof(x));
 	return x;
+}
+
+/* all the below belongs in kbdfs  */
+
+/*
+ * The codes at 0x79 and 0x81 are produed by the PFU Happy Hacking keyboard.
+ * A 'standard' keyboard doesn't produce anything above 0x58.
+ */
+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',	LCtrl,	'a',	's',
+[0x20]	'd',	'f',	'g',	'h',	'j',	'k',	'l',	';',
+[0x28]	'\'',	'`',	Shift,	'\\',	'z',	'x',	'c',	'v',
+[0x30]	'b',	'n',	'm',	',',	'.',	'/',	Shift,	'*',
+[0x38]	Latin,	' ',	LCtrl,	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',	LCtrl,	'A',	'S',
+[0x20]	'D',	'F',	'G',	'H',	'J',	'K',	'L',	':',
+[0x28]	'"',	'~',	Shift,	'|',	'Z',	'X',	'C',	'V',
+[0x30]	'B',	'N',	'M',	'<',	'>',	'?',	Shift,	'*',
+[0x38]	Latin,	' ',	LCtrl,	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',	LCtrl,	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,
+};
+
+void
+echo(Rune r, char *buf, int n)
+{
+        if(kbd.raw)
+                return;
+
+        if(r == '\n'){
+				putstrn("\r", 1);
+        } else if(r == 0x15){
+                buf = "^U\n";
+                n = 3;
+        }
+		putstrn(buf, n);
+}
+
+/*
+ *  Put character, possibly a rune, into read queue at interrupt time.
+ *  Performs translation for compose sequences
+ *  Called at interrupt time to process a character.
+ */
+int
+kbdputc(Queue *q, int ch)
+{
+        int n;
+        char buf[UTFmax] = "";
+        Rune r;
+        static Rune kc[15];
+        static int nk, collecting = 0;
+
+        r = ch;
+        if(r == Latin) {
+                collecting = 1;
+                nk = 0;
+                return 0;
+        }
+        if(collecting) {
+                int c;
+                nk += runetochar((char*)&kc[nk], &r);
+                c = latin1(kc, nk);
+                if(c < -1)      /* need more keystrokes */
+                        return 0;
+                collecting = 0;
+                if(c == -1) {   /* invalid sequence */
+                        echo(kc[0], (char*)kc, nk);
+                        qproduce(q, kc, nk);
+                        return 0;
+                }
+                r = (Rune)c;
+        }
+        kbd.c = r;
+        n = runetochar(buf, &r);
+        if(n == 0)
+                return 0;
+        echo(r, buf, n);
+        qproduce(q, buf, n);
+        return 0;
+}
+
+void
+kbdrepeat(int rep)
+{
+        kbd.repeat = rep;
+        kbd.count = 0;
+}
+
+void
+kbdclock(void)
+{
+        if(kbd.repeat == 0)
+                return;
+        if(kbd.repeat==1 && ++kbd.count>HZ){
+                kbd.repeat = 2;
+                kbd.count = 0;
+                return;
+        }
+        if(++kbd.count&1)
+                kbdputc(kbdq, kbd.c);
+}
+
+/*
+ *  Called by a uart interrupt for console input.
+ *
+ *  turn '\r' into '\n' before putting it into the queue.
+ */
+int
+kbdcr2nl(Queue *q, int ch)
+{
+        if(ch == '\r')
+                ch = '\n';
+        return kbdputc(q, ch);
+}
+
+/*
+ *  called from the keyboard interrupt
+ */
+void
+kbdprocesschar(int ch)
+{
+	int s, c, i;
+	static int esc1, esc2;
+	static int alt, caps, ctl, num, shift;
+	static int collecting, nk;
+	static Rune kc[5];
+	int keyup;
+
+	c = ch;
+	/*
+	 *  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 > sizeof kbtab){
+		c |= keyup;
+		if(c != 0xFF)	/* these come fairly often: CAPSLOCK U Y */
+			print("unknown key %ux\n", c);
+		return;
+	}
+
+	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;
+			mouseshifted = 0;
+			break;
+		case RCtrl:
+		case LCtrl:
+			ctl = 0;
+			break;
+		}
+		return;
+	}
+
+	/*
+ 	 *  normal character
+	 */
+	if(!(c & (Spec|KF))){
+		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 Caps:
+			caps ^= 1;
+			return;
+		case Num:
+			num ^= 1;
+			return;
+		case Shift:
+			shift = 1;
+			mouseshifted = 1;
+			return;
+		case Latin:
+			alt = 1;
+			/*
+			 * VMware uses Ctl-Alt as the key combination
+			 * to make the VM give up keyboard and mouse focus.
+			 * This has the unfortunate side effect that when you
+			 * come back into focus, Plan 9 thinks you want to type
+			 * a compose sequence (you just typed alt). 
+			 *
+			 * As a clumsy hack around this, we look for ctl-alt
+			 * and don't treat it as the start of a compose sequence.
+			 */
+			if(!ctl){
+				collecting = 1;
+				nk = 0;
+			}
+			return;
+		case LCtrl:
+		case RCtrl:
+			collecting = 0;
+			nk = 0;
+			ctl = 1;
+			return;
+		}
+	}
+	kbdputc(kbdq, c);
 }
--- a/os/port/portfns.h
+++ b/os/port/portfns.h
@@ -123,10 +123,11 @@
 int		islo(void);
 void		iunlock(Lock*);
 void		ixsummary(void);
-void		kbdclock(void);
-int		kbdcr2nl(Queue*, int);
-int		kbdputc(Queue*, int);
-void		kbdrepeat(int);
+void		kbdclock(void);		/* will go away with kbdfs */
+int		kbdcr2nl(Queue*, int);	/* will go away with kbdfs */
+void		kbdprocesschar(int);	/* will go away with kbdfs */
+int		kbdputc(Queue*, int);	/* will go away with kbdfs */
+void		kbdrepeat(int);		/* will go away with kbdfs */
 void		kproc(char*, void(*)(void*), void*, int);
 int		kfgrpclose(Fgrp*, int);
 void		kprocchild(Proc*, void (*)(void*), void*);