1 /*
2 * keyboard scan code input from outside the kernel.
3 * to avoid duplication of keyboard map processing for usb.
4 */
5
6 #include "u.h"
7 #include "../port/lib.h"
8 #include "mem.h"
9 #include "dat.h"
10 #include "fns.h"
11 #include "../port/error.h"
12
13 extern void kbdputsc(int, int);
14
15 enum {
16 Qdir,
17 Qkbd,
18 };
19
20 Dirtab kbintab[] = {
21 ".", {Qdir, 0, QTDIR}, 0, 0555,
22 "kbin", {Qkbd, 0}, 0, 0200,
23 };
24
25 Lock kbinlck;
26 int kbinbusy;
27
28 static Chan *
kbinattach(char * spec)29 kbinattach(char *spec)
30 {
31 return devattach(L'Ι', spec);
32 }
33
34 static Walkqid*
kbinwalk(Chan * c,Chan * nc,char ** name,int nname)35 kbinwalk(Chan *c, Chan *nc, char **name, int nname)
36 {
37 return devwalk(c, nc, name, nname, kbintab, nelem(kbintab), devgen);
38 }
39
40 static int
kbinstat(Chan * c,uchar * dp,int n)41 kbinstat(Chan *c, uchar *dp, int n)
42 {
43 return devstat(c, dp, n, kbintab, nelem(kbintab), devgen);
44 }
45
46 static Chan*
kbinopen(Chan * c,int omode)47 kbinopen(Chan *c, int omode)
48 {
49 if(!iseve())
50 error(Eperm);
51 if(c->qid.path == Qkbd){
52 lock(&kbinlck);
53 if(kbinbusy){
54 unlock(&kbinlck);
55 error(Einuse);
56 }
57 kbinbusy++;
58 unlock(&kbinlck);
59 }
60 return devopen(c, omode, kbintab, nelem(kbintab), devgen);
61 }
62
63 static void
kbinclose(Chan * c)64 kbinclose(Chan *c)
65 {
66 if(c->aux){
67 free(c->aux);
68 c->aux = nil;
69 }
70 if(c->qid.path == Qkbd)
71 kbinbusy = 0;
72 }
73
74 static long
kbinread(Chan * c,void * a,long n,vlong)75 kbinread(Chan *c, void *a, long n, vlong )
76 {
77 if(c->qid.type == QTDIR)
78 return devdirread(c, a, n, kbintab, nelem(kbintab), devgen);
79 return 0;
80 }
81
82 static long
kbinwrite(Chan * c,void * a,long n,vlong)83 kbinwrite(Chan *c, void *a, long n, vlong)
84 {
85 int i;
86 uchar *p = a;
87
88 if(c->qid.type == QTDIR)
89 error(Eisdir);
90 switch((int)c->qid.path){
91 case Qkbd:
92 for(i = 0; i < n; i++)
93 kbdputsc(*p++, 1); /* external source */
94 break;
95 default:
96 error(Egreg);
97 }
98 return n;
99 }
100
101 Dev kbindevtab = {
102 L'Ι',
103 "kbin",
104
105 devreset,
106 devinit,
107 devshutdown,
108 kbinattach,
109 kbinwalk,
110 kbinstat,
111 kbinopen,
112 devcreate,
113 kbinclose,
114 kbinread,
115 devbread,
116 kbinwrite,
117 devbwrite,
118 devremove,
119 devwstat,
120 };
121