1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
#include "u.h"
#include "lib.h"
#include "dat.h"
#include "fns.h"
#include "error.h"
static Queue* keyq;
static int kbdinuse;
void
kbdkey(Rune r, int down)
{
char buf[2+UTFmax];
if(r == 0)
return;
if(!kbdinuse || keyq == nil){
if(down)
kbdputc(kbdq, r); /* /dev/cons */
return;
}
memset(buf, 0, sizeof buf);
buf[0] = down ? 'r' : 'R';
qproduce(keyq, buf, 2+runetochar(buf+1, &r));
}
enum{
Qdir,
Qkbd,
};
static Dirtab kbddir[]={
".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
"kbd", {Qkbd}, 0, 0444,
};
static void
kbdinit(void)
{
keyq = qopen(4*1024, Qcoalesce, 0, 0);
if(keyq == nil)
panic("kbdinit");
qnoblock(keyq, 1);
}
static Chan*
kbdattach(char *spec)
{
return devattach('b', spec);
}
static Walkqid*
kbdwalk(Chan *c, Chan *nc, char **name, int nname)
{
return devwalk(c, nc, name,nname, kbddir, nelem(kbddir), devgen);
}
static int
kbdstat(Chan *c, uchar *dp, int n)
{
return devstat(c, dp, n, kbddir, nelem(kbddir), devgen);
}
static Chan*
kbdopen(Chan *c, int omode)
{
c = devopen(c, omode, kbddir, nelem(kbddir), devgen);
switch((ulong)c->qid.path){
case Qkbd:
if(tas(&kbdinuse) != 0){
c->flag &= ~COPEN;
error(Einuse);
}
break;
}
return c;
}
static void
kbdclose(Chan *c)
{
switch((ulong)c->qid.path){
case Qkbd:
if(c->flag&COPEN)
kbdinuse = 0;
break;
}
}
static long
kbdread(Chan *c, void *buf, long n, vlong off)
{
USED(off);
if(n <= 0)
return n;
switch((ulong)c->qid.path){
case Qdir:
return devdirread(c, buf, n, kbddir, nelem(kbddir), devgen);
case Qkbd:
return qread(keyq, buf, n);
default:
print("kbdread 0x%llux\n", c->qid.path);
error(Egreg);
}
return -1; /* never reached */
}
static long
kbdwrite(Chan *c, void *va, long n, vlong off)
{
USED(c);
USED(va);
USED(n);
USED(off);
error(Eperm);
return -1; /* never reached */
}
Dev kbddevtab = {
'b',
"kbd",
devreset,
kbdinit,
devshutdown,
kbdattach,
kbdwalk,
kbdstat,
kbdopen,
devcreate,
kbdclose,
kbdread,
devbread,
kbdwrite,
devbwrite,
devremove,
devwstat,
};
|