ref: 26c2845917cb4661a6e04e3b41d52fdc1338a2c4
parent: 67856b45077ec20116f1cb658b6686d4cdecbdfa
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Mon May 9 04:32:14 EDT 2011
kbdfs
--- a/lib/namespace
+++ b/lib/namespace
@@ -14,6 +14,7 @@
# mount points
mount -a /srv/slashn /n
+mount -b /srv/cons /dev
# authentication
mount -a /srv/factotum /mnt
--- a/sys/src/9/boot/bootrc
+++ b/sys/src/9/boot/bootrc
@@ -2,6 +2,12 @@
bind -q '#p' /proc
+if(test -e '#b' && ! test -e /dev/kbd){
+ bind -a '#b' /dev
+ aux/kbdfs -s cons
+ exec /rc/bin/bootrc </dev/cons >/dev/cons >[2]/dev/cons
+}
+
bind -qa '#S' /dev
bind -qa '#f' /dev
bind -qa '#k' /dev
--- /dev/null
+++ b/sys/src/9/pc/devkbd.c
@@ -1,0 +1,481 @@
+/*
+ * keyboard input
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.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) */
+
+ Spec= 0xF800, /* Unicode private space */
+ 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,
+ Altgr= Spec|0x67,
+ Kmouse= Spec|0x100,
+ No= 0x00, /* peter */
+
+ Home= KF|13,
+ Up= KF|14,
+ Pgup= KF|15,
+ Print= KF|16,
+ Left= KF|17,
+ Right= KF|18,
+ End= KF|24,
+ Down= View,
+ Pgdown= KF|19,
+ Ins= KF|20,
+ Del= 0x7F,
+ Scroll= KF|21,
+
+ Nscan= 128,
+
+ Int= 0, /* kbscans indices */
+ Ext,
+ Nscans,
+};
+
+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 */
+};
+
+enum {
+ Qdir,
+ Qscancode,
+ Qleds,
+};
+
+static Dirtab kbdtab[] = {
+ ".", {Qdir, 0, QTDIR}, 0, 0555,
+ "scancode", {Qscancode, 0}, 0, 0440,
+ "leds", {Qleds, 0}, 0, 0220,
+};
+
+static Lock i8042lock;
+static uchar ccc;
+static void kbdputc(int);
+static void (*auxputc)(int, int);
+static int nokbd = 1; /* flag: no PS/2 keyboard */
+
+static struct {
+ Ref ref;
+ Queue *q;
+} kbd;
+
+/*
+ * 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)
+{
+ int i, x;
+
+ if(nokbd)
+ return;
+
+ *((ushort*)KADDR(0x472)) = 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;
+ static int badkbd;
+
+ if(badkbd)
+ return -1;
+ 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);
+ badkbd = 1; /* don't keep trying; there might not be one */
+ return -1;
+ }
+ return 0;
+}
+
+int
+i8042auxcmds(uchar *cmd, int ncmd)
+{
+ int i;
+
+ ilock(&i8042lock);
+ for(i=0; i<ncmd; i++){
+ if(outready() < 0)
+ break;
+ outb(Cmd, 0xD4);
+ if(outready() < 0)
+ break;
+ outb(Data, cmd[i]);
+ }
+ iunlock(&i8042lock);
+ return i;
+}
+
+/*
+ * set keyboard's leds for lock states (scroll, numeric, caps).
+ *
+ * at least one keyboard (from Qtronics) also sets its numeric-lock
+ * behaviour to match the led state, though it has no numeric keypad,
+ * and some BIOSes bring the system up with numeric-lock set and no
+ * setting to change that. this combination steals the keys for these
+ * characters and makes it impossible to generate them: uiolkjm&*().
+ * thus we'd like to be able to force the numeric-lock led (and behaviour) off.
+ */
+static void
+setleds(int leds)
+{
+ static int old = -1;
+
+ if(nokbd || leds == old)
+ return;
+ leds &= 7;
+ ilock(&i8042lock);
+ for(;;){
+ if(outready() < 0)
+ break;
+ outb(Data, 0xed); /* `reset keyboard lock states' */
+ if(outready() < 0)
+ break;
+ outb(Data, leds);
+ if(outready() < 0)
+ break;
+ old = leds;
+ break;
+ }
+ iunlock(&i8042lock);
+}
+
+/*
+ * keyboard interrupt
+ */
+static void
+i8042intr(Ureg*, void*)
+{
+ int s, c;
+ uchar b;
+
+ /*
+ * get status
+ */
+ ilock(&i8042lock);
+ s = inb(Status);
+ if(!(s&Inready)){
+ iunlock(&i8042lock);
+ return;
+ }
+
+ /*
+ * get the character
+ */
+ c = inb(Data);
+ iunlock(&i8042lock);
+
+ /*
+ * if it's the aux port...
+ */
+ if(s & Minready){
+ if(auxputc != nil)
+ auxputc(c, 0);
+ return;
+ }
+
+ b = c & 0xff;
+ qproduce(kbd.q, &b, 1);
+}
+
+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); /* auxiliary device enable */
+ if(outready() < 0){
+ iunlock(&i8042lock);
+ return;
+ }
+ auxputc = putc;
+ intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux");
+ iunlock(&i8042lock);
+}
+
+static Chan *
+kbdattach(char *spec)
+{
+ return devattach(L'b', spec);
+}
+
+static Walkqid*
+kbdwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, kbdtab, nelem(kbdtab), devgen);
+}
+
+static int
+kbdstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, kbdtab, nelem(kbdtab), devgen);
+}
+
+static Chan*
+kbdopen(Chan *c, int omode)
+{
+ if(!iseve())
+ error(Eperm);
+ if(c->qid.path == Qscancode){
+ if(incref(&kbd.ref) != 1){
+ decref(&kbd.ref);
+ error(Einuse);
+ }
+ }
+ return devopen(c, omode, kbdtab, nelem(kbdtab), devgen);
+}
+
+static void
+kbdclose(Chan *c)
+{
+ if(c->qid.path == Qscancode)
+ decref(&kbd.ref);
+}
+
+static Block*
+kbdbread(Chan *c, long n, ulong)
+{
+ if(c->qid.path != Qscancode)
+ error(Egreg);
+
+ return qbread(kbd.q, n);
+}
+
+static long
+kbdread(Chan *c, void *a, long n, vlong)
+{
+ if(c->qid.path != Qscancode)
+ error(Egreg);
+
+ return qread(kbd.q, a, n);
+}
+
+static long
+kbdwrite(Chan *c, void *a, long n, vlong)
+{
+ char tmp[8+1], *p;
+
+ if(c->qid.path != Qleds)
+ error(Egreg);
+
+ p = tmp + n;
+ if(n >= sizeof(tmp))
+ p = tmp + sizeof(tmp)-1;
+ memmove(tmp, a, p - tmp);
+ *p = 0;
+
+ setleds(atoi(tmp));
+
+ return n;
+}
+
+Dev kbddevtab = {
+ L'b',
+ "kbd",
+
+ devreset,
+ devinit,
+ devshutdown,
+ kbdattach,
+ kbdwalk,
+ kbdstat,
+ kbdopen,
+ devcreate,
+ kbdclose,
+ kbdread,
+ kbdbread,
+ kbdwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+
+static char *initfailed = "i8042: kbdinit failed\n";
+
+static int
+outbyte(int port, int c)
+{
+ outb(port, c);
+ if(outready() < 0) {
+ print(initfailed);
+ return -1;
+ }
+ return 0;
+}
+
+void
+kbdenable(void)
+{
+ kbd.q = qopen(4*1024, 0, 0, 0);
+ if(kbd.q == nil)
+ panic("kbdenable");
+ qnoblock(kbd.q, 1);
+
+ ioalloc(Data, 1, 0, "kbd");
+ ioalloc(Cmd, 1, 0, "kbd");
+
+ intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd");
+}
+
+void
+kbdinit(void)
+{
+ int c, try;
+
+ /* wait for a quiescent controller */
+ try = 1000;
+ while(try-- > 0 && (c = inb(Status)) & (Outbusy | Inready)) {
+ if(c & Inready)
+ inb(Data);
+ delay(1);
+ }
+ if (try <= 0) {
+ print(initfailed);
+ return;
+ }
+
+ /* get current controller command byte */
+ outb(Cmd, 0x20);
+ if(inready() < 0){
+ print("i8042: kbdinit can't read ccc\n");
+ ccc = 0;
+ } else
+ ccc = inb(Data);
+
+ /* enable kbd xfers and interrupts */
+ ccc &= ~Ckbddis;
+ ccc |= Csf | Ckbdint | Cscs1;
+ if(outready() < 0) {
+ print(initfailed);
+ return;
+ }
+
+ nokbd = 0;
+
+ /* disable mouse */
+ if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0)
+ print("i8042: kbdinit mouse disable failed\n");
+}
--- a/sys/src/9/pc/kbd.c
+++ /dev/null
@@ -1,715 +1,0 @@
-/*
- * keyboard input
- */
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.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) */
-
- Spec= 0xF800, /* Unicode private space */
- 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,
- Altgr= Spec|0x67,
- Kmouse= Spec|0x100,
- No= 0x00, /* peter */
-
- Home= KF|13,
- Up= KF|14,
- Pgup= KF|15,
- Print= KF|16,
- Left= KF|17,
- Right= KF|18,
- End= KF|24,
- Down= View,
- Pgdown= KF|19,
- Ins= KF|20,
- Del= 0x7F,
- Scroll= KF|21,
-
- Nscan= 128,
-
- Int= 0, /* kbscans indices */
- Ext,
- Nscans,
-};
-
-/*
- * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
- * A 'standard' keyboard doesn't produce anything above 0x58.
- */
-Rune kbtab[Nscan] =
-{
-[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[Nscan] =
-{
-[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[Nscan] =
-{
-[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] Altgr, 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,
-};
-
-Rune kbtabaltgr[Nscan] =
-{
-[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] Altgr, 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,
-};
-
-Rune kbtabctrl[Nscan] =
-{
-[0x00] No, '', '', '', '', '', '', '',
-[0x08] '', '', '', '', ' ', '', '\b', '\t',
-[0x10] '', '', '', '', '', '', '', '\t',
-[0x18] '', '', '', '', '\n', Ctrl, '', '',
-[0x20] '', '', '', '\b', '\n', '', '', '',
-[0x28] '', No, Shift, '', '', '', '', '',
-[0x30] '', '', ' ', '', '', '', Shift, '\n',
-[0x38] Latin, No, Ctrl, '', '', '', '', '',
-[0x40] '', '', '', ' ', '', '', '', '',
-[0x48] '', '', ' ', '', '', '', '', '',
-[0x50] '', '', '', '', No, No, No, '',
-[0x58] '', 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, '', No, '\b', No, No, No, No,
-};
-
-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 */
-};
-
-int mouseshifted;
-void (*kbdmouse)(int);
-
-static Lock i8042lock;
-static uchar ccc;
-static void (*auxputc)(int, int);
-static int nokbd = 1; /* flag: no PS/2 keyboard */
-
-/*
- * 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)
-{
- int i, x;
-
- if(nokbd)
- return;
-
- *((ushort*)KADDR(0x472)) = 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;
- static int badkbd;
-
- if(badkbd)
- return -1;
- 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);
- badkbd = 1; /* don't keep trying; there might not be one */
- return -1;
- }
- return 0;
-}
-
-int
-i8042auxcmds(uchar *cmd, int ncmd)
-{
- int i;
-
- ilock(&i8042lock);
- for(i=0; i<ncmd; i++){
- if(outready() < 0)
- break;
- outb(Cmd, 0xD4);
- if(outready() < 0)
- break;
- outb(Data, cmd[i]);
- }
- iunlock(&i8042lock);
- return i;
-}
-
-typedef struct Kbscan Kbscan;
-struct Kbscan {
- int esc1;
- int esc2;
- int alt;
- int altgr;
- int caps;
- int ctl;
- int num;
- int shift;
- int collecting;
- int nk;
- Rune kc[5];
- int buttons;
-};
-
-Kbscan kbscans[Nscans]; /* kernel and external scan code state */
-
-static int kdebug;
-
-/*
- * set keyboard's leds for lock states (scroll, numeric, caps).
- *
- * at least one keyboard (from Qtronics) also sets its numeric-lock
- * behaviour to match the led state, though it has no numeric keypad,
- * and some BIOSes bring the system up with numeric-lock set and no
- * setting to change that. this combination steals the keys for these
- * characters and makes it impossible to generate them: uiolkjm&*().
- * thus we'd like to be able to force the numeric-lock led (and behaviour) off.
- */
-static void
-setleds(Kbscan *kbscan)
-{
- int leds;
-
- if(nokbd || kbscan != &kbscans[Int])
- return;
- leds = 0;
- if(kbscan->num)
- leds |= 1<<1;
- if(0 && kbscan->caps) /* we don't implement caps lock */
- leds |= 1<<2;
- ilock(&i8042lock);
- outready();
- outb(Data, 0xed); /* `reset keyboard lock states' */
- outready();
- outb(Data, leds);
- outready();
- iunlock(&i8042lock);
-}
-
-/*
- * Scan code processing
- */
-void
-kbdputsc(int c, int external)
-{
- int i, keyup;
- Kbscan *kbscan;
-
- if(external)
- kbscan = &kbscans[Ext];
- else
- kbscan = &kbscans[Int];
-
- if(kdebug)
- print("sc %x ms %d\n", c, mouseshifted);
- /*
- * e0's is the first of a 2 character sequence, e1 the first
- * of a 3 character sequence (on the safari)
- */
- if(c == 0xe0){
- kbscan->esc1 = 1;
- return;
- } else if(c == 0xe1){
- kbscan->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(kbscan->esc1){
- c = kbtabesc1[c];
- kbscan->esc1 = 0;
- } else if(kbscan->esc2){
- kbscan->esc2--;
- return;
- } else if(kbscan->shift)
- c = kbtabshift[c];
- else if(kbscan->altgr)
- c = kbtabaltgr[c];
- else if(kbscan->ctl)
- c = kbtabctrl[c];
- else
- c = kbtab[c];
-
- if(kbscan->caps && c<='z' && c>='a')
- c += 'A' - 'a';
-
- /*
- * keyup only important for shifts
- */
- if(keyup){
- switch(c){
- case Latin:
- kbscan->alt = 0;
- break;
- case Shift:
- kbscan->shift = 0;
- mouseshifted = 0;
- if(kdebug)
- print("shiftclr\n");
- break;
- case Ctrl:
- kbscan->ctl = 0;
- break;
- case Altgr:
- kbscan->altgr = 0;
- break;
- case Kmouse|1:
- case Kmouse|2:
- case Kmouse|3:
- case Kmouse|4:
- case Kmouse|5:
- kbscan->buttons &= ~(1<<(c-Kmouse-1));
- if(kbdmouse)
- kbdmouse(kbscan->buttons);
- break;
- }
- return;
- }
-
- /*
- * normal character
- */
- if(!(c & (Spec|KF))){
- if(kbscan->ctl)
- if(kbscan->alt && c == Del)
- exit(0);
- if(!kbscan->collecting){
- kbdputc(kbdq, c);
- return;
- }
- kbscan->kc[kbscan->nk++] = c;
- c = latin1(kbscan->kc, kbscan->nk);
- if(c < -1) /* need more keystrokes */
- return;
- if(c != -1) /* valid sequence */
- kbdputc(kbdq, c);
- else /* dump characters */
- for(i=0; i<kbscan->nk; i++)
- kbdputc(kbdq, kbscan->kc[i]);
- kbscan->nk = 0;
- kbscan->collecting = 0;
- return;
- } else {
- switch(c){
- case Caps:
- kbscan->caps ^= 1;
- return;
- case Num:
- kbscan->num ^= 1;
- if(!external)
- setleds(kbscan);
- return;
- case Shift:
- kbscan->shift = 1;
- if(kdebug)
- print("shift\n");
- mouseshifted = 1;
- return;
- case Latin:
- kbscan->alt = 1;
- /*
- * VMware and Qemu use 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(!kbscan->ctl){
- kbscan->collecting = 1;
- kbscan->nk = 0;
- }
- return;
- case Ctrl:
- kbscan->ctl = 1;
- return;
- case Altgr:
- kbscan->altgr = 1;
- return;
- case Kmouse|1:
- case Kmouse|2:
- case Kmouse|3:
- case Kmouse|4:
- case Kmouse|5:
- kbscan->buttons |= 1<<(c-Kmouse-1);
- if(kbdmouse)
- kbdmouse(kbscan->buttons);
- return;
- case KF|11:
- print("kbd debug on, F12 turns it off\n");
- kdebug = 1;
- break;
- case KF|12:
- kdebug = 0;
- break;
- }
- }
- kbdputc(kbdq, c);
-}
-
-/*
- * keyboard interrupt
- */
-static void
-i8042intr(Ureg*, void*)
-{
- int s, c;
-
- /*
- * get status
- */
- ilock(&i8042lock);
- s = inb(Status);
- if(!(s&Inready)){
- iunlock(&i8042lock);
- return;
- }
-
- /*
- * get the character
- */
- c = inb(Data);
- iunlock(&i8042lock);
-
- /*
- * if it's the aux port...
- */
- if(s & Minready){
- if(auxputc != nil)
- auxputc(c, kbscans[Int].shift);
- return;
- }
-
- kbdputsc(c, Int);
-}
-
-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); /* auxiliary device enable */
- if(outready() < 0){
- iunlock(&i8042lock);
- return;
- }
- auxputc = putc;
- intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux");
- iunlock(&i8042lock);
-}
-
-static char *initfailed = "i8042: kbdinit failed\n";
-
-static int
-outbyte(int port, int c)
-{
- outb(port, c);
- if(outready() < 0) {
- print(initfailed);
- return -1;
- }
- return 0;
-}
-
-void
-kbdinit(void)
-{
- int c, try;
-
- /* wait for a quiescent controller */
- try = 1000;
- while(try-- > 0 && (c = inb(Status)) & (Outbusy | Inready)) {
- if(c & Inready)
- inb(Data);
- delay(1);
- }
- if (try <= 0) {
- print(initfailed);
- return;
- }
-
- /* get current controller command byte */
- outb(Cmd, 0x20);
- if(inready() < 0){
- print("i8042: kbdinit can't read ccc\n");
- ccc = 0;
- } else
- ccc = inb(Data);
-
- /* enable kbd xfers and interrupts */
- ccc &= ~Ckbddis;
- ccc |= Csf | Ckbdint | Cscs1;
- if(outready() < 0) {
- print(initfailed);
- return;
- }
-
- nokbd = 0;
-
- /* disable mouse */
- if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0)
- print("i8042: kbdinit mouse disable failed\n");
-}
-
-void
-kbdenable(void)
-{
- 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");
-
- kbscans[Int].num = 0;
- setleds(&kbscans[Int]);
-}
-
-void
-kbdputmap(ushort m, ushort scanc, Rune r)
-{
- if(scanc >= Nscan)
- error(Ebadarg);
- switch(m) {
- default:
- error(Ebadarg);
- case 0:
- kbtab[scanc] = r;
- break;
- case 1:
- kbtabshift[scanc] = r;
- break;
- case 2:
- kbtabesc1[scanc] = r;
- break;
- case 3:
- kbtabaltgr[scanc] = r;
- break;
- case 4:
- kbtabctrl[scanc] = r;
- break;
- }
-}
-
-int
-kbdgetmap(uint offset, int *t, int *sc, Rune *r)
-{
- if ((int)offset < 0)
- error(Ebadarg);
- *t = offset/Nscan;
- *sc = offset%Nscan;
- switch(*t) {
- default:
- return 0;
- case 0:
- *r = kbtab[*sc];
- return 1;
- case 1:
- *r = kbtabshift[*sc];
- return 1;
- case 2:
- *r = kbtabesc1[*sc];
- return 1;
- case 3:
- *r = kbtabaltgr[*sc];
- return 1;
- case 4:
- *r = kbtabctrl[*sc];
- return 1;
- }
-}
--- a/sys/src/9/pc/mkfile
+++ b/sys/src/9/pc/mkfile
@@ -1,6 +1,6 @@
-CONF=pc
-CONFLIST=pc pccpu pcf pccpuf
-CRAPLIST=pccd pcflop
+CONF=pcf
+CONFLIST=pcf pccpuf
+CRAPLIST=pc pccpu pccd pcflop
EXTRACOPIES=
#EXTRACOPIES=lookout boundary # copy to these servers on install
@@ -49,7 +49,6 @@
cga.$O\
i8253.$O\
i8259.$O\
- kbd.$O\
main.$O\
memory.$O\
mmu.$O\
--- a/sys/src/9/pc/mouse.c
+++ b/sys/src/9/pc/mouse.c
@@ -22,8 +22,6 @@
MousePS2= 2,
};
-extern int mouseshifted;
-
static QLock mousectlqlock;
static int mousetype;
static int intellimouse;
@@ -95,11 +93,6 @@
ulong m;
int buttons, dx, dy;
- /*
- * non-ps2 keyboards might not set shift
- * but still set mouseshifted.
- */
- shift |= mouseshifted;
/*
* Resynchronize in stream with timing; see comment above.
*/
--- a/sys/src/9/pc/pc
+++ /dev/null
@@ -1,134 +1,0 @@
-dev
- root
- cons
-
- arch
- pnp pci
- env
- pipe
- proc
- mnt
- srv
- dup
- rtc
- ssl
- tls
- cap
- kprof
- fs
-
- ether netif
- ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
-
- draw screen vga vgax
- mouse mouse
- vga
- kbmap
- kbin
-
- sd
- floppy dma
- lpt
-
- audio dma
- pccard
- i82365 cis
- uart
- usb
-
-
-link
- realmode
- devpccard
- devi82365
- ether2000 ether8390
- ether2114x pci
- ether589 etherelnk3
- ether79c970 pci
- ether8003 ether8390
- ether8139 pci
- ether8169 pci ethermii
- ether82543gc pci
- ether82563 pci
- ether82557 pci
- ether83815 pci
- etherbcm pci
- etherdp83820 pci
- etherec2t ether8390
- etherelnk3 pci
- etherga620 pci
- etherigbe pci ethermii
- ethervgbe pci ethermii
- ethervt6102 pci ethermii
- ethervt6105m pci ethermii
- ethersink
- ethersmc devi82365 cis
- etherwavelan wavelan devi82365 cis pci
- ethermedium
-# etherm10g
- ether82598 pci
- pcmciamodem
- netdevmedium
- loopbackmedium
- usbuhci
- usbohci
- usbehci usbehcipc
-
-misc
- archmp mp apic
- mtrr
-
- sdata pci sdscsi
- sd53c8xx pci sdscsi
- sdmylex pci sdscsi
- sdiahci pci sdscsi
-
- uarti8250
- uartpci pci
- uartisa
-
- vga3dfx +cur
- vgaark2000pv +cur
- vgabt485 =cur
- vgaclgd542x +cur
- vgaclgd546x +cur
- vgact65545 +cur
- vgacyber938x +cur
- vgaet4000 +cur
- vgahiqvideo +cur
- vgai81x +cur
- vgamach64xx +cur
- vgamga2164w +cur
- vgamga4xx +cur
- vganeomagic +cur
- vganvidia +cur
- vgargb524 =cur
- vgas3 +cur vgasavage
- vgat2r4 +cur
- vgatvp3020 =cur
- vgatvp3026 =cur
- vgavesa
- vgavmware +cur
- vgageode +cur
-
-ip
- tcp
- udp
- ipifc
- icmp
- icmp6
- gre
- ipmux
- esp
-
-port
- int cpuserver = 0;
-
-boot
- tcp
-
-bootdir
- bootpc.out boot
- /386/bin/ip/ipconfig
- /386/bin/auth/factotum
- /386/bin/usb/usbd
--- a/sys/src/9/pc/pccpu
+++ /dev/null
@@ -1,99 +1,0 @@
-# pccpu - cpu server kernel
-dev
- root
- cons
- arch
- pnp pci
- env
- pipe
- proc
- mnt
- srv
- dup
- rtc
- ssl
- tls
- bridge log
- sdp thwack unthwack
- cap
- kprof
- fs
- segment
-
- ether netif
- ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
-
- sd
- floppy dma
- aoe
-
- uart
- usb
- kbin
- audio
-
-link
- realmode
- ether2000 ether8390
- ether2114x pci
- ether79c970 pci
- ether8003 ether8390
- ether8139 pci
- ether8169 pci ethermii
- ether82543gc pci
- ether82563 pci
- ether82557 pci
- ether83815 pci
- etherdp83820 pci
- etherelnk3 pci
- etherga620 pci
- etherigbe pci ethermii
- ethervgbe pci ethermii
- ethervt6102 pci ethermii
- ethervt6105m pci ethermii
-# etherm10g pci ethermii
- ether82598 pci
- ethersink
- ethermedium
- loopbackmedium
- usbuhci
- usbohci
- usbehci usbehcipc
-
-misc
- archmp mp apic
- mtrr
-
- uarti8250
- uartpci pci
- uartaxp pci
-
- sdata pci sdscsi
- sd53c8xx pci sdscsi
- sdmv50xx pci sdscsi
- sdmylex pci sdscsi
- sdiahci pci sdscsi
- sdaoe sdscsi
-
-ip
- tcp
- udp
- ipifc
- icmp
- icmp6
- gre
- ipmux
- esp
- rudp
-
-port
- int cpuserver = 1;
-
-boot cpu
- tcp
-
-bootdir
- bootpccpu.out boot
- /386/bin/ip/ipconfig ipconfig
- /386/bin/auth/factotum
- /386/bin/usb/usbd
--- a/sys/src/9/pc/pccpuf
+++ b/sys/src/9/pc/pccpuf
@@ -24,6 +24,7 @@
draw screen vga vgax
mouse mouse
+ kbd
vga
sd
@@ -32,7 +33,6 @@
uart
usb
- kbin
link
realmode
--- a/sys/src/9/pc/pcf
+++ b/sys/src/9/pc/pcf
@@ -22,9 +22,8 @@
draw screen vga vgax
mouse mouse
+ kbd
vga
- kbmap
- kbin
sd
floppy dma
--- a/sys/src/9/port/auth.c
+++ b/sys/src/9/port/auth.c
@@ -133,6 +133,7 @@
buf[n] = 0;
renameuser(eve, buf);
+ srvrenameuser(eve, buf);
kstrdup(&eve, buf);
kstrdup(&up->user, buf);
up->basepri = PriNormal;
--- a/sys/src/9/port/bootfs.proto
+++ b/sys/src/9/port/bootfs.proto
@@ -2,6 +2,8 @@
bin
9660srv
awk
+ aux
+ kbdfs
bind
bzfs
cat
--- a/sys/src/9/port/devcons.c
+++ b/sys/src/9/port/devcons.c
@@ -11,8 +11,6 @@
void (*consdebug)(void) = nil;
void (*screenputs)(char*, int) = nil;
-Queue* kbdq; /* unprocessed console input */
-Queue* lineq; /* processed console input */
Queue* serialoq; /* serial console output */
Queue* kprintoq; /* console output, for /dev/kprint */
ulong kprintinuse; /* test and set whether /dev/kprint is open */
@@ -20,30 +18,6 @@
int panicking;
-static struct
-{
- QLock;
-
- int raw; /* true if we shouldn't process input */
- Ref ctl; /* number of opens to the control file */
- int x; /* index into line */
- char line[1024]; /* current input line */
-
- int count;
- int ctlpoff;
-
- /* a place to save up characters at interrupt time before dumping them in the queue */
- Lock lockputc;
- char istage[1024];
- char *iw;
- char *ir;
- char *ie;
-} kbd = {
- .iw = kbd.istage,
- .ir = kbd.istage,
- .ie = kbd.istage + sizeof(kbd.istage),
-};
-
char *sysname;
vlong fasthz;
@@ -70,10 +44,6 @@
void
printinit(void)
{
- lineq = qopen(2*1024, 0, nil, nil);
- if(lineq == nil)
- panic("printinit");
- qnoblock(lineq, 1);
}
int
@@ -179,7 +149,7 @@
while(n > 0) {
t = memchr(str, '\n', n);
- if(t && !kbd.raw) {
+ if(t) {
m = t-str;
if(usewrite){
qwrite(serialoq, str, m);
@@ -206,8 +176,6 @@
putstrn0(str, n, 0);
}
-int noprint;
-
int
print(char *fmt, ...)
{
@@ -215,9 +183,6 @@
va_list arg;
char buf[PRINTSIZE];
- if(noprint)
- return -1;
-
va_start(arg, fmt);
n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
va_end(arg);
@@ -350,231 +315,10 @@
return n;
}
-static void
-echoscreen(char *buf, int n)
-{
- char *e, *p;
- char ebuf[128];
- int x;
-
- p = ebuf;
- e = ebuf + sizeof(ebuf) - 4;
- while(n-- > 0){
- if(p >= e){
- screenputs(ebuf, p - ebuf);
- p = ebuf;
- }
- x = *buf++;
- if(x == 0x15){
- *p++ = '^';
- *p++ = 'U';
- *p++ = '\n';
- } else
- *p++ = x;
- }
- if(p != ebuf)
- screenputs(ebuf, p - ebuf);
-}
-
-static void
-echoserialoq(char *buf, int n)
-{
- char *e, *p;
- char ebuf[128];
- int x;
-
- p = ebuf;
- e = ebuf + sizeof(ebuf) - 4;
- while(n-- > 0){
- if(p >= e){
- qiwrite(serialoq, ebuf, p - ebuf);
- p = ebuf;
- }
- x = *buf++;
- if(x == '\n'){
- *p++ = '\r';
- *p++ = '\n';
- } else if(x == 0x15){
- *p++ = '^';
- *p++ = 'U';
- *p++ = '\n';
- } else
- *p++ = x;
- }
- if(p != ebuf)
- qiwrite(serialoq, ebuf, p - ebuf);
-}
-
-static void
-echo(char *buf, int n)
-{
- static int ctrlt, pid;
- int x;
- char *e, *p;
-
- if(n == 0)
- return;
-
- e = buf+n;
- for(p = buf; p < e; p++){
- switch(*p){
- case 0x10: /* ^P */
- if(cpuserver && !kbd.ctlpoff){
- active.exiting = 1;
- return;
- }
- break;
- case 0x14: /* ^T */
- ctrlt++;
- if(ctrlt > 2)
- ctrlt = 2;
- continue;
- }
-
- if(ctrlt != 2)
- continue;
-
- /* ^T escapes */
- ctrlt = 0;
- switch(*p){
- case 'S':
- x = splhi();
- dumpstack();
- procdump();
- splx(x);
- return;
- case 's':
- dumpstack();
- return;
- case 'x':
- xsummary();
- ixsummary();
- mallocsummary();
- // memorysummary();
- pagersummary();
- return;
- case 'd':
- if(consdebug == nil)
- consdebug = rdb;
- else
- consdebug = nil;
- print("consdebug now %#p\n", consdebug);
- return;
- case 'D':
- if(consdebug == nil)
- consdebug = rdb;
- consdebug();
- return;
- case 'p':
- x = spllo();
- procdump();
- splx(x);
- return;
- case 'q':
- scheddump();
- return;
- case 'k':
- killbig("^t ^t k");
- return;
- case 'r':
- exit(0);
- return;
- }
- }
-
- qproduce(kbdq, buf, n);
- if(kbd.raw)
- return;
- kmesgputs(buf, n);
- if(screenputs != nil)
- echoscreen(buf, n);
- if(serialoq)
- echoserialoq(buf, n);
-}
-
-/*
- * Called by a uart interrupt for console input.
- *
- * turn '\r' into '\n' before putting it into the queue.
- */
-int
-kbdcr2nl(Queue*, int ch)
-{
- char *next;
-
- ilock(&kbd.lockputc); /* just a mutex */
- if(ch == '\r' && !kbd.raw)
- ch = '\n';
- next = kbd.iw+1;
- if(next >= kbd.ie)
- next = kbd.istage;
- if(next != kbd.ir){
- *kbd.iw = ch;
- kbd.iw = next;
- }
- iunlock(&kbd.lockputc);
- return 0;
-}
-
-/*
- * Put character, possibly a rune, into read queue at interrupt time.
- * Called at interrupt time to process a character.
- */
-int
-kbdputc(Queue*, int ch)
-{
- int i, n;
- char buf[3];
- Rune r;
- char *next;
-
- if(kbd.ir == nil)
- return 0; /* in case we're not inited yet */
-
- ilock(&kbd.lockputc); /* just a mutex */
- r = ch;
- n = runetochar(buf, &r);
- for(i = 0; i < n; i++){
- next = kbd.iw+1;
- if(next >= kbd.ie)
- next = kbd.istage;
- if(next == kbd.ir)
- break;
- *kbd.iw = buf[i];
- kbd.iw = next;
- }
- iunlock(&kbd.lockputc);
- return 0;
-}
-
-/*
- * we save up input characters till clock time to reduce
- * per character interrupt overhead.
- */
-static void
-kbdputcclock(void)
-{
- char *iw;
-
- /* this amortizes cost of qproduce */
- if(kbd.iw != kbd.ir){
- iw = kbd.iw;
- if(iw < kbd.ir){
- echo(kbd.ir, kbd.ie-kbd.ir);
- kbd.ir = kbd.istage;
- }
- if(kbd.ir != iw){
- echo(kbd.ir, iw-kbd.ir);
- kbd.ir = iw;
- }
- }
-}
-
enum{
Qdir,
Qbintime,
Qcons,
- Qconsctl,
Qcputime,
Qdrivers,
Qkmesg,
@@ -607,7 +351,6 @@
".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
"bintime", {Qbintime}, 24, 0664,
"cons", {Qcons}, 0, 0660,
- "consctl", {Qconsctl}, 0, 0220,
"cputime", {Qcputime}, 6*NUMSIZE, 0444,
"drivers", {Qdrivers}, 0, 0444,
"hostdomain", {Qhostdomain}, DOMLEN, 0664,
@@ -665,11 +408,6 @@
{
todinit();
randominit();
- /*
- * at 115200 baud, the 1024 char buffer takes 56 ms to process,
- * processing it every 22 ms should be fine
- */
- addclock0link(kbdputcclock, 22);
}
static Chan*
@@ -696,10 +434,6 @@
c->aux = nil;
c = devopen(c, omode, consdir, nelem(consdir), devgen);
switch((ulong)c->qid.path){
- case Qconsctl:
- incref(&kbd.ctl);
- break;
-
case Qkprint:
if(tas(&kprintinuse) != 0){
c->flag &= ~COPEN;
@@ -724,14 +458,6 @@
consclose(Chan *c)
{
switch((ulong)c->qid.path){
- /* last close of control file turns off raw */
- case Qconsctl:
- if(c->flag&COPEN){
- if(decref(&kbd.ctl) == 0)
- kbd.raw = 0;
- }
- break;
-
/* close of kprint allows other opens */
case Qkprint:
if(c->flag & COPEN){
@@ -747,9 +473,9 @@
{
ulong l;
Mach *mp;
- char *b, *bp, ch;
+ char *b, *bp;
char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */
- int i, k, id, send;
+ int i, k, id;
vlong offset = off;
extern char configfile[];
@@ -761,49 +487,7 @@
return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
case Qcons:
- qlock(&kbd);
- if(waserror()) {
- qunlock(&kbd);
- nexterror();
- }
- while(!qcanread(lineq)){
- if(qread(kbdq, &ch, 1) == 0)
- continue;
- send = 0;
- if(ch == 0){
- /* flush output on rawoff -> rawon */
- if(kbd.x > 0)
- send = !qcanread(kbdq);
- }else if(kbd.raw){
- kbd.line[kbd.x++] = ch;
- send = !qcanread(kbdq);
- }else{
- switch(ch){
- case '\b':
- if(kbd.x > 0)
- kbd.x--;
- break;
- case 0x15: /* ^U */
- kbd.x = 0;
- break;
- case '\n':
- case 0x04: /* ^D */
- send = 1;
- default:
- if(ch != 0x04)
- kbd.line[kbd.x++] = ch;
- break;
- }
- }
- if(send || kbd.x == sizeof kbd.line){
- qwrite(lineq, kbd.line, kbd.x);
- kbd.x = 0;
- }
- }
- n = qread(lineq, buf, n);
- qunlock(&kbd);
- poperror();
- return n;
+ error(Egreg);
case Qcputime:
k = offset;
@@ -980,7 +664,7 @@
static long
conswrite(Chan *c, void *va, long n, vlong off)
{
- char buf[256], ch;
+ char buf[256];
long l, bp;
char *a;
Mach *mp;
@@ -1007,29 +691,6 @@
putstrn0(buf, bp, 1);
a += bp;
l -= bp;
- }
- break;
-
- case Qconsctl:
- if(n >= sizeof(buf))
- n = sizeof(buf)-1;
- strncpy(buf, a, n);
- buf[n] = 0;
- for(a = buf; a;){
- if(strncmp(a, "rawon", 5) == 0){
- kbd.raw = 1;
- /* clumsy hack - wake up reader */
- ch = 0;
- qwrite(kbdq, &ch, 1);
- } else if(strncmp(a, "rawoff", 6) == 0){
- kbd.raw = 0;
- } else if(strncmp(a, "ctlpon", 6) == 0){
- kbd.ctlpoff = 0;
- } else if(strncmp(a, "ctlpoff", 7) == 0){
- kbd.ctlpoff = 1;
- }
- if(a = strchr(a, ' '))
- a++;
}
break;
--- a/sys/src/9/port/devkbin.c
+++ /dev/null
@@ -1,120 +1,0 @@
-/*
- * keyboard scan code input from outside the kernel.
- * to avoid duplication of keyboard map processing for usb.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-extern void kbdputsc(int, int);
-
-enum {
- Qdir,
- Qkbd,
-};
-
-Dirtab kbintab[] = {
- ".", {Qdir, 0, QTDIR}, 0, 0555,
- "kbin", {Qkbd, 0}, 0, 0200,
-};
-
-Lock kbinlck;
-int kbinbusy;
-
-static Chan *
-kbinattach(char *spec)
-{
- return devattach(L'Ι', spec);
-}
-
-static Walkqid*
-kbinwalk(Chan *c, Chan *nc, char **name, int nname)
-{
- return devwalk(c, nc, name, nname, kbintab, nelem(kbintab), devgen);
-}
-
-static int
-kbinstat(Chan *c, uchar *dp, int n)
-{
- return devstat(c, dp, n, kbintab, nelem(kbintab), devgen);
-}
-
-static Chan*
-kbinopen(Chan *c, int omode)
-{
- if(!iseve())
- error(Eperm);
- if(c->qid.path == Qkbd){
- lock(&kbinlck);
- if(kbinbusy){
- unlock(&kbinlck);
- error(Einuse);
- }
- kbinbusy++;
- unlock(&kbinlck);
- }
- return devopen(c, omode, kbintab, nelem(kbintab), devgen);
-}
-
-static void
-kbinclose(Chan *c)
-{
- if(c->aux){
- free(c->aux);
- c->aux = nil;
- }
- if(c->qid.path == Qkbd)
- kbinbusy = 0;
-}
-
-static long
-kbinread(Chan *c, void *a, long n, vlong )
-{
- if(c->qid.type == QTDIR)
- return devdirread(c, a, n, kbintab, nelem(kbintab), devgen);
- return 0;
-}
-
-static long
-kbinwrite(Chan *c, void *a, long n, vlong)
-{
- int i;
- uchar *p = a;
-
- if(c->qid.type == QTDIR)
- error(Eisdir);
- switch((int)c->qid.path){
- case Qkbd:
- for(i = 0; i < n; i++)
- kbdputsc(*p++, 1); /* external source */
- break;
- default:
- error(Egreg);
- }
- return n;
-}
-
-Dev kbindevtab = {
- L'Ι',
- "kbin",
-
- devreset,
- devinit,
- devshutdown,
- kbinattach,
- kbinwalk,
- kbinstat,
- kbinopen,
- devcreate,
- kbinclose,
- kbinread,
- devbread,
- kbinwrite,
- devbwrite,
- devremove,
- devwstat,
-};
--- a/sys/src/9/port/devkbmap.c
+++ /dev/null
@@ -1,179 +1,0 @@
-/*
- * keyboard map
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-enum{
- Qdir,
- Qdata,
-};
-Dirtab kbmaptab[]={
- ".", {Qdir, 0, QTDIR}, 0, 0555,
- "kbmap", {Qdata, 0}, 0, 0600,
-};
-#define NKBFILE sizeof(kbmaptab)/sizeof(kbmaptab[0])
-
-#define KBLINELEN (3*NUMSIZE+1) /* t code val\n */
-
-static Chan *
-kbmapattach(char *spec)
-{
- return devattach(L'κ', spec);
-}
-
-static Walkqid*
-kbmapwalk(Chan *c, Chan *nc, char **name, int nname)
-{
- return devwalk(c, nc, name, nname, kbmaptab, NKBFILE, devgen);
-}
-
-static int
-kbmapstat(Chan *c, uchar *dp, int n)
-{
- return devstat(c, dp, n, kbmaptab, NKBFILE, devgen);
-}
-
-static Chan*
-kbmapopen(Chan *c, int omode)
-{
- if(!iseve())
- error(Eperm);
- return devopen(c, omode, kbmaptab, NKBFILE, devgen);
-}
-
-static void
-kbmapclose(Chan *c)
-{
- if(c->aux){
- free(c->aux);
- c->aux = nil;
- }
-}
-
-static long
-kbmapread(Chan *c, void *a, long n, vlong offset)
-{
- char *bp;
- char tmp[KBLINELEN+1];
- int t, sc;
- Rune r;
-
- if(c->qid.type == QTDIR)
- return devdirread(c, a, n, kbmaptab, NKBFILE, devgen);
-
- switch((int)(c->qid.path)){
- case Qdata:
- if(kbdgetmap(offset/KBLINELEN, &t, &sc, &r)) {
- bp = tmp;
- bp += readnum(0, bp, NUMSIZE, t, NUMSIZE);
- bp += readnum(0, bp, NUMSIZE, sc, NUMSIZE);
- bp += readnum(0, bp, NUMSIZE, r, NUMSIZE);
- *bp++ = '\n';
- *bp = 0;
- n = readstr(offset%KBLINELEN, a, n, tmp);
- } else
- n = 0;
- break;
- default:
- n=0;
- break;
- }
- return n;
-}
-
-static long
-kbmapwrite(Chan *c, void *a, long n, vlong)
-{
- char line[100], *lp, *b;
- int key, m, l;
- Rune r;
-
- if(c->qid.type == QTDIR)
- error(Eperm);
-
- switch((int)(c->qid.path)){
- case Qdata:
- b = a;
- l = n;
- lp = line;
- if(c->aux){
- strcpy(line, c->aux);
- lp = line+strlen(line);
- free(c->aux);
- c->aux = nil;
- }
- while(--l >= 0) {
- *lp++ = *b++;
- if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
- *lp = 0;
- if(*line == 0)
- error(Ebadarg);
- if(*line == '\n' || *line == '#'){
- lp = line;
- continue;
- }
- lp = line;
- while(*lp == ' ' || *lp == '\t')
- lp++;
- m = strtoul(line, &lp, 0);
- key = strtoul(lp, &lp, 0);
- while(*lp == ' ' || *lp == '\t')
- lp++;
- r = 0;
- if(*lp == '\'' && lp[1])
- chartorune(&r, lp+1);
- else if(*lp == '^' && lp[1]){
- chartorune(&r, lp+1);
- if(0x40 <= r && r < 0x60)
- r -= 0x40;
- else
- error(Ebadarg);
- }else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
- r = 0xF900+lp[1]-'0';
- else if(*lp>='0' && *lp<='9') /* includes 0x... */
- r = strtoul(lp, &lp, 0);
- else
- error(Ebadarg);
- kbdputmap(m, key, r);
- lp = line;
- }
- }
- if(lp != line){
- l = lp-line;
- c->aux = lp = smalloc(l+1);
- memmove(lp, line, l);
- lp[l] = 0;
- }
- break;
- default:
- error(Ebadusefd);
- }
- return n;
-}
-
-Dev kbmapdevtab = {
- L'κ',
- "kbmap",
-
- devreset,
- devinit,
- devshutdown,
- kbmapattach,
- kbmapwalk,
- kbmapstat,
- kbmapopen,
- devcreate,
- kbmapclose,
- kbmapread,
- devbread,
- kbmapwrite,
- devbwrite,
- devremove,
- devwstat,
-};
--- a/sys/src/9/port/devsrv.c
+++ b/sys/src/9/port/devsrv.c
@@ -352,3 +352,15 @@
srvremove,
srvwstat,
};
+
+void
+srvrenameuser(char *old, char *new)
+{
+ Srv *sp;
+
+ qlock(&srvlk);
+ for(sp = srv; sp; sp = sp->link)
+ if(sp->owner!=nil && strcmp(old, sp->owner)==0)
+ kstrdup(&sp->owner, new);
+ qunlock(&srvlk);
+}
--- a/sys/src/9/port/devuart.c
+++ b/sys/src/9/port/devuart.c
@@ -223,9 +223,7 @@
if(p->console || p->special){
if(uartenable(p) != nil){
if(p->console){
- kbdq = p->iq;
serialoq = p->oq;
- p->putc = kbdcr2nl;
}
p->opens++;
}
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -142,10 +142,6 @@
int ispages(void*);
int isphysseg(char*);
void ixsummary(void);
-int kbdcr2nl(Queue*, int);
-int kbdgetmap(uint, int*, int*, Rune*);
-int kbdputc(Queue*, int);
-void kbdputmap(ushort, ushort, Rune);
void kickpager(void);
void killbig(char*);
void kproc(char*, void(*)(void*), void*);
@@ -323,6 +319,7 @@
void splx(int);
void splxpc(int);
char* srvname(Chan*);
+void srvrenameuser(char*, char*);
int swapcount(ulong);
int swapfull(void);
void swapinit(void);
--- /dev/null
+++ b/sys/src/cmd/aux/kbdfs.c
@@ -1,0 +1,1159 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
+enum {
+ Spec= 0xF800, /* Unicode private space */
+ 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,
+ Altgr= Spec|0x67,
+ Kmouse= Spec|0x100,
+ No= 0x00, /* peter */
+
+ Home= KF|13,
+ Up= KF|14,
+ Pgup= KF|15,
+ Print= KF|16,
+ Left= KF|17,
+ Right= KF|18,
+ End= KF|24,
+ Down= View,
+ Pgdown= KF|19,
+ Ins= KF|20,
+ Del= 0x7F,
+ Scroll= KF|21,
+
+ Nscan= 128,
+
+ Int= 0, /* scans indices */
+ Ext,
+ Nscans,
+
+ Qroot= 0,
+ Qkbd,
+ Qkbin,
+ Qkbmap,
+ Qcons,
+ Qconsctl,
+ Nqid,
+
+ Rawon= 0,
+ Rawoff,
+ Kbdflush,
+
+ STACKSZ = 8*1024,
+};
+
+typedef struct Key Key;
+typedef struct Scan Scan;
+
+struct Key {
+ int down;
+ int c;
+ Rune r;
+};
+
+struct Scan {
+ int esc1;
+ int esc2;
+ int caps;
+ int num;
+ int shift;
+ int ctrl;
+ int latin;
+ int altgr;
+ int leds;
+};
+
+struct Qtab {
+ char *name;
+ int mode;
+ int type;
+} qtab[Nqid] = {
+ "/",
+ DMDIR|0555,
+ QTDIR,
+
+ "kbd",
+ 0666,
+ 0,
+
+ "kbin",
+ 0222,
+ 0,
+
+ "kbmap",
+ 0666,
+ 0,
+
+ "cons",
+ 0666,
+ 0,
+
+ "consctl",
+ 0666,
+ 0,
+};
+
+char Eshort[] = "read count too small";
+char Ebadarg[] = "invalid argument";
+char Eperm[] = "permission denied";
+char Enonexist[] = "file does not exist";
+char Ebadspec[] = "bad attach specifier";
+char Ewalk[] = "walk in non directory";
+char Efront[] = "the front fell off";
+
+int scanfd;
+int ledsfd;
+
+int consfd;
+int echofd;
+
+int kbdopen;
+int consopen;
+
+Channel *keychan; /* Key */
+
+Channel *reqchan; /* Req* */
+Channel *ctlchan; /* int */
+
+Channel *rawchan; /* Rune */
+Channel *linechan; /* char * */
+Channel *kbdchan; /* char* */
+
+/*
+ * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
+ * A 'standard' keyboard doesn't produce anything above 0x58.
+ */
+Rune kbtab[Nscan] =
+{
+[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[Nscan] =
+{
+[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[Nscan] =
+{
+[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] Altgr, 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,
+};
+
+Rune kbtabaltgr[Nscan] =
+{
+[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] Altgr, 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,
+};
+
+Rune kbtabctrl[Nscan] =
+{
+[0x00] No, '', '', '', '', '', '', '',
+[0x08] '', '', '', '', ' ', '', '\b', '\t',
+[0x10] '', '', '', '', '', '', '', '\t',
+[0x18] '', '', '', '', '\n', Ctrl, '', '',
+[0x20] '', '', '', '\b', '\n', '', '', '',
+[0x28] '', No, Shift, '', '', '', '', '',
+[0x30] '', '', ' ', '', '', '', Shift, '\n',
+[0x38] Latin, No, Ctrl, '', '', '', '', '',
+[0x40] '', '', '', ' ', '', '', '', '',
+[0x48] '', '', ' ', '', '', '', '', '',
+[0x50] '', '', '', '', No, No, No, '',
+[0x58] '', 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, '', No, '\b', No, No, No, No,
+};
+
+void reboot(void);
+
+/*
+ * Scan code processing
+ */
+void
+kbdputsc(Scan *scan, int c)
+{
+ Key key;
+
+ /*
+ * e0's is the first of a 2 character sequence, e1 the first
+ * of a 3 character sequence (on the safari)
+ */
+ if(c == 0xe0){
+ scan->esc1 = 1;
+ return;
+ } else if(c == 0xe1){
+ scan->esc2 = 2;
+ return;
+ }
+
+ key.down = (c & 0x80) == 0;
+ key.c = c & 0x7f;
+
+ if(key.c >= Nscan)
+ return;
+
+ if(scan->esc1)
+ key.r = kbtabesc1[key.c];
+ else if(scan->shift)
+ key.r = kbtabshift[key.c];
+ else if(scan->altgr)
+ key.r = kbtabaltgr[key.c];
+ else if(scan->ctrl)
+ key.r = kbtabctrl[key.c];
+ else
+ key.r = kbtab[key.c];
+
+ if(scan->caps && key.r<='z' && key.r>='a')
+ key.r += 'A' - 'a';
+
+ if(scan->ctrl && scan->latin && key.r == Del)
+ reboot();
+
+ send(keychan, &key);
+
+ if(scan->esc1)
+ scan->esc1 = 0;
+ else if(scan->esc2)
+ scan->esc2--;
+
+ switch(key.r){
+ case Shift:
+ scan->shift = key.down;
+ break;
+ case Ctrl:
+ scan->ctrl = key.down;
+ break;
+ case Altgr:
+ scan->altgr = key.down;
+ break;
+ case Latin:
+ scan->latin = key.down;
+ break;
+ case Num:
+ scan->num ^= key.down;
+ break;
+ case Caps:
+ scan->caps ^= key.down;
+ break;
+ }
+}
+
+void
+setleds(Scan *scan, int leds)
+{
+ char buf[8];
+
+ if(ledsfd < 0 || scan->leds == leds)
+ return;
+ leds &= 7;
+ snprint(buf, sizeof(buf), "%d", leds);
+ pwrite(ledsfd, buf, strlen(buf), 0);
+ scan->leds = leds;
+}
+
+/*
+ * Read scan codes from scanfd
+ */
+void
+scanproc(void *)
+{
+ uchar buf[64];
+ Scan scan;
+ int i, n;
+
+ threadsetname("scanproc");
+
+ memset(&scan, 0, sizeof scan);
+ while((n = read(scanfd, buf, sizeof buf)) > 0){
+ for(i=0; i<n; i++)
+ kbdputsc(&scan, buf[i]);
+ setleds(&scan, (scan.num<<1) | (scan.caps<<2));
+ }
+}
+
+char*
+utfconv(Rune *r, int n)
+{
+ char *s, *p;
+ int l;
+
+ l = runenlen(r, n) + 1;
+ s = emalloc9p(l);
+ for(p = s; n > 0; r++, n--)
+ p += runetochar(p, r);
+ *p = 0;
+ return s;
+}
+
+/*
+ * Read key events from keychan and produce characters to
+ * rawchan and keystate in kbdchan. this way here is only
+ * one global keystate even if multiple keyboards are used.
+ */
+void
+keyproc(void *)
+{
+ int cb[Nscan];
+ Rune rb[Nscan];
+ Key key;
+ int i, nb;
+ char *s;
+
+ threadsetname("keyproc");
+
+ nb = 0;
+ while(recv(keychan, &key) > 0){
+ if(key.down){
+ switch(key.r){
+ case Caps:
+ case Num:
+ case Shift:
+ case Latin:
+ case Ctrl:
+ case Altgr:
+ case Kmouse|1:
+ case Kmouse|2:
+ case Kmouse|3:
+ case Kmouse|4:
+ case Kmouse|5:
+ case KF|11:
+ case KF|12:
+ break;
+ default:
+ nbsend(rawchan, &key.r);
+ }
+ }
+
+ s = nil;
+ for(i=0; i<nb && cb[i] != key.c; i++)
+ ;
+ if(!key.down){
+ if(i < nb){
+ memmove(cb+i, cb+i+1, (nb-i+1) * sizeof(cb[0]));
+ memmove(rb+i, rb+i+1, (nb-i+1) * sizeof(rb[0]));
+ nb--;
+ s = utfconv(rb, nb);
+ }
+ } else if(i == nb && nb < nelem(cb) && key.r){
+ cb[nb] = key.c;
+ rb[nb] = key.r;
+ nb++;
+ s = utfconv(rb, nb);
+ }
+ if(s && nbsendp(kbdchan, s) <= 0)
+ free(s);
+ }
+}
+
+/*
+ * Read characters from consfd (serial console)
+ */
+void
+consproc(void *)
+{
+ char *p, *e, *x, buf[64];
+ Rune r;
+ int n;
+
+ threadsetname("consproc");
+
+ p = buf;
+ e = buf + sizeof(buf);
+ while((n = read(consfd, p, e - p)) > 0){
+ x = buf + n;
+ while(p < x && fullrune(p, x - p)){
+ p += chartorune(&r, p);
+ send(rawchan, &r);
+ }
+ n = x - p;
+ if(n > 0){
+ memmove(buf, p, n);
+ p = buf + n;
+ }
+ }
+}
+
+/*
+ * Cook lines for cons
+ */
+void
+lineproc(void *aux)
+{
+ char *l, *p, *e, *s;
+ Channel *cook;
+ int done;
+ Rune r;
+
+ cook = aux;
+
+ threadsetname("lineproc");
+
+ for(;;){
+ l = emalloc9p(1024);
+ p = s = l;
+ e = l + 1024-(UTFmax+1);
+ done = 0;
+ do {
+ recv(cook, &r);
+ switch(r){
+ case '\0': /* flush */
+ p = l;
+ continue;
+ case '\b': /* backspace */
+ while(p > l){
+ --p;
+ if(fullrune(p, s - p))
+ break;
+ }
+ write(echofd, "\b", 1);
+ continue;
+ case 0x04: /* eof */
+ p = l;
+ done = 1;
+ break;
+ case '\r':
+ continue;
+ case '\n':
+ done = 1;
+ default:
+ p += runetochar(s = p, &r);
+ write(echofd, s, p - s);
+ }
+ } while(!done && p < e);
+ *p = 0;
+ sendp(linechan, l);
+ }
+}
+
+enum {
+ Areq,
+ Actl,
+ Araw,
+ Aline,
+ Akbd,
+ Aend,
+};
+
+/*
+ * Queue reads to cons and kbd, flushing and
+ * relay data between 9p and rawchan / kbdchan.
+ */
+void
+ctlproc(void *)
+{
+ struct {
+ Req *h;
+ Req **t;
+ } qcons, qkbd, *q;
+ Alt a[Aend+1];
+ Req *req;
+ Fid *fid;
+ Rune r;
+ char *s, *b, *p, *e;
+ int c, n, raw;
+ Channel *cook;
+
+ threadsetname("ctlproc");
+
+ cook = chancreate(sizeof(Rune), 0);
+
+ if(scanfd >= 0)
+ proccreate(scanproc, nil, STACKSZ);
+ if(consfd >= 0)
+ proccreate(consproc, nil, STACKSZ);
+
+ threadcreate(keyproc, nil, STACKSZ);
+ threadcreate(lineproc, cook, STACKSZ);
+
+ raw = 0;
+
+ b = p = e = nil;
+
+ qcons.h = nil;
+ qcons.t = &qcons.h;
+ qkbd.h = nil;
+ qkbd.t = &qkbd.h;
+
+ memset(a, 0, sizeof a);
+
+ a[Areq].c = reqchan;
+ a[Areq].v = &req;
+ a[Areq].op = CHANRCV;
+
+ a[Actl].c = ctlchan;
+ a[Actl].v = &c;
+ a[Actl].op = CHANRCV;
+
+ a[Araw].c = rawchan;
+ a[Araw].v = &r;
+ a[Araw].op = CHANRCV;
+
+ a[Aline].c = linechan;
+ a[Aline].v = &s;
+ a[Aline].op = CHANRCV;
+
+ a[Akbd].c = kbdchan;
+ a[Akbd].v = &s;
+ a[Akbd].op = CHANRCV;
+
+ a[Aend].op = CHANEND;
+
+ for(;;){
+ s = nil;
+
+ a[Araw].op = (b == nil) ? CHANRCV : CHANNOP;
+ a[Aline].op = (b == nil) ? CHANRCV : CHANNOP;
+ a[Akbd].op = qkbd.h || !kbdopen ? CHANRCV : CHANNOP;
+
+ switch(alt(a)){
+ case Areq:
+ fid = req->fid;
+ if(req->ifcall.type == Tflush){
+ Req **rr;
+
+ fid = req->oldreq->fid;
+ q = fid->qid.path == Qcons ? &qcons : &qkbd;
+ for(rr = &q->h; *rr && *rr != req->oldreq; rr = &((*rr)->aux))
+ ;
+ if(*rr == req->oldreq){
+ if((*rr = req->oldreq->aux) == nil)
+ q->t = rr;
+ req->oldreq->aux = nil;
+ respond(req->oldreq, "interrupted");
+ }
+ respond(req, nil);
+ } else if(req->ifcall.type == Tread){
+ q = fid->qid.path == Qcons ? &qcons : &qkbd;
+ req->aux = nil;
+ *q->t = req;
+ q->t = &req->aux;
+ goto Havereq;
+ } else
+ respond(req, Efront);
+ break;
+
+ case Actl:
+ switch(c){
+ case Rawoff:
+ case Rawon:
+ raw = (c == Rawon);
+ if(raw){
+ while(s = nbrecvp(linechan))
+ free(s);
+ r = '\0';
+ send(cook, &r);
+ free(b);
+ b = nil;
+ }
+ break;
+ case Kbdflush:
+ while(s = nbrecvp(kbdchan))
+ free(s);
+ break;
+ }
+ break;
+
+ case Araw:
+ if(raw){
+ s = emalloc9p(UTFmax+1);
+ s[runetochar(s, &r)] = 0;
+ } else {
+ send(cook, &r);
+ break;
+ }
+ /* no break */
+
+ case Aline:
+ b = s;
+ p = s;
+ e = s + strlen(s);
+
+ Havereq:
+ while(b && (req = qcons.h)){
+ if((qcons.h = req->aux) == nil)
+ qcons.t = &qcons.h;
+ n = e - p;
+ if(req->ifcall.count < n)
+ n = req->ifcall.count;
+ req->ofcall.count = n;
+ memmove(req->ofcall.data, p, n);
+ respond(req, nil);
+ p += n;
+ if(p >= e){
+ free(b);
+ b = nil;
+ }
+ }
+ break;
+
+ case Akbd:
+ if(req = qkbd.h){
+ if((qkbd.h = req->aux) == nil)
+ qkbd.t = &qkbd.h;
+ n = strlen(s) + 1;
+ if(n > req->ifcall.count)
+ respond(req, Eshort);
+ else {
+ req->ofcall.count = n;
+ memmove(req->ofcall.data, s, n);
+ respond(req, nil);
+ }
+ }
+ break;
+ }
+ }
+}
+
+/*
+ * Keyboard layout maps
+ */
+
+Rune*
+kbmapent(int t, int sc)
+{
+ if(sc < 0 || sc >= Nscan)
+ return nil;
+ switch(t){
+ default:
+ return nil;
+ case 0:
+ return &kbtab[sc];
+ case 1:
+ return &kbtabshift[sc];
+ case 2:
+ return &kbtabesc1[sc];
+ case 3:
+ return &kbtabaltgr[sc];
+ case 4:
+ return &kbtabctrl[sc];
+ }
+}
+
+void
+kbmapread(Req *req)
+{
+ char tmp[3*12+1];
+ int t, sc, off, n;
+ Rune *rp;
+
+ off = req->ifcall.offset/(sizeof(tmp)-1);
+ t = off/Nscan;
+ sc = off%Nscan;
+ if(rp = kbmapent(t, sc))
+ sprint(tmp, "%11d %11d %11d\n", t, sc, *rp);
+ else
+ *tmp = 0;
+ n = strlen(tmp);
+ if(req->ifcall.count < n)
+ n = req->ifcall.count;
+ req->ofcall.count = n;
+ memmove(req->ofcall.data, tmp, n);
+ respond(req, nil);
+}
+
+void
+kbmapwrite(Req *req)
+{
+ char line[100], *lp, *b;
+ Rune r, *rp;
+ int sc, t, l;
+ Fid *f;
+
+ f = req->fid;
+ b = req->ifcall.data;
+ l = req->ifcall.count;
+ lp = line;
+ if(f->aux){
+ strcpy(line, f->aux);
+ lp = line+strlen(line);
+ free(f->aux);
+ f->aux = nil;
+ }
+ while(--l >= 0) {
+ *lp++ = *b++;
+ if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
+ *lp = 0;
+ if(*line == 0){
+ Badarg:
+ respond(req, Ebadarg);
+ return;
+ }
+ if(*line == '\n' || *line == '#'){
+ lp = line;
+ continue;
+ }
+ lp = line;
+ while(*lp == ' ' || *lp == '\t')
+ lp++;
+ t = strtoul(line, &lp, 0);
+ sc = strtoul(lp, &lp, 0);
+ while(*lp == ' ' || *lp == '\t')
+ lp++;
+ if((rp = kbmapent(t, sc)) == nil)
+ goto Badarg;
+ r = 0;
+ if(*lp == '\'' && lp[1])
+ chartorune(&r, lp+1);
+ else if(*lp == '^' && lp[1]){
+ chartorune(&r, lp+1);
+ if(0x40 <= r && r < 0x60)
+ r -= 0x40;
+ else
+ goto Badarg;
+ }else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
+ r = 0xF900+lp[1]-'0';
+ else if(*lp>='0' && *lp<='9') /* includes 0x... */
+ r = strtoul(lp, &lp, 0);
+ else
+ goto Badarg;
+ *rp = r;
+ lp = line;
+ }
+ }
+ if(lp != line){
+ l = lp-line;
+ f->aux = lp = emalloc9p(l+1);
+ memmove(lp, line, l);
+ lp[l] = 0;
+ }
+ req->ofcall.count = req->ifcall.count;
+ respond(req, nil);
+}
+
+/*
+ * Filesystem
+ */
+
+static int
+fillstat(ulong qid, Dir *d)
+{
+ struct Qtab *t;
+
+ memset(d, 0, sizeof *d);
+ d->uid = "kbd";
+ d->gid = "kbd";
+ d->muid = "";
+ d->qid = (Qid){qid, 0, 0};
+ d->atime = time(0);
+ t = qtab + qid;
+ d->name = t->name;
+ d->qid.type = t->type;
+ d->mode = t->mode;
+ return 1;
+}
+
+static void
+fsattach(Req *r)
+{
+ char *spec;
+
+ spec = r->ifcall.aname;
+ if(spec && spec[0]){
+ respond(r, Ebadspec);
+ return;
+ }
+ r->fid->qid = (Qid){Qroot, 0, QTDIR};
+ r->ofcall.qid = r->fid->qid;
+ respond(r, nil);
+}
+
+static void
+fsstat(Req *r)
+{
+ fillstat((ulong)r->fid->qid.path, &r->d);
+ r->d.name = estrdup9p(r->d.name);
+ r->d.uid = estrdup9p(r->d.uid);
+ r->d.gid = estrdup9p(r->d.gid);
+ r->d.muid = estrdup9p(r->d.muid);
+ respond(r, nil);
+}
+
+static char*
+fswalk1(Fid *fid, char *name, Qid *qid)
+{
+ int i;
+ ulong path;
+
+ path = fid->qid.path;
+ switch(path){
+ case Qroot:
+ if (strcmp(name, "..") == 0) {
+ *qid = (Qid){Qroot, 0, QTDIR};
+ fid->qid = *qid;
+ return nil;
+ }
+ for(i = fid->qid.path; i<Nqid; i++){
+ if(strcmp(name, qtab[i].name) != 0)
+ continue;
+ *qid = (Qid){i, 0, 0};
+ fid->qid = *qid;
+ return nil;
+ }
+ return Enonexist;
+
+ default:
+ return Ewalk;
+ }
+}
+
+static void
+fsopen(Req *r)
+{
+ Fid *f;
+ static int need[4] = { 4, 2, 6, 1 };
+ struct Qtab *t;
+ int n;
+
+ f = r->fid;
+ t = qtab + f->qid.path;
+ n = need[r->ifcall.mode & 3];
+ if((n & t->mode) != n)
+ respond(r, Eperm);
+ else{
+ f->aux = nil;
+ switch((ulong)f->qid.path){
+ case Qkbd:
+ if(kbdopen++ == 0)
+ sendul(ctlchan, Kbdflush);
+ break;
+ case Qcons:
+ case Qconsctl:
+ if(consopen++ == 0)
+ sendul(ctlchan, Rawoff);
+ break;
+ }
+ respond(r, nil);
+ }
+}
+
+static int
+readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
+{
+ int i, m, n;
+ long pos;
+ Dir d;
+
+ n = 0;
+ pos = 0;
+ for (i = 1; i < Nqid; i++){
+ fillstat(i, &d);
+ m = convD2M(&d, &buf[n], blen-n);
+ if(off <= pos){
+ if(m <= BIT16SZ || m > cnt)
+ break;
+ n += m;
+ cnt -= m;
+ }
+ pos += m;
+ }
+ return n;
+}
+
+static void
+fsread(Req *r)
+{
+ Fid *f;
+
+ f = r->fid;
+ switch((ulong)f->qid.path){
+ default:
+ respond(r, Efront);
+ return;
+
+ case Qroot:
+ r->ofcall.count = readtopdir(f, (void*)r->ofcall.data, r->ifcall.offset,
+ r->ifcall.count, r->ifcall.count);
+ break;
+
+ case Qkbd:
+ case Qcons:
+ sendp(reqchan, r);
+ return;
+
+ case Qkbmap:
+ kbmapread(r);
+ return;
+ }
+ respond(r, nil);
+}
+
+static void
+fswrite(Req *r)
+{
+ Fid *f;
+ char *p;
+ int n, i;
+
+ f = r->fid;
+ switch((ulong)f->qid.path){
+ default:
+ respond(r, Efront);
+ return;
+
+ case Qcons:
+ n = r->ifcall.count;
+ if(write(echofd, r->ifcall.data, n) != n){
+ responderror(r);
+ return;
+ }
+ r->ofcall.count = n;
+ break;
+
+ case Qconsctl:
+ p = r->ifcall.data;
+ n = r->ifcall.count;
+ if(n >= 5 && memcmp(p, "rawon", 5) == 0)
+ sendul(ctlchan, Rawon);
+ else if(n >= 6 && memcmp(p, "rawoff", 6) == 0)
+ sendul(ctlchan, Rawoff);
+ else {
+ respond(r, Ebadarg);
+ return;
+ }
+ r->ofcall.count = n;
+ break;
+
+ case Qkbin:
+ if(f->aux == nil){
+ f->aux = emalloc9p(sizeof(Scan));
+ memset(f->aux, 0, sizeof(Scan));
+ }
+ for(i=0; i<r->ifcall.count; i++)
+ kbdputsc((Scan*)f->aux, (uchar)r->ifcall.data[i]);
+ r->ofcall.count = i;
+ break;
+
+ case Qkbmap:
+ kbmapwrite(r);
+ return;
+
+ }
+ respond(r, nil);
+}
+
+static void
+fsflush(Req *r)
+{
+ switch((ulong)r->oldreq->fid->qid.path) {
+ case Qkbd:
+ case Qcons:
+ sendp(reqchan, r);
+ return;
+ }
+ respond(r, nil);
+}
+
+static void
+fsdestroyfid(Fid *f)
+{
+ void *p;
+
+ if(f->omode != -1)
+ switch((ulong)f->qid.path){
+ case Qkbin:
+ case Qkbmap:
+ if(p = f->aux){
+ f->aux = nil;
+ free(p);
+ }
+ break;
+ case Qkbd:
+ kbdopen--;
+ break;
+ case Qcons:
+ case Qconsctl:
+ consopen--;
+ break;
+ }
+}
+
+static void
+fsend(Srv*)
+{
+ threadexitsall(nil);
+}
+
+Srv fs = {
+ .attach= fsattach,
+ .walk1= fswalk1,
+ .open= fsopen,
+ .read= fsread,
+ .write= fswrite,
+ .stat= fsstat,
+ .flush= fsflush,
+ .destroyfid= fsdestroyfid,
+ .end= fsend,
+};
+
+void
+reboot(void)
+{
+ int fd;
+
+ if((fd = open("/dev/reboot", OWRITE)) < 0){
+ fprint(2, "can't open /dev/reboot: %r\n");
+ return;
+ }
+ fprint(fd, "reboot\n");
+ close(fd);
+}
+
+void
+elevate(void)
+{
+ char buf[128];
+ Dir *d, nd;
+ int fd;
+
+ snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
+ if((fd = open(buf, OWRITE)) < 0){
+ fprint(2, "can't open %s: %r\n", buf);
+ return;
+ }
+
+ /* get higher than normal priority */
+ fprint(fd, "pri 16");
+
+ /* dont let anybody kill us */
+ if(d = dirfstat(fd)){
+ nulldir(&nd);
+ nd.mode = d->mode & ~0222;
+ dirfwstat(fd, &nd);
+ free(d);
+ }
+
+ close(fd);
+
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: kbdfs [-m mntpnt]\n");
+ exits("usage");
+}
+
+void
+threadmain(int argc, char** argv)
+{
+ char *mtpt = "/dev";
+ char *srv = nil;
+ char *cons = nil;
+
+ consfd = -1;
+ echofd = 1;
+
+ ARGBEGIN{
+ case 'D':
+ chatty9p++;
+ break;
+ case 'm':
+ mtpt = EARGF(usage());
+ break;
+ case 's':
+ srv = EARGF(usage());
+ break;
+ case 'c':
+ cons = EARGF(usage());
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if((scanfd = open("/dev/scancode", OREAD)) < 0)
+ fprint(2, "can't open /dev/scancode: %r\n");
+ if((ledsfd = open("/dev/leds", OWRITE)) < 0)
+ fprint(2, "can't open /dev/leds: %r\n");
+
+ if(cons){
+ if((consfd = open(cons, ORDWR)) < 0)
+ fprint(2, "can't open %s: %r\n", cons);
+ else
+ echofd = consfd;
+ }
+
+ keychan = chancreate(sizeof(Key), 8);
+ reqchan = chancreate(sizeof(Req*), 0);
+ ctlchan = chancreate(sizeof(int), 0);
+ rawchan = chancreate(sizeof(Rune), 32);
+ linechan = chancreate(sizeof(char*), 16);
+ kbdchan = chancreate(sizeof(char*), 16);
+
+ elevate();
+
+ procrfork(ctlproc, nil, STACKSZ, RFNAMEG|RFNOTEG);
+
+ threadpostmountsrv(&fs, srv, mtpt, MBEFORE);
+}
--- a/sys/src/cmd/aux/mkfile
+++ b/sys/src/cmd/aux/mkfile
@@ -16,6 +16,7 @@
depend\
disksim\
getflags\
+ kbdfs\
lines\
listen\
listen1\