diff --git a/lib/namespace b/lib/namespace index 87f30eb4f..81105f7e6 100755 --- a/lib/namespace +++ b/lib/namespace @@ -14,6 +14,7 @@ bind -a #S /dev # mount points mount -a /srv/slashn /n +mount -b /srv/cons /dev # authentication mount -a /srv/factotum /mnt diff --git a/sys/src/9/boot/bootrc b/sys/src/9/boot/bootrc index f1d4c37cf..8a05621c5 100644 --- 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 >[2]/dev/cons +} + bind -qa '#S' /dev bind -qa '#f' /dev bind -qa '#k' /dev diff --git a/sys/src/9/pc/devkbd.c b/sys/src/9/pc/devkbd.c new file mode 100644 index 000000000..b7cc494e1 --- /dev/null +++ b/sys/src/9/pc/devkbd.c @@ -0,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; iqid.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"); +} diff --git a/sys/src/9/pc/kbd.c b/sys/src/9/pc/kbd.c deleted file mode 100644 index 69ee3162d..000000000 --- a/sys/src/9/pc/kbd.c +++ /dev/null @@ -1,715 +0,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; inum) - 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; ink; 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; - } -} diff --git a/sys/src/9/pc/mkfile b/sys/src/9/pc/mkfile index f6814ac32..2170c1268 100644 --- 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 @@ OBJ=\ cga.$O\ i8253.$O\ i8259.$O\ - kbd.$O\ main.$O\ memory.$O\ mmu.$O\ diff --git a/sys/src/9/pc/mouse.c b/sys/src/9/pc/mouse.c index 282e3595f..66bc1f937 100644 --- a/sys/src/9/pc/mouse.c +++ b/sys/src/9/pc/mouse.c @@ -22,8 +22,6 @@ enum MousePS2= 2, }; -extern int mouseshifted; - static QLock mousectlqlock; static int mousetype; static int intellimouse; @@ -95,11 +93,6 @@ ps2mouseputc(int c, int shift) 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. */ diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc deleted file mode 100644 index 84017436b..000000000 --- a/sys/src/9/pc/pc +++ /dev/null @@ -1,134 +0,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 diff --git a/sys/src/9/pc/pccpu b/sys/src/9/pc/pccpu deleted file mode 100644 index e4a71194d..000000000 --- a/sys/src/9/pc/pccpu +++ /dev/null @@ -1,99 +0,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 diff --git a/sys/src/9/pc/pccpuf b/sys/src/9/pc/pccpuf index e3372cff1..a5e7407e1 100644 --- a/sys/src/9/pc/pccpuf +++ b/sys/src/9/pc/pccpuf @@ -24,6 +24,7 @@ dev draw screen vga vgax mouse mouse + kbd vga sd @@ -32,7 +33,6 @@ dev uart usb - kbin link realmode diff --git a/sys/src/9/pc/pcf b/sys/src/9/pc/pcf index 3edb863be..900b6ed1f 100644 --- a/sys/src/9/pc/pcf +++ b/sys/src/9/pc/pcf @@ -22,9 +22,8 @@ dev draw screen vga vgax mouse mouse + kbd vga - kbmap - kbin sd floppy dma diff --git a/sys/src/9/port/auth.c b/sys/src/9/port/auth.c index 9565acd4e..7521e5a43 100644 --- a/sys/src/9/port/auth.c +++ b/sys/src/9/port/auth.c @@ -133,6 +133,7 @@ hostownerwrite(char *a, int n) buf[n] = 0; renameuser(eve, buf); + srvrenameuser(eve, buf); kstrdup(&eve, buf); kstrdup(&up->user, buf); up->basepri = PriNormal; diff --git a/sys/src/9/port/bootfs.proto b/sys/src/9/port/bootfs.proto index 62749e365..c7b25d271 100644 --- a/sys/src/9/port/bootfs.proto +++ b/sys/src/9/port/bootfs.proto @@ -2,6 +2,8 @@ $cputype bin 9660srv awk + aux + kbdfs bind bzfs cat diff --git a/sys/src/9/port/devcons.c b/sys/src/9/port/devcons.c index 8ede174f0..5cd736662 100644 --- 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 iprintscreenputs = 1; 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 @@ Cmdtab rebootmsg[] = void printinit(void) { - lineq = qopen(2*1024, 0, nil, nil); - if(lineq == nil) - panic("printinit"); - qnoblock(lineq, 1); } int @@ -179,7 +149,7 @@ putstrn0(char *str, int n, int usewrite) 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 @@ putstrn(char *str, int n) putstrn0(str, n, 0); } -int noprint; - int print(char *fmt, ...) { @@ -215,9 +183,6 @@ print(char *fmt, ...) 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 @@ pprint(char *fmt, ...) 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 @@ static Dirtab consdir[]={ ".", {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 @@ consinit(void) { 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 @@ consopen(Chan *c, int omode) 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 @@ static void 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 @@ consread(Chan *c, void *buf, long n, vlong off) { 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 @@ consread(Chan *c, void *buf, long n, vlong off) 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 @@ consread(Chan *c, void *buf, long n, vlong off) 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; @@ -1010,29 +694,6 @@ conswrite(Chan *c, void *va, long n, vlong off) } 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; - case Qtime: if(!iseve()) error(Eperm); diff --git a/sys/src/9/port/devkbin.c b/sys/src/9/port/devkbin.c deleted file mode 100644 index 1f5fae8e0..000000000 --- a/sys/src/9/port/devkbin.c +++ /dev/null @@ -1,120 +0,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, -}; diff --git a/sys/src/9/port/devkbmap.c b/sys/src/9/port/devkbmap.c deleted file mode 100644 index fec4d8efb..000000000 --- a/sys/src/9/port/devkbmap.c +++ /dev/null @@ -1,179 +0,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, -}; diff --git a/sys/src/9/port/devsrv.c b/sys/src/9/port/devsrv.c index 0a8996750..2c021289e 100644 --- a/sys/src/9/port/devsrv.c +++ b/sys/src/9/port/devsrv.c @@ -352,3 +352,15 @@ Dev srvdevtab = { 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); +} diff --git a/sys/src/9/port/devuart.c b/sys/src/9/port/devuart.c index a93f70e4c..e534fa1c3 100644 --- a/sys/src/9/port/devuart.c +++ b/sys/src/9/port/devuart.c @@ -223,9 +223,7 @@ uartreset(void) if(p->console || p->special){ if(uartenable(p) != nil){ if(p->console){ - kbdq = p->iq; serialoq = p->oq; - p->putc = kbdcr2nl; } p->opens++; } diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 14c3506e5..ca56a6cf0 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -142,10 +142,6 @@ Segment* isoverlap(Proc*, ulong, int); 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 @@ int spllo(void); void splx(int); void splxpc(int); char* srvname(Chan*); +void srvrenameuser(char*, char*); int swapcount(ulong); int swapfull(void); void swapinit(void); diff --git a/sys/src/cmd/aux/kbdfs.c b/sys/src/cmd/aux/kbdfs.c new file mode 100644 index 000000000..d04f885a9 --- /dev/null +++ b/sys/src/cmd/aux/kbdfs.c @@ -0,0 +1,1159 @@ +#include +#include +#include +#include +#include +#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 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 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; iqid = *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; iifcall.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); +} diff --git a/sys/src/cmd/aux/mkfile b/sys/src/cmd/aux/mkfile index e36db1a32..d6284a1d9 100644 --- a/sys/src/cmd/aux/mkfile +++ b/sys/src/cmd/aux/mkfile @@ -16,6 +16,7 @@ TARG=\ depend\ disksim\ getflags\ + kbdfs\ lines\ listen\ listen1\