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