]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vnc/devcons.c
vncs: /dev/kbd support by running kbdfs and forwarding keycodes thru kbdin
[plan9front.git] / sys / src / cmd / vnc / devcons.c
1 #include        <u.h>
2 #include        <libc.h>
3 #include        "compat.h"
4 #include        "kbd.h"
5 #include        "error.h"
6
7 Snarf   snarf = {
8         .vers = 1
9 };
10
11 enum{
12         Qdir,
13         Qcons,
14         Qconsctl,
15         Qsnarf,
16         Qwinname,
17 };
18
19 static Dirtab consdir[]={
20         ".",            {Qdir, 0, QTDIR},       0,              DMDIR|0555,
21         "cons",         {Qcons},        0,              0660,
22         "consctl",      {Qconsctl},     0,              0220,
23         "snarf",        {Qsnarf},       0,              0600,
24         "winname",      {Qwinname},     0,              0000,
25 };
26
27 static Chan*
28 consattach(char *spec)
29 {
30         return devattach('c', spec);
31 }
32
33 static Walkqid*
34 conswalk(Chan *c, Chan *nc, char **name, int nname)
35 {
36         return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
37 }
38
39 static int
40 consstat(Chan *c, uchar *dp, int n)
41 {
42         return devstat(c, dp, n, consdir, nelem(consdir), devgen);
43 }
44
45 static Chan*
46 consopen(Chan *c, int omode)
47 {
48         c->aux = nil;
49         c = devopen(c, omode, consdir, nelem(consdir), devgen);
50         switch((ulong)c->qid.path){
51         case Qconsctl:
52                 break;
53         case Qsnarf:
54                 if((c->mode&3) == OWRITE || (c->mode&3) == ORDWR)
55                         c->aux = smalloc(sizeof(Snarf));
56                 break;
57         }
58         return c;
59 }
60
61 void
62 setsnarf(char *buf, int n, int *vers)
63 {
64         int i;
65
66         qlock(&snarf);
67         snarf.vers++;
68         if(vers)
69                 *vers = snarf.vers;     
70         for(i = 0; i < nelem(consdir); i++){
71                 if(consdir[i].qid.type == Qsnarf){
72                         consdir[i].qid.vers = snarf.vers;
73                         break;
74                 }
75         }
76         free(snarf.buf);
77         snarf.n = n;
78         snarf.buf = buf;
79         qunlock(&snarf);
80 }
81
82 static void
83 consclose(Chan *c)
84 {
85         Snarf *t;
86
87         switch((ulong)c->qid.path){
88         /* last close of control file turns off raw */
89         case Qconsctl:
90                 break;
91         /* odd behavior but really ok: replace snarf buffer when /dev/snarf is closed */
92         case Qsnarf:
93                 t = c->aux;
94                 if(t == nil)
95                         break;
96                 setsnarf(t->buf, t->n, 0);
97                 t->buf = nil;   /* setsnarf took it */
98                 free(t);
99                 c->aux = nil;
100                 break;
101         }
102 }
103
104 static long
105 consread(Chan *c, void *buf, long n, vlong off)
106 {
107         if(n <= 0)
108                 return n;
109         switch((ulong)c->qid.path){
110         case Qsnarf:
111                 qlock(&snarf);
112                 if(off < snarf.n){
113                         if(off + n > snarf.n)
114                                 n = snarf.n - off;
115                         memmove(buf, snarf.buf+off, n);
116                 }else
117                         n = 0;
118                 qunlock(&snarf);
119                 return n;
120
121         case Qdir:
122                 return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
123
124         case Qcons:
125                 error(Egreg);
126                 return -1;
127
128         default:
129                 print("consread 0x%llux\n", c->qid.path);
130                 error(Egreg);
131         }
132         return -1;              /* never reached */
133 }
134
135 static long
136 conswrite(Chan *c, void *va, long n, vlong)
137 {
138         Snarf *t;
139         char *a;
140
141         switch((ulong)c->qid.path){
142         case Qcons:
143                 screenputs(va, n);
144                 break;
145
146         case Qconsctl:
147                 error(Egreg);
148                 break;
149
150         case Qsnarf:
151                 t = c->aux;
152                 /* always append only */
153                 if(t->n > MAXSNARF)     /* avoid thrashing when people cut huge text */
154                         error("snarf buffer too big");
155                 a = realloc(t->buf, t->n + n + 1);
156                 if(a == nil)
157                         error("snarf buffer too big");
158                 t->buf = a;
159                 memmove(t->buf+t->n, va, n);
160                 t->n += n;
161                 t->buf[t->n] = '\0';
162                 break;
163         default:
164                 print("conswrite: 0x%llux\n", c->qid.path);
165                 error(Egreg);
166         }
167         return n;
168 }
169
170 Dev consdevtab = {
171         'c',
172         "cons",
173
174         devreset,
175         devinit,
176         consattach,
177         conswalk,
178         consstat,
179         consopen,
180         devcreate,
181         consclose,
182         consread,
183         devbread,
184         conswrite,
185         devbwrite,
186         devremove,
187         devwstat,
188 };