xref: /plan9/sys/src/9/port/devkbin.c (revision c8a340cd3a4d961f476a4f4f2d047cd5eedaced7)
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