1 257fb626 2006-06-25 devnull /* Copyright (c) 2006 Russ Cox */
3 257fb626 2006-06-25 devnull #include <u.h>
4 150f8802 2006-06-25 devnull #include <sys/select.h>
5 257fb626 2006-06-25 devnull #include <libc.h>
6 257fb626 2006-06-25 devnull #include <draw.h>
7 257fb626 2006-06-25 devnull #include <mouse.h>
8 257fb626 2006-06-25 devnull #include <cursor.h>
9 257fb626 2006-06-25 devnull #include <drawfcall.h>
10 257fb626 2006-06-25 devnull #include <mux.h>
12 257fb626 2006-06-25 devnull int chattydrawclient;
14 257fb626 2006-06-25 devnull static int drawgettag(Mux *mux, void *vmsg);
15 257fb626 2006-06-25 devnull static void* drawrecv(Mux *mux);
16 3a194702 2006-11-04 devnull static int drawnbrecv(Mux *mux, void**);
17 257fb626 2006-06-25 devnull static int drawsend(Mux *mux, void *vmsg);
18 257fb626 2006-06-25 devnull static int drawsettag(Mux *mux, void *vmsg, uint tag);
19 150f8802 2006-06-25 devnull static int canreadfd(int);
22 257fb626 2006-06-25 devnull _displayconnect(Display *d)
24 257fb626 2006-06-25 devnull int pid, p[2];
26 257fb626 2006-06-25 devnull fmtinstall('W', drawfcallfmt);
27 257fb626 2006-06-25 devnull fmtinstall('H', encodefmt);
29 257fb626 2006-06-25 devnull if(pipe(p) < 0)
30 257fb626 2006-06-25 devnull return -1;
31 257fb626 2006-06-25 devnull if((pid=fork()) < 0){
32 257fb626 2006-06-25 devnull close(p[0]);
33 257fb626 2006-06-25 devnull close(p[1]);
34 257fb626 2006-06-25 devnull return -1;
36 257fb626 2006-06-25 devnull if(pid == 0){
37 257fb626 2006-06-25 devnull close(p[0]);
38 257fb626 2006-06-25 devnull dup(p[1], 0);
39 257fb626 2006-06-25 devnull dup(p[1], 1);
40 257fb626 2006-06-25 devnull /* execl("strace", "strace", "-o", "drawsrv.out", "drawsrv", nil); */
42 19f4cef5 2006-06-26 devnull * The argv0 has no meaning to devdraw.
43 19f4cef5 2006-06-26 devnull * Pass it along only so that the various
44 19f4cef5 2006-06-26 devnull * devdraws in psu -a can be distinguished.
46 19f4cef5 2006-06-26 devnull execl("devdraw", "devdraw", argv0, nil);
47 150f8802 2006-06-25 devnull sysfatal("exec devdraw: %r");
49 257fb626 2006-06-25 devnull close(p[1]);
50 257fb626 2006-06-25 devnull d->srvfd = p[0];
51 257fb626 2006-06-25 devnull return 0;
55 257fb626 2006-06-25 devnull _displaymux(Display *d)
57 257fb626 2006-06-25 devnull if((d->mux = mallocz(sizeof(*d->mux), 1)) == nil)
58 257fb626 2006-06-25 devnull return -1;
60 257fb626 2006-06-25 devnull d->mux->mintag = 1;
61 257fb626 2006-06-25 devnull d->mux->maxtag = 255;
62 257fb626 2006-06-25 devnull d->mux->send = drawsend;
63 257fb626 2006-06-25 devnull d->mux->recv = drawrecv;
64 150f8802 2006-06-25 devnull d->mux->nbrecv = drawnbrecv;
65 257fb626 2006-06-25 devnull d->mux->gettag = drawgettag;
66 257fb626 2006-06-25 devnull d->mux->settag = drawsettag;
67 257fb626 2006-06-25 devnull d->mux->aux = d;
68 257fb626 2006-06-25 devnull muxinit(d->mux);
70 257fb626 2006-06-25 devnull return 0;
73 257fb626 2006-06-25 devnull static int
74 257fb626 2006-06-25 devnull drawsend(Mux *mux, void *vmsg)
77 257fb626 2006-06-25 devnull uchar *msg;
78 257fb626 2006-06-25 devnull Display *d;
80 257fb626 2006-06-25 devnull msg = vmsg;
81 257fb626 2006-06-25 devnull GET(msg, n);
82 257fb626 2006-06-25 devnull d = mux->aux;
83 257fb626 2006-06-25 devnull return write(d->srvfd, msg, n);
86 3a194702 2006-11-04 devnull static int
87 3a194702 2006-11-04 devnull _drawrecv(Mux *mux, int canblock, void **vp)
90 257fb626 2006-06-25 devnull uchar buf[4], *p;
91 257fb626 2006-06-25 devnull Display *d;
93 257fb626 2006-06-25 devnull d = mux->aux;
94 3a194702 2006-11-04 devnull *vp = nil;
95 3a194702 2006-11-04 devnull if(!canblock && !canreadfd(d->srvfd))
96 3a194702 2006-11-04 devnull return 0;
97 150f8802 2006-06-25 devnull if((n=readn(d->srvfd, buf, 4)) != 4)
98 3a194702 2006-11-04 devnull return 1;
99 257fb626 2006-06-25 devnull GET(buf, n);
100 257fb626 2006-06-25 devnull p = malloc(n);
101 257fb626 2006-06-25 devnull if(p == nil){
102 257fb626 2006-06-25 devnull fprint(2, "out of memory allocating %d in drawrecv\n", n);
103 3a194702 2006-11-04 devnull return 1;
105 257fb626 2006-06-25 devnull memmove(p, buf, 4);
106 3a194702 2006-11-04 devnull if(readn(d->srvfd, p+4, n-4) != n-4){
107 3a194702 2006-11-04 devnull free(p);
108 3a194702 2006-11-04 devnull return 1;
110 3a194702 2006-11-04 devnull *vp = p;
111 3a194702 2006-11-04 devnull return 1;
114 150f8802 2006-06-25 devnull static void*
115 150f8802 2006-06-25 devnull drawrecv(Mux *mux)
117 3a194702 2006-11-04 devnull void *p;
118 3a194702 2006-11-04 devnull _drawrecv(mux, 1, &p);
119 3a194702 2006-11-04 devnull return p;
122 3a194702 2006-11-04 devnull static int
123 3a194702 2006-11-04 devnull drawnbrecv(Mux *mux, void **vp)
125 3a194702 2006-11-04 devnull return _drawrecv(mux, 0, vp);
128 257fb626 2006-06-25 devnull static int
129 257fb626 2006-06-25 devnull drawgettag(Mux *mux, void *vmsg)
131 257fb626 2006-06-25 devnull uchar *msg;
132 40227f1f 2006-07-04 devnull USED(mux);
134 257fb626 2006-06-25 devnull msg = vmsg;
135 257fb626 2006-06-25 devnull return msg[4];
138 257fb626 2006-06-25 devnull static int
139 257fb626 2006-06-25 devnull drawsettag(Mux *mux, void *vmsg, uint tag)
141 257fb626 2006-06-25 devnull uchar *msg;
142 40227f1f 2006-07-04 devnull USED(mux);
144 257fb626 2006-06-25 devnull msg = vmsg;
145 257fb626 2006-06-25 devnull msg[4] = tag;
146 257fb626 2006-06-25 devnull return 0;
149 257fb626 2006-06-25 devnull static int
150 257fb626 2006-06-25 devnull displayrpc(Display *d, Wsysmsg *tx, Wsysmsg *rx, void **freep)
152 257fb626 2006-06-25 devnull int n, nn;
153 257fb626 2006-06-25 devnull void *tpkt, *rpkt;
155 257fb626 2006-06-25 devnull n = sizeW2M(tx);
156 257fb626 2006-06-25 devnull tpkt = malloc(n);
157 257fb626 2006-06-25 devnull if(freep)
158 257fb626 2006-06-25 devnull *freep = nil;
159 257fb626 2006-06-25 devnull if(tpkt == nil)
160 257fb626 2006-06-25 devnull return -1;
161 257fb626 2006-06-25 devnull tx->tag = 0;
162 257fb626 2006-06-25 devnull if(chattydrawclient)
163 257fb626 2006-06-25 devnull fprint(2, "<- %W\n", tx);
164 257fb626 2006-06-25 devnull nn = convW2M(tx, tpkt, n);
165 257fb626 2006-06-25 devnull if(nn != n){
166 257fb626 2006-06-25 devnull free(tpkt);
167 257fb626 2006-06-25 devnull werrstr("drawclient: sizeW2M convW2M mismatch");
168 257fb626 2006-06-25 devnull fprint(2, "%r\n");
169 257fb626 2006-06-25 devnull return -1;
172 19f4cef5 2006-06-26 devnull * This is the only point where we might reschedule.
173 19f4cef5 2006-06-26 devnull * Muxrpc might need to acquire d->mux->lk, which could
174 19f4cef5 2006-06-26 devnull * be held by some other proc (e.g., the one reading from
175 19f4cef5 2006-06-26 devnull * the keyboard via Trdkbd messages). If we need to wait
176 19f4cef5 2006-06-26 devnull * for the lock, don't let other threads from this proc
177 19f4cef5 2006-06-26 devnull * run. This keeps up the appearance that writes to /dev/draw
178 19f4cef5 2006-06-26 devnull * don't cause rescheduling. If you *do* allow rescheduling
179 19f4cef5 2006-06-26 devnull * here, then flushimage(display, 1) happening in two different
180 19f4cef5 2006-06-26 devnull * threads in the same proc can cause a buffer of commands
181 19f4cef5 2006-06-26 devnull * to be written out twice, leading to interesting results
182 19f4cef5 2006-06-26 devnull * on the screen.
184 19f4cef5 2006-06-26 devnull * Threadpin and threadunpin were added to the thread library
185 19f4cef5 2006-06-26 devnull * to solve exactly this problem. Be careful! They are dangerous.
187 19f4cef5 2006-06-26 devnull * _pin and _unpin are aliases for threadpin and threadunpin
188 19f4cef5 2006-06-26 devnull * in a threaded program and are no-ops in unthreaded programs.
191 257fb626 2006-06-25 devnull rpkt = muxrpc(d->mux, tpkt);
192 19f4cef5 2006-06-26 devnull _unpin();
193 257fb626 2006-06-25 devnull free(tpkt);
194 257fb626 2006-06-25 devnull if(rpkt == nil){
195 257fb626 2006-06-25 devnull werrstr("muxrpc: %r");
196 257fb626 2006-06-25 devnull return -1;
198 257fb626 2006-06-25 devnull GET((uchar*)rpkt, n);
199 257fb626 2006-06-25 devnull nn = convM2W(rpkt, n, rx);
200 257fb626 2006-06-25 devnull if(nn != n){
201 257fb626 2006-06-25 devnull free(rpkt);
202 257fb626 2006-06-25 devnull werrstr("drawclient: convM2W packet size mismatch %d %d %.*H", n, nn, n, rpkt);
203 257fb626 2006-06-25 devnull fprint(2, "%r\n");
204 257fb626 2006-06-25 devnull return -1;
206 257fb626 2006-06-25 devnull if(chattydrawclient)
207 257fb626 2006-06-25 devnull fprint(2, "-> %W\n", rx);
208 257fb626 2006-06-25 devnull if(rx->type == Rerror){
209 257fb626 2006-06-25 devnull werrstr("%s", rx->error);
210 257fb626 2006-06-25 devnull free(rpkt);
211 257fb626 2006-06-25 devnull return -1;
213 257fb626 2006-06-25 devnull if(rx->type != tx->type+1){
214 257fb626 2006-06-25 devnull werrstr("packet type mismatch -- tx %d rx %d",
215 257fb626 2006-06-25 devnull tx->type, rx->type);
216 257fb626 2006-06-25 devnull free(rpkt);
217 257fb626 2006-06-25 devnull return -1;
219 257fb626 2006-06-25 devnull if(freep)
220 257fb626 2006-06-25 devnull *freep = rpkt;
222 257fb626 2006-06-25 devnull free(rpkt);
223 257fb626 2006-06-25 devnull return 0;
227 257fb626 2006-06-25 devnull _displayinit(Display *d, char *label, char *winsize)
229 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
231 257fb626 2006-06-25 devnull tx.type = Tinit;
232 150f8802 2006-06-25 devnull tx.label = label;
233 150f8802 2006-06-25 devnull tx.winsize = winsize;
234 257fb626 2006-06-25 devnull return displayrpc(d, &tx, &rx, nil);
238 257fb626 2006-06-25 devnull _displayrdmouse(Display *d, Mouse *m, int *resized)
240 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
242 257fb626 2006-06-25 devnull tx.type = Trdmouse;
243 257fb626 2006-06-25 devnull if(displayrpc(d, &tx, &rx, nil) < 0)
244 257fb626 2006-06-25 devnull return -1;
245 257fb626 2006-06-25 devnull *m = rx.mouse;
246 257fb626 2006-06-25 devnull *resized = rx.resized;
247 257fb626 2006-06-25 devnull return 0;
251 257fb626 2006-06-25 devnull _displayrdkbd(Display *d, Rune *r)
253 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
255 257fb626 2006-06-25 devnull tx.type = Trdkbd;
256 257fb626 2006-06-25 devnull if(displayrpc(d, &tx, &rx, nil) < 0)
257 257fb626 2006-06-25 devnull return -1;
258 257fb626 2006-06-25 devnull *r = rx.rune;
259 257fb626 2006-06-25 devnull return 0;
263 257fb626 2006-06-25 devnull _displaymoveto(Display *d, Point p)
265 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
267 257fb626 2006-06-25 devnull tx.type = Tmoveto;
268 257fb626 2006-06-25 devnull tx.mouse.xy = p;
269 257fb626 2006-06-25 devnull return displayrpc(d, &tx, &rx, nil);
273 257fb626 2006-06-25 devnull _displaycursor(Display *d, Cursor *c)
275 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
277 257fb626 2006-06-25 devnull tx.type = Tcursor;
278 257fb626 2006-06-25 devnull if(c == nil){
279 257fb626 2006-06-25 devnull memset(&tx.cursor, 0, sizeof tx.cursor);
280 257fb626 2006-06-25 devnull tx.arrowcursor = 1;
282 257fb626 2006-06-25 devnull tx.arrowcursor = 0;
283 257fb626 2006-06-25 devnull tx.cursor = *c;
285 257fb626 2006-06-25 devnull return displayrpc(d, &tx, &rx, nil);
289 257fb626 2006-06-25 devnull _displaybouncemouse(Display *d, Mouse *m)
291 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
293 257fb626 2006-06-25 devnull tx.type = Tbouncemouse;
294 257fb626 2006-06-25 devnull tx.mouse = *m;
295 257fb626 2006-06-25 devnull return displayrpc(d, &tx, &rx, nil);
299 257fb626 2006-06-25 devnull _displaylabel(Display *d, char *label)
301 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
303 257fb626 2006-06-25 devnull tx.type = Tlabel;
304 257fb626 2006-06-25 devnull tx.label = label;
305 257fb626 2006-06-25 devnull return displayrpc(d, &tx, &rx, nil);
309 257fb626 2006-06-25 devnull _displayrdsnarf(Display *d)
311 257fb626 2006-06-25 devnull void *p;
312 257fb626 2006-06-25 devnull char *s;
313 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
315 257fb626 2006-06-25 devnull tx.type = Trdsnarf;
316 257fb626 2006-06-25 devnull if(displayrpc(d, &tx, &rx, &p) < 0)
317 257fb626 2006-06-25 devnull return nil;
318 257fb626 2006-06-25 devnull s = strdup(rx.snarf);
319 257fb626 2006-06-25 devnull free(p);
320 257fb626 2006-06-25 devnull return s;
324 257fb626 2006-06-25 devnull _displaywrsnarf(Display *d, char *snarf)
326 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
328 257fb626 2006-06-25 devnull tx.type = Twrsnarf;
329 257fb626 2006-06-25 devnull tx.snarf = snarf;
330 257fb626 2006-06-25 devnull return displayrpc(d, &tx, &rx, nil);
334 257fb626 2006-06-25 devnull _displayrddraw(Display *d, void *v, int n)
336 257fb626 2006-06-25 devnull void *p;
337 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
339 257fb626 2006-06-25 devnull tx.type = Trddraw;
340 257fb626 2006-06-25 devnull tx.count = n;
341 257fb626 2006-06-25 devnull if(displayrpc(d, &tx, &rx, &p) < 0)
342 257fb626 2006-06-25 devnull return -1;
343 257fb626 2006-06-25 devnull memmove(v, rx.data, rx.count);
344 257fb626 2006-06-25 devnull free(p);
345 257fb626 2006-06-25 devnull return rx.count;
349 257fb626 2006-06-25 devnull _displaywrdraw(Display *d, void *v, int n)
351 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
353 257fb626 2006-06-25 devnull tx.type = Twrdraw;
354 257fb626 2006-06-25 devnull tx.count = n;
355 257fb626 2006-06-25 devnull tx.data = v;
356 257fb626 2006-06-25 devnull if(displayrpc(d, &tx, &rx, nil) < 0)
357 257fb626 2006-06-25 devnull return -1;
358 257fb626 2006-06-25 devnull return rx.count;
362 257fb626 2006-06-25 devnull _displaytop(Display *d)
364 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
366 257fb626 2006-06-25 devnull tx.type = Ttop;
367 257fb626 2006-06-25 devnull return displayrpc(d, &tx, &rx, nil);
371 257fb626 2006-06-25 devnull _displayresize(Display *d, Rectangle r)
373 257fb626 2006-06-25 devnull Wsysmsg tx, rx;
375 257fb626 2006-06-25 devnull tx.type = Tresize;
376 257fb626 2006-06-25 devnull tx.rect = r;
377 257fb626 2006-06-25 devnull return displayrpc(d, &tx, &rx, nil);
380 150f8802 2006-06-25 devnull static int
381 150f8802 2006-06-25 devnull canreadfd(int fd)
383 150f8802 2006-06-25 devnull fd_set rs, ws, xs;
384 150f8802 2006-06-25 devnull struct timeval tv;
386 150f8802 2006-06-25 devnull FD_ZERO(&rs);
387 150f8802 2006-06-25 devnull FD_ZERO(&ws);
388 150f8802 2006-06-25 devnull FD_ZERO(&xs);
389 150f8802 2006-06-25 devnull FD_SET(fd, &rs);
390 150f8802 2006-06-25 devnull FD_SET(fd, &xs);
391 150f8802 2006-06-25 devnull tv.tv_sec = 0;
392 150f8802 2006-06-25 devnull tv.tv_usec = 0;
393 150f8802 2006-06-25 devnull if(select(fd+1, &rs, &ws, &xs, &tv) < 0)
394 150f8802 2006-06-25 devnull return 0;
395 150f8802 2006-06-25 devnull if(FD_ISSET(fd, &rs) || FD_ISSET(fd, &xs))
396 150f8802 2006-06-25 devnull return 1;
397 150f8802 2006-06-25 devnull return 0;