xref: /inferno-os/emu/port/devtk.c (revision 7de2b42d50e3c05cc143e7b51284009b5e185581)
1 #include	"dat.h"
2 #include	"fns.h"
3 #include	"error.h"
4 
5 #include <interp.h>
6 
7 #include	"draw.h"
8 #include	<memdraw.h>
9 #include	<memlayer.h>
10 #include	<cursor.h>
11 
12 enum{
13 	Qdir,
14 	Qtkevents
15 };
16 
17 static
18 Dirtab tkdirtab[]=
19 {
20 	".",	{Qdir, 0, QTDIR},	0,		DMDIR|0555,
21 	"tkevents",		{Qtkevents, 0},		0,	0600,
22 };
23 
24 static struct {
25 	QLock	l;
26 	Queue*	eq;
27 	Ref	inuse;
28 } tkevents;
29 
30 static void
31 tkwiretapper(void *top, char *cmd, char *result, void *image, Rectangle *rp)
32 {
33 	Block *b;
34 	int n;
35 	char *s, *e;
36 
37 //fprint(2, "wiretap %p %q %q\n", top, cmd, result);
38 	if(tkevents.eq == nil)
39 		return;
40 	n = 12;
41 	if(cmd != nil)
42 		n += strlen(cmd)+2+1;
43 	if(result != nil)
44 		n += strlen(result)+2+1;
45 	if(image != nil)
46 		n += 12;
47 	if(rp != nil)
48 		n += 4*20;
49 	n++;
50 	b = allocb(n);
51 	if(b != nil){
52 		s = (char*)b->wp;
53 		e = s+n;
54 		s += snprint(s, e-s, "%p", top);
55 		if(cmd != nil){
56 			*s++ = ' ';
57 			*s++ = '[';
58 			n = strlen(cmd);
59 			memmove(s, cmd, n);
60 			s += n;
61 			*s++ = ']';
62 		}
63 		/* ignore result for now */
64 		if(image != nil)
65 			s += snprint(s, e-s, " %p", image);
66 		if(rp != nil)
67 			s += snprint(s, e-s, " %d %d %d %d", rp->min.x, rp->min.y, rp->max.x, rp->max.y);
68 		b->wp = (uchar*)s;
69 		release();
70 		qlock(&tkevents.l);
71 		if(waserror()){
72 			freeb(b);
73 			qunlock(&tkevents.l);
74 			acquire();
75 			return;
76 		}
77 		if(tkevents.eq != nil)
78 			qbwrite(tkevents.eq, b);
79 		else
80 			freeb(b);
81 		poperror();
82 		qunlock(&tkevents.l);
83 		acquire();
84 	}
85 }
86 
87 void	(*tkwiretap)(void*, char*, char*, void*, Rectangle*) = tkwiretapper;
88 
89 static Chan*
90 tkattach(char* spec)
91 {
92 	return devattach(L'τ', spec);
93 }
94 
95 static Walkqid*
96 tkwalk(Chan *c, Chan *nc, char **name, int nname)
97 {
98 	return devwalk(c, nc, name, nname, tkdirtab, nelem(tkdirtab), devgen);
99 }
100 
101 static int
102 tkstat(Chan *c, uchar *db, int n)
103 {
104 	return devstat(c, db, n, tkdirtab, nelem(tkdirtab), devgen);
105 }
106 
107 static Chan*
108 tkopen(Chan* c, int omode)
109 {
110 	if(c->qid.type & QTDIR)
111 		return devopen(c, omode, tkdirtab, nelem(tkdirtab), devgen);
112 	switch(c->qid.path){
113 	case Qtkevents:
114 		c = devopen(c, omode, tkdirtab, nelem(tkdirtab), devgen);
115 		qlock(&tkevents.l);
116 		if(incref(&tkevents.inuse) != 1){
117 			qunlock(&tkevents.l);
118 			error(Einuse);
119 		}
120 		if(tkevents.eq == nil)
121 			tkevents.eq = qopen(256*1024, 0, nil, nil);
122 		else
123 			qreopen(tkevents.eq);
124 		qunlock(&tkevents.l);
125 		break;
126 	}
127 	return c;
128 }
129 
130 static void
131 tkclose(Chan* c)
132 {
133 	if(c->qid.type & QTDIR || (c->flag & COPEN) == 0)
134 		return;
135 	qlock(&tkevents.l);
136 	if(decref(&tkevents.inuse) == 0)
137 		qclose(tkevents.eq);
138 	qunlock(&tkevents.l);
139 }
140 
141 static long
142 tkread(Chan* c, void* a, long n, vlong offset)
143 {
144 	USED(offset);
145 	if(c->qid.type & QTDIR)
146 		return devdirread(c, a, n, tkdirtab, nelem(tkdirtab), devgen);
147 
148 	switch((ulong)c->qid.path){
149 	case Qtkevents:
150 		return qread(tkevents.eq, a, n);
151 	default:
152 		n=0;
153 		break;
154 	}
155 	return n;
156 }
157 
158 static long
159 tkwrite(Chan *c, void* a, long n, vlong offset)
160 {
161 	USED(c); USED(a); USED(n); USED(offset);
162 	error(Ebadusefd);
163 	return 0;
164 }
165 
166 Dev tkdevtab = {
167 	L'τ',
168 	"tk",
169 
170 //	devreset,
171 	devinit,
172 	tkattach,
173 //	devdetach,
174 	tkwalk,
175 	tkstat,
176 	tkopen,
177 	devcreate,
178 	tkclose,
179 	tkread,
180 	devbread,
181 	tkwrite,
182 	devbwrite,
183 	devremove,
184 	devwstat,
185 };
186