]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/wacom.c
merge
[plan9front.git] / sys / src / cmd / aux / wacom.c
1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
4 #include <thread.h>
5 #include <9p.h>
6
7 typedef struct Tablet Tablet;
8 typedef struct Message Message;
9 typedef struct QItem QItem;
10 typedef struct Queue Queue;
11 typedef struct Reader Reader;
12
13
14 enum { MAX = 1000 };
15
16 struct Tablet {
17         int ser;
18         int xmax, ymax, pmax, version;
19         int sx, sy;
20 };
21
22 struct Message {
23         Ref;
24         int b, x, y, p;
25         char *msg;
26 };
27
28 Tablet*
29 newtablet(char* dev)
30 {
31         int serctl;
32         char* ctl;
33         Tablet* t;
34
35         ctl = smprint("%sctl", dev);
36         t = calloc(sizeof(Tablet), 1);
37         t->ser = open(dev, ORDWR);
38         if(t->ser < 0) {
39                 free(t);
40                 return 0;
41         }
42         serctl = open(ctl, OWRITE);
43         free(ctl);
44         if(serctl < 0) {
45                 free(t);
46                 close(t->ser);
47                 return 0;
48         }
49         if(fprint(serctl, "b19200\n") < 0) {
50                 free(t);
51                 close(t->ser);
52                 close(serctl);
53                 return 0;
54         }
55         close(serctl);
56         return t;
57 }
58
59 int
60 query(Tablet* t)
61 {
62         uchar buf[11];
63
64         if(write(t->ser, "&0*", 3) < 3) return -1;
65         do {
66                 if(read(t->ser, buf, 1) < 1) return -1;
67         } while(buf[0] != 0xC0);
68         if(readn(t->ser, buf+1, 10) < 10) return -1;
69         t->xmax = (buf[1] << 9) | (buf[2] << 2) | ((buf[6] >> 5) & 3);
70         t->ymax = (buf[3] << 9) | (buf[4] << 2) | ((buf[6] >> 3) & 3);
71         t->pmax = buf[5] | (buf[6] & 7);
72         t->version = (buf[9] << 7) | buf[10];
73         if(write(t->ser, "1", 1) < 1) return -1;
74         return 0;
75 }
76
77 int
78 screensize(Tablet* t)
79 {
80         int fd;
81         char buf[189], buf2[12], *p;
82         
83         fd = open("/dev/draw/new", OREAD);
84         if(fd < 0) return -1;
85         read(fd, buf, 189);
86         memcpy(buf2, buf + 72, 11);
87         buf2[11] = 0;
88         for(p = buf2; *p == ' '; p++);
89         t->sx = atoi(p);
90         memcpy(buf2, buf + 84, 11);
91         for(p = buf2; *p == ' '; p++);
92         t->sy = atoi(p);
93         if(t->sx == 0 || t->sy == 0) {
94                 close(fd);
95                 werrstr("invalid resolution read from /dev/draw/new");
96                 return -1;
97         }
98         
99         close(fd);
100         return 0;
101 }
102
103 int
104 findheader(Tablet* t)
105 {
106         uchar c;
107         
108         do {
109                 if(read(t->ser, &c, 1) < 1) return -1;
110         } while((c & 0x80) == 0);
111         return c;
112 }
113
114 Message*
115 readpacket(Tablet* t)
116 {
117         uchar buf[9];
118         int head;
119         Message *m;
120
121         head = findheader(t);
122         if(head < 0) return 0;
123         if(readn(t->ser, buf, 9) < 9) return 0;
124         
125         m = calloc(sizeof(Message), 1);
126         incref(m);
127         
128         m->b = head & 7;
129         m->x = (buf[0] << 9) | (buf[1] << 2) | ((buf[5] >> 5) & 3);
130         m->y = (buf[2] << 9) | (buf[3] << 2) | ((buf[5] >> 3) & 3);
131         m->p = ((buf[5] & 7) << 7) | buf[4];
132         
133         m->p *= MAX;
134         m->p /= t->pmax;
135         m->x *= t->sx;
136         m->x /= t->xmax;
137         m->y *= t->sy;
138         m->y /= t->ymax;
139         
140         m->msg = smprint("m %d %d %d %d\n", m->x, m->y, m->b, m->p);
141         return m;
142 }
143
144 void
145 msgdecref(Message *m)
146 {
147         if(decref(m) == 0) {
148                 free(m->msg);
149                 free(m);
150         }
151 }
152
153 struct QItem {
154         Message *m;
155         QItem *next;
156 };
157
158 struct Queue {
159         Lock;
160         QItem *first, *last;
161 };
162
163 void
164 qput(Queue* q, Message* m)
165 {
166         QItem *i;
167         
168         lock(q);
169         i = malloc(sizeof(QItem));
170         i->m = m;
171         i->next = 0;
172         if(q->last == nil) {
173                 q->last = q->first = i;
174         } else {
175                 q->last->next = i;
176                 q->last = i;
177         }
178         unlock(q);
179 }
180
181 Message*
182 qget(Queue* q)
183 {
184         QItem *i;
185         Message *m;
186         
187         if(q->first == nil) return nil;
188         lock(q);
189         i = q->first;
190         if(q->first == q->last) {
191                 q->first = q->last = nil;
192         } else {
193                 q->first = i->next;
194         }
195         m = i->m;
196         free(i);
197         unlock(q);
198         return m;
199 }
200
201 void
202 freequeue(Queue *q)
203 {
204         Message *m;
205         
206         while(m = qget(q))
207                 msgdecref(m);
208         free(q);
209 }
210
211 struct Reader {
212         Queue *e;
213         Reader *prev, *next;
214         Req* req;
215 };
216
217 Lock readers;
218 Reader *rfirst, *rlast;
219
220 void
221 reply(Req *req, Message *m)
222 {
223         req->ofcall.count = strlen(m->msg);
224         if(req->ofcall.count > req->ifcall.count)
225                 req->ofcall.count = req->ifcall.count;
226         memmove(req->ofcall.data, m->msg, req->ofcall.count);
227         respond(req, nil);
228 }
229
230 void
231 sendout(Message *m)
232 {
233         Reader *r;
234         
235         lock(&readers);
236         for(r = rfirst; r; r = r->next) {
237                 if(r->req) {
238                         reply(r->req, m);
239                         r->req = nil;
240                 } else {
241                         incref(m);
242                         qput(r->e, m);
243                 }
244         }
245         unlock(&readers);
246 }
247
248 void
249 tabletopen(Req *req)
250 {
251         Reader *r;
252         
253         lock(&readers);
254         r = calloc(sizeof(Reader), 1);
255         r->e = calloc(sizeof(Queue), 1);
256         if(rlast) rlast->next = r;
257         r->prev = rlast;
258         rlast = r;
259         if(rfirst == nil) rfirst = r;
260         unlock(&readers);
261         req->fid->aux = r;
262         respond(req, nil);
263 }
264
265 void
266 tabletdestroyfid(Fid *fid)
267 {
268         Reader *r;
269
270         r = fid->aux;
271         if(r == nil) return;
272         lock(&readers);
273         if(r->prev) r->prev->next = r->next;
274         if(r->next) r->next->prev = r->prev;
275         if(r == rfirst) rfirst = r->next;
276         if(r == rlast) rlast = r->prev;
277         freequeue(r->e);
278         free(r);
279         unlock(&readers);
280 }
281
282 void
283 tabletdestroyreq(Req *req)
284 {
285         Reader *r;
286         
287         if(req->fid == nil) return;
288         r = req->fid->aux;
289         if(r == nil) return;
290         if(req == r->req) {
291                 r->req = nil;
292         }
293 }
294
295 void
296 tabletread(Req* req)
297 {
298         Reader *r;
299         Message *m;
300         
301         r = req->fid->aux;
302         if(m = qget(r->e)) {
303                 reply(req, m);
304                 msgdecref(m);
305         } else {
306                 if(r->req) {
307                         respond(req, "no concurrent reads, please");
308                 } else {
309                         r->req = req;
310                 }
311         }
312 }
313
314 Srv tabletsrv = {
315         .open = tabletopen,     
316         .read = tabletread,
317         .destroyfid = tabletdestroyfid,
318         .destroyreq = tabletdestroyreq,
319 };
320
321 File *tfile;
322
323 void
324 main()
325 {
326         Tablet *t;
327         Message *m;
328         int fd[2];
329         
330         pipe(fd);
331         tabletsrv.infd = tabletsrv.outfd = fd[0];
332         tabletsrv.srvfd = fd[1];
333         tabletsrv.tree = alloctree(getuser(), getuser(), 0555, 0);
334         tfile = createfile(tabletsrv.tree->root, "tablet", getuser(), 0400, 0);
335         if(rfork(RFPROC | RFMEM | RFNOWAIT | RFNOTEG) > 0) exits(nil);
336         if(rfork(RFPROC | RFMEM) == 0) {
337                 srv(&tabletsrv);
338                 exits(nil);
339         }
340         mount(fd[1], -1, "/dev", MAFTER, "");
341         
342         t = newtablet("/dev/eia2");
343         if(!t) sysfatal("%r");
344         if(screensize(t) < 0) sysfatal("%r");
345         if(query(t) < 0) sysfatal("%r");
346         while(1) {
347                 m = readpacket(t);
348                 if(!m) sysfatal("%r");
349                 sendout(m);
350                 msgdecref(m);
351         }
352 }