|
@@ -0,0 +1,120 @@
|
|
|
+/*
|
|
|
+ * 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, uint8_t *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 int32_t
|
|
|
+kbinread(Chan *c, void *a, int32_t n, int64_t _)
|
|
|
+{
|
|
|
+ if(c->qid.type == QTDIR)
|
|
|
+ return devdirread(c, a, n, kbintab, nelem(kbintab), devgen);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int32_t
|
|
|
+kbinwrite(Chan *c, void *a, int32_t n, int64_t _)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ uint8_t *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,
|
|
|
+};
|