xref: /inferno-os/lib/lego/styx.c (revision 46439007cf417cbd9ac8049bb4122c890097a0fa)
1*46439007SCharles.Forsyth /*
2*46439007SCharles.Forsyth  *  styx.c
3*46439007SCharles.Forsyth  *
4*46439007SCharles.Forsyth  *  A Styx fileserver for a Lego RCX
5*46439007SCharles.Forsyth  *
6*46439007SCharles.Forsyth  *  Nigel Roles
7*46439007SCharles.Forsyth  *  Vita Nuova
8*46439007SCharles.Forsyth  *
9*46439007SCharles.Forsyth  *  This is a heavily modified version of test5.c
10*46439007SCharles.Forsyth  *
11*46439007SCharles.Forsyth  *  I couldn't have done this without Kekoa...
12*46439007SCharles.Forsyth  *
13*46439007SCharles.Forsyth  *
14*46439007SCharles.Forsyth  *  The contents of this file are subject to the Mozilla Public License
15*46439007SCharles.Forsyth  *  Version 1.0 (the "License"); you may not use this file except in
16*46439007SCharles.Forsyth  *  compliance with the License. You may obtain a copy of the License at
17*46439007SCharles.Forsyth  *  http://www.mozilla.org/MPL/
18*46439007SCharles.Forsyth  *
19*46439007SCharles.Forsyth  *  Software distributed under the License is distributed on an "AS IS"
20*46439007SCharles.Forsyth  *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
21*46439007SCharles.Forsyth  *  License for the specific language governing rights and limitations
22*46439007SCharles.Forsyth  *  under the License.
23*46439007SCharles.Forsyth  *
24*46439007SCharles.Forsyth  *  The Original Code is Librcx sample program code, released February 9,
25*46439007SCharles.Forsyth  *  1999.
26*46439007SCharles.Forsyth  *
27*46439007SCharles.Forsyth  *  The Initial Developer of the Original Code is Kekoa Proudfoot.
28*46439007SCharles.Forsyth  *  Portions created by Kekoa Proudfoot are Copyright (C) 1999
29*46439007SCharles.Forsyth  *  Kekoa Proudfoot. All Rights Reserved.
30*46439007SCharles.Forsyth  *
31*46439007SCharles.Forsyth  *  Contributor(s): Kekoa Proudfoot <kekoa@graphics.stanford.edu>
32*46439007SCharles.Forsyth  */
33*46439007SCharles.Forsyth 
34*46439007SCharles.Forsyth //#include "stdlib.h"
35*46439007SCharles.Forsyth #include "rom.h"
36*46439007SCharles.Forsyth 
37*46439007SCharles.Forsyth #include "lib9.h"
38*46439007SCharles.Forsyth #include "styx.h"
39*46439007SCharles.Forsyth 
40*46439007SCharles.Forsyth #include "llp.h"
41*46439007SCharles.Forsyth 
42*46439007SCharles.Forsyth #define ASSERT(cond) if (!(cond)) fatal(__LINE__)
43*46439007SCharles.Forsyth #define FATAL fatal(__LINE__)
44*46439007SCharles.Forsyth #define PROGRESS progress(__LINE__)
45*46439007SCharles.Forsyth 
46*46439007SCharles.Forsyth #if 0
47*46439007SCharles.Forsyth #define ABP
48*46439007SCharles.Forsyth #endif
49*46439007SCharles.Forsyth 
50*46439007SCharles.Forsyth uchar *send_fid_reply_payload(void);
51*46439007SCharles.Forsyth void send_fid_reply(uchar type, ushort tag, ushort fid, uchar *msg, short len);
52*46439007SCharles.Forsyth void send_error_reply(unsigned short tag, char *msg);
53*46439007SCharles.Forsyth 
54*46439007SCharles.Forsyth static unsigned short msgcount;
55*46439007SCharles.Forsyth static unsigned char compressed_incoming[150];
56*46439007SCharles.Forsyth static unsigned char incoming[1024];
57*46439007SCharles.Forsyth static unsigned char compressed_reply[150];
58*46439007SCharles.Forsyth short compressed_reply_len;
59*46439007SCharles.Forsyth static unsigned char reply[1024];
60*46439007SCharles.Forsyth unsigned short reply_len;
61*46439007SCharles.Forsyth unsigned short transmitted_reply_len;
62*46439007SCharles.Forsyth unsigned char alternating_bit;
63*46439007SCharles.Forsyth static uchar dir[116];
64*46439007SCharles.Forsyth uchar prepared;
65*46439007SCharles.Forsyth uchar reader_count;
66*46439007SCharles.Forsyth uchar dispatch[6];
67*46439007SCharles.Forsyth 
68*46439007SCharles.Forsyth /* ROM pseudofunctions */
69*46439007SCharles.Forsyth 
70*46439007SCharles.Forsyth static inline void
set_data_pointer(void * ptr)71*46439007SCharles.Forsyth set_data_pointer (void *ptr)
72*46439007SCharles.Forsyth {
73*46439007SCharles.Forsyth     play_sound_or_set_data_pointer(0x1771, (short)ptr, 0);
74*46439007SCharles.Forsyth }
75*46439007SCharles.Forsyth 
76*46439007SCharles.Forsyth static inline char
check_valid(void)77*46439007SCharles.Forsyth check_valid (void)
78*46439007SCharles.Forsyth {
79*46439007SCharles.Forsyth 	char valid;
80*46439007SCharles.Forsyth 	check_for_data(&valid, NULL);
81*46439007SCharles.Forsyth 	return valid;
82*46439007SCharles.Forsyth }
83*46439007SCharles.Forsyth 
84*46439007SCharles.Forsyth static inline int
receive_message(void * ptr,int len)85*46439007SCharles.Forsyth receive_message (void *ptr, int len)
86*46439007SCharles.Forsyth {
87*46439007SCharles.Forsyth 	char bytes = 0;
88*46439007SCharles.Forsyth 	receive_data(ptr, len, &bytes);
89*46439007SCharles.Forsyth 	/* Bytes includes checksum, since we don't want that, return bytes-1 */
90*46439007SCharles.Forsyth 	return bytes - 1;
91*46439007SCharles.Forsyth }
92*46439007SCharles.Forsyth 
93*46439007SCharles.Forsyth static inline void
send_message(void * ptr,int len)94*46439007SCharles.Forsyth send_message (void *ptr, int len)
95*46439007SCharles.Forsyth {
96*46439007SCharles.Forsyth 	if (len)
97*46439007SCharles.Forsyth 		while (send_data(0x1776, 0, ptr, len));
98*46439007SCharles.Forsyth }
99*46439007SCharles.Forsyth 
100*46439007SCharles.Forsyth int
poll_power(void)101*46439007SCharles.Forsyth poll_power(void)
102*46439007SCharles.Forsyth {
103*46439007SCharles.Forsyth 	static short debounce = 0;
104*46439007SCharles.Forsyth 	static short state = -1;
105*46439007SCharles.Forsyth 	short status;
106*46439007SCharles.Forsyth 	get_power_status(0x4000, &status);
107*46439007SCharles.Forsyth 	if (state != status)
108*46439007SCharles.Forsyth 		debounce = 0;
109*46439007SCharles.Forsyth 	else if (debounce < 10)
110*46439007SCharles.Forsyth 		debounce++;
111*46439007SCharles.Forsyth 	state = status;
112*46439007SCharles.Forsyth 	return debounce >= 10 ? state : -1;
113*46439007SCharles.Forsyth }
114*46439007SCharles.Forsyth 
115*46439007SCharles.Forsyth static void
progress(short line)116*46439007SCharles.Forsyth progress(short line)
117*46439007SCharles.Forsyth {
118*46439007SCharles.Forsyth 	set_lcd_number(LCD_UNSIGNED, line, LCD_DECIMAL_0);
119*46439007SCharles.Forsyth 	refresh_display();
120*46439007SCharles.Forsyth }
121*46439007SCharles.Forsyth 
122*46439007SCharles.Forsyth static void
fatal(short line)123*46439007SCharles.Forsyth fatal(short line)
124*46439007SCharles.Forsyth {
125*46439007SCharles.Forsyth 	set_lcd_segment(LCD_STANDING);
126*46439007SCharles.Forsyth 	progress(line);
127*46439007SCharles.Forsyth 	while (poll_power() != 0)
128*46439007SCharles.Forsyth 		;
129*46439007SCharles.Forsyth }
130*46439007SCharles.Forsyth 
131*46439007SCharles.Forsyth typedef struct Reader {
132*46439007SCharles.Forsyth 	ushort tag;
133*46439007SCharles.Forsyth 	ushort fid;
134*46439007SCharles.Forsyth 	ushort offset;
135*46439007SCharles.Forsyth 	ushort count;
136*46439007SCharles.Forsyth 	struct Reader *next;
137*46439007SCharles.Forsyth } Reader;
138*46439007SCharles.Forsyth 
139*46439007SCharles.Forsyth typedef struct DirectoryEntry {
140*46439007SCharles.Forsyth 	char *name;
141*46439007SCharles.Forsyth 	uchar qid;
142*46439007SCharles.Forsyth 	const struct DirectoryEntry *sub;
143*46439007SCharles.Forsyth 	short (*read)(const struct DirectoryEntry *dp, ushort tag, ushort fid, ushort offset, ushort count);
144*46439007SCharles.Forsyth 	short (*write)(const struct DirectoryEntry *dp, ushort offset, ushort count, uchar *buf);
145*46439007SCharles.Forsyth } DirectoryEntry;
146*46439007SCharles.Forsyth 
147*46439007SCharles.Forsyth #define QID_ROOT 0
148*46439007SCharles.Forsyth #define QID_MOTOR 1
149*46439007SCharles.Forsyth #define QID_MOTOR_0 2
150*46439007SCharles.Forsyth #define QID_MOTOR_1 3
151*46439007SCharles.Forsyth #define QID_MOTOR_2 4
152*46439007SCharles.Forsyth #define QID_MOTOR_012 5
153*46439007SCharles.Forsyth #define QID_SENSOR 6
154*46439007SCharles.Forsyth #define QID_SENSOR_0 7
155*46439007SCharles.Forsyth #define QID_SENSOR_1 8
156*46439007SCharles.Forsyth #define QID_SENSOR_2 9
157*46439007SCharles.Forsyth 
158*46439007SCharles.Forsyth typedef struct Sensor {
159*46439007SCharles.Forsyth 	sensor_t sensor;
160*46439007SCharles.Forsyth 	uchar active;
161*46439007SCharles.Forsyth 	uchar greater;
162*46439007SCharles.Forsyth 	ushort thresh;
163*46439007SCharles.Forsyth 	Reader *reader;
164*46439007SCharles.Forsyth } Sensor;
165*46439007SCharles.Forsyth 
166*46439007SCharles.Forsyth Sensor sensor[3];
167*46439007SCharles.Forsyth 
168*46439007SCharles.Forsyth short
atoin(char * s,short lim)169*46439007SCharles.Forsyth atoin(char *s, short lim)
170*46439007SCharles.Forsyth {
171*46439007SCharles.Forsyth 	short total = 0;
172*46439007SCharles.Forsyth 	while (*s && lim) {
173*46439007SCharles.Forsyth 		char c = *s++;
174*46439007SCharles.Forsyth 		if (c >= '0' && c <= '9')
175*46439007SCharles.Forsyth 			total = total * 10 + c - '0';
176*46439007SCharles.Forsyth 		else
177*46439007SCharles.Forsyth 			break;
178*46439007SCharles.Forsyth 		lim--;
179*46439007SCharles.Forsyth 	}
180*46439007SCharles.Forsyth 	return total;
181*46439007SCharles.Forsyth }
182*46439007SCharles.Forsyth 
183*46439007SCharles.Forsyth short
itoa(char * buf,short value)184*46439007SCharles.Forsyth itoa(char *buf, short value)
185*46439007SCharles.Forsyth {
186*46439007SCharles.Forsyth 	char *bp = buf;
187*46439007SCharles.Forsyth 	short divisor;
188*46439007SCharles.Forsyth 	if (value < 0) {
189*46439007SCharles.Forsyth 		*bp++ = '-';
190*46439007SCharles.Forsyth 		value = -value;
191*46439007SCharles.Forsyth 	}
192*46439007SCharles.Forsyth 	if (value == 0)
193*46439007SCharles.Forsyth 		*bp++ = '0';
194*46439007SCharles.Forsyth 	else {
195*46439007SCharles.Forsyth 		divisor = 10000;
196*46439007SCharles.Forsyth 		while (divisor > value)
197*46439007SCharles.Forsyth 			divisor /= 10;
198*46439007SCharles.Forsyth 		while (divisor) {
199*46439007SCharles.Forsyth 			*bp++ = '0' + value / divisor;
200*46439007SCharles.Forsyth 			value %= divisor;
201*46439007SCharles.Forsyth 			divisor /= 10;
202*46439007SCharles.Forsyth 		}
203*46439007SCharles.Forsyth 	}
204*46439007SCharles.Forsyth 	return bp - buf;
205*46439007SCharles.Forsyth }
206*46439007SCharles.Forsyth 
207*46439007SCharles.Forsyth Reader *
readercreate(ushort tag,ushort fid,ushort offset,ushort count)208*46439007SCharles.Forsyth readercreate(ushort tag, ushort fid, ushort offset, ushort count)
209*46439007SCharles.Forsyth {
210*46439007SCharles.Forsyth 	Reader *rp = malloc(sizeof(Reader));
211*46439007SCharles.Forsyth 	rp->tag = tag;
212*46439007SCharles.Forsyth 	rp->fid = fid;
213*46439007SCharles.Forsyth 	rp->offset = offset;
214*46439007SCharles.Forsyth 	rp->count = count;
215*46439007SCharles.Forsyth 	rp->next = 0;
216*46439007SCharles.Forsyth 	reader_count++;
217*46439007SCharles.Forsyth 	return rp;
218*46439007SCharles.Forsyth }
219*46439007SCharles.Forsyth 
220*46439007SCharles.Forsyth void
readerfree(Reader * rp)221*46439007SCharles.Forsyth readerfree(Reader *rp)
222*46439007SCharles.Forsyth {
223*46439007SCharles.Forsyth 	free(rp);
224*46439007SCharles.Forsyth 	reader_count--;
225*46439007SCharles.Forsyth }
226*46439007SCharles.Forsyth 
227*46439007SCharles.Forsyth int
senderrorreset(Reader * rp,void * magic)228*46439007SCharles.Forsyth senderrorreset(Reader *rp, void *magic)
229*46439007SCharles.Forsyth {
230*46439007SCharles.Forsyth 	send_error_reply(rp->tag, "reset");
231*46439007SCharles.Forsyth 	return 1;
232*46439007SCharles.Forsyth }
233*46439007SCharles.Forsyth 
234*46439007SCharles.Forsyth void
readerlistfindanddestroy(Reader ** rpp,int (* action)(Reader * rp,void * magic),void * magic)235*46439007SCharles.Forsyth readerlistfindanddestroy(Reader **rpp, int (*action)(Reader *rp, void *magic), void *magic)
236*46439007SCharles.Forsyth {
237*46439007SCharles.Forsyth 	while (*rpp) {
238*46439007SCharles.Forsyth 		Reader *rp = *rpp;
239*46439007SCharles.Forsyth 		if ((*action)(rp, magic)) {
240*46439007SCharles.Forsyth 			*rpp = rp->next;
241*46439007SCharles.Forsyth 			readerfree(rp);
242*46439007SCharles.Forsyth 		}
243*46439007SCharles.Forsyth 		else
244*46439007SCharles.Forsyth 			rpp = &(rp->next);
245*46439007SCharles.Forsyth 	}
246*46439007SCharles.Forsyth }
247*46439007SCharles.Forsyth 
248*46439007SCharles.Forsyth void
allreaderlistfindanddestroy(int (* action)(Reader * rp,void * magic),void * magic)249*46439007SCharles.Forsyth allreaderlistfindanddestroy(int (*action)(Reader *rp, void *magic), void *magic)
250*46439007SCharles.Forsyth {
251*46439007SCharles.Forsyth 	short i;
252*46439007SCharles.Forsyth 	for (i = 0; i < 3; i++)
253*46439007SCharles.Forsyth 		readerlistfindanddestroy(&sensor[i].reader, action, magic);
254*46439007SCharles.Forsyth }
255*46439007SCharles.Forsyth 
256*46439007SCharles.Forsyth short
sensorwrite(const DirectoryEntry * dp,ushort offset,ushort count,uchar * data)257*46439007SCharles.Forsyth sensorwrite(const DirectoryEntry *dp, ushort offset, ushort count, uchar *data)
258*46439007SCharles.Forsyth {
259*46439007SCharles.Forsyth 	short i;
260*46439007SCharles.Forsyth 	Sensor *sp;
261*46439007SCharles.Forsyth 	uchar greater;
262*46439007SCharles.Forsyth 	short type, mode;
263*46439007SCharles.Forsyth 	ushort k;
264*46439007SCharles.Forsyth 
265*46439007SCharles.Forsyth 	if (offset != 0)
266*46439007SCharles.Forsyth 		return -1;
267*46439007SCharles.Forsyth 	i = dp->qid - QID_SENSOR_0;
268*46439007SCharles.Forsyth 	sp = &sensor[i];
269*46439007SCharles.Forsyth 	k = count;
270*46439007SCharles.Forsyth 	if (k == 0)
271*46439007SCharles.Forsyth 		return -1;
272*46439007SCharles.Forsyth 	switch (data[0]) {
273*46439007SCharles.Forsyth 	case 'b':
274*46439007SCharles.Forsyth 		type = SENSOR_TYPE_TOUCH;
275*46439007SCharles.Forsyth 		mode = SENSOR_MODE_PULSE;
276*46439007SCharles.Forsyth 		break;
277*46439007SCharles.Forsyth 	case 'l':
278*46439007SCharles.Forsyth 		type = SENSOR_TYPE_TOUCH;
279*46439007SCharles.Forsyth 		mode = SENSOR_MODE_RAW;
280*46439007SCharles.Forsyth 		break;
281*46439007SCharles.Forsyth 	default:
282*46439007SCharles.Forsyth 		return -1;
283*46439007SCharles.Forsyth 	}
284*46439007SCharles.Forsyth 	data++; k--;
285*46439007SCharles.Forsyth 	if (k == 0)
286*46439007SCharles.Forsyth 		return -1;
287*46439007SCharles.Forsyth 	if (*data == '>') {
288*46439007SCharles.Forsyth 		greater = 1;
289*46439007SCharles.Forsyth 		data++;
290*46439007SCharles.Forsyth 		k--;
291*46439007SCharles.Forsyth 	}
292*46439007SCharles.Forsyth 	else if (*data == '<') {
293*46439007SCharles.Forsyth 		greater = 0;
294*46439007SCharles.Forsyth 		data++;
295*46439007SCharles.Forsyth 		k--;
296*46439007SCharles.Forsyth 	}
297*46439007SCharles.Forsyth 	else
298*46439007SCharles.Forsyth 		greater = 1;
299*46439007SCharles.Forsyth 	if (k == 0)
300*46439007SCharles.Forsyth 		return -1;
301*46439007SCharles.Forsyth 	readerlistfindanddestroy(&sp->reader, senderrorreset, 0);
302*46439007SCharles.Forsyth 	set_sensor_passive(SENSOR_0 + i);
303*46439007SCharles.Forsyth 	sp->sensor.type = type;
304*46439007SCharles.Forsyth 	sp->sensor.mode = mode;
305*46439007SCharles.Forsyth 	sp->thresh = atoin(data, k);
306*46439007SCharles.Forsyth 	sp->sensor.raw = 0;
307*46439007SCharles.Forsyth 	sp->sensor.value = 0;
308*46439007SCharles.Forsyth 	sp->sensor.boolean = 0;
309*46439007SCharles.Forsyth 	sp->active = 1;
310*46439007SCharles.Forsyth 	sp->greater = greater;
311*46439007SCharles.Forsyth 	set_sensor_active(SENSOR_0 + i);
312*46439007SCharles.Forsyth 	return count;
313*46439007SCharles.Forsyth }
314*46439007SCharles.Forsyth 
315*46439007SCharles.Forsyth void
send_read_reply(ushort tag,ushort fid,ushort offset,ushort len,uchar * answer,short answerlen)316*46439007SCharles.Forsyth send_read_reply(ushort tag, ushort fid, ushort offset, ushort len, uchar *answer, short answerlen)
317*46439007SCharles.Forsyth {
318*46439007SCharles.Forsyth 	uchar *out = send_fid_reply_payload();
319*46439007SCharles.Forsyth 	ushort actual;
320*46439007SCharles.Forsyth 	if (offset < answerlen) {
321*46439007SCharles.Forsyth 		actual = answerlen - offset;
322*46439007SCharles.Forsyth 		if (actual > len)
323*46439007SCharles.Forsyth 			actual = len;
324*46439007SCharles.Forsyth 		memcpy(out + 3, answer + offset, actual);
325*46439007SCharles.Forsyth 	}
326*46439007SCharles.Forsyth 	else
327*46439007SCharles.Forsyth 		actual = 0;
328*46439007SCharles.Forsyth 	out[0] = actual;
329*46439007SCharles.Forsyth 	out[1] = actual >> 8;
330*46439007SCharles.Forsyth 	out[2] = 0;
331*46439007SCharles.Forsyth 	send_fid_reply(Rread, tag, fid, 0, actual + 3);
332*46439007SCharles.Forsyth }
333*46439007SCharles.Forsyth 
334*46439007SCharles.Forsyth void
send_sensor_read_reply(ushort tag,ushort fid,ushort offset,ushort count,short value)335*46439007SCharles.Forsyth send_sensor_read_reply(ushort tag, ushort fid, ushort offset, ushort count, short value)
336*46439007SCharles.Forsyth {
337*46439007SCharles.Forsyth 	short answerlen;
338*46439007SCharles.Forsyth 	char answer[8];
339*46439007SCharles.Forsyth 	/* reply is countlow counthigh pad data[count] */
340*46439007SCharles.Forsyth 	answerlen = itoa(answer, value);
341*46439007SCharles.Forsyth 	send_read_reply(tag, fid, offset, count, answer, answerlen);
342*46439007SCharles.Forsyth }
343*46439007SCharles.Forsyth 
344*46439007SCharles.Forsyth int
sensortriggered(Sensor * sp)345*46439007SCharles.Forsyth sensortriggered(Sensor *sp)
346*46439007SCharles.Forsyth {
347*46439007SCharles.Forsyth 	if (sp->greater)
348*46439007SCharles.Forsyth 		return sp->sensor.value >= sp->thresh;
349*46439007SCharles.Forsyth 	else
350*46439007SCharles.Forsyth 		return sp->sensor.value < sp->thresh;
351*46439007SCharles.Forsyth }
352*46439007SCharles.Forsyth 
353*46439007SCharles.Forsyth short
sensorread(const struct DirectoryEntry * dp,ushort tag,ushort fid,ushort offset,ushort count)354*46439007SCharles.Forsyth sensorread(const struct DirectoryEntry *dp, ushort tag, ushort fid, ushort offset, ushort count)
355*46439007SCharles.Forsyth {
356*46439007SCharles.Forsyth 	short i;
357*46439007SCharles.Forsyth 	Sensor *sp;
358*46439007SCharles.Forsyth 	i = dp->qid - QID_SENSOR_0;
359*46439007SCharles.Forsyth 	sp = sensor + i;
360*46439007SCharles.Forsyth 	if (!sp->active)
361*46439007SCharles.Forsyth 		return -1;
362*46439007SCharles.Forsyth 	if (sensortriggered(sp))
363*46439007SCharles.Forsyth 		send_sensor_read_reply(tag, fid, offset, count, sp->sensor.value);
364*46439007SCharles.Forsyth 	else {
365*46439007SCharles.Forsyth 		/* add to queue */
366*46439007SCharles.Forsyth 		Reader *rp = readercreate(tag, fid, offset, count);
367*46439007SCharles.Forsyth 		rp->next = sp->reader;
368*46439007SCharles.Forsyth 		sp->reader = rp;
369*46439007SCharles.Forsyth 	}
370*46439007SCharles.Forsyth 	return 0;
371*46439007SCharles.Forsyth }
372*46439007SCharles.Forsyth 
373*46439007SCharles.Forsyth void
sensorpoll(void)374*46439007SCharles.Forsyth sensorpoll(void)
375*46439007SCharles.Forsyth {
376*46439007SCharles.Forsyth 	short i;
377*46439007SCharles.Forsyth 	Sensor *sp;
378*46439007SCharles.Forsyth 
379*46439007SCharles.Forsyth 	if ((dispatch[0] & 0x80) == 0) {
380*46439007SCharles.Forsyth 		return;
381*46439007SCharles.Forsyth 	}
382*46439007SCharles.Forsyth 	dispatch[0] &= 0x7f;
383*46439007SCharles.Forsyth 	/* do the following every 3 ms with a following wind */
384*46439007SCharles.Forsyth 	for (i = 0; i < 3; i++) {
385*46439007SCharles.Forsyth 		sp = sensor + i;
386*46439007SCharles.Forsyth 		if (sp->active) {
387*46439007SCharles.Forsyth 			/*
388*46439007SCharles.Forsyth 			 * read sensor 4 times to reduce debounce on each
389*46439007SCharles.Forsyth 			 * edge to effectively 25 counts, or 75ms
390*46439007SCharles.Forsyth 			 * allowing about 8 pulses a second
391*46439007SCharles.Forsyth 			 */
392*46439007SCharles.Forsyth 			read_sensor(SENSOR_0 + i, &sp->sensor);
393*46439007SCharles.Forsyth 			read_sensor(SENSOR_0 + i, &sp->sensor);
394*46439007SCharles.Forsyth 			read_sensor(SENSOR_0 + i, &sp->sensor);
395*46439007SCharles.Forsyth 			read_sensor(SENSOR_0 + i, &sp->sensor);
396*46439007SCharles.Forsyth 			if (sensortriggered(sp)) {
397*46439007SCharles.Forsyth 				/* complete any outstanding reads */
398*46439007SCharles.Forsyth 				while (sp->reader) {
399*46439007SCharles.Forsyth 					Reader *rp = sp->reader;
400*46439007SCharles.Forsyth 					sp->reader = rp->next;
401*46439007SCharles.Forsyth 					send_sensor_read_reply(rp->tag, rp->fid, rp->offset, rp->count, sp->sensor.value);
402*46439007SCharles.Forsyth 					readerfree(rp);
403*46439007SCharles.Forsyth 				}
404*46439007SCharles.Forsyth 			}
405*46439007SCharles.Forsyth 		}
406*46439007SCharles.Forsyth 	}
407*46439007SCharles.Forsyth }
408*46439007SCharles.Forsyth 
409*46439007SCharles.Forsyth short
motorparse(uchar * flag,short * mode,short * power,uchar * data)410*46439007SCharles.Forsyth motorparse(uchar *flag, short *mode, short *power, uchar *data)
411*46439007SCharles.Forsyth {
412*46439007SCharles.Forsyth 	switch (data[0]) {
413*46439007SCharles.Forsyth 	case 'f': *mode = MOTOR_FWD; break;
414*46439007SCharles.Forsyth 	case 'r': *mode = MOTOR_REV; break;
415*46439007SCharles.Forsyth 	case 's': *mode = MOTOR_STOP; break;
416*46439007SCharles.Forsyth 	case 'F': *mode = MOTOR_FLOAT; break;
417*46439007SCharles.Forsyth 	case '-': return 1;
418*46439007SCharles.Forsyth 	default:
419*46439007SCharles.Forsyth 		return 0;
420*46439007SCharles.Forsyth 	}
421*46439007SCharles.Forsyth 	if (data[1] >= '0' && data[1] <= '7')
422*46439007SCharles.Forsyth 		*power = data[1] - '0';
423*46439007SCharles.Forsyth 	else
424*46439007SCharles.Forsyth 		return 0;
425*46439007SCharles.Forsyth 	*flag = 1;
426*46439007SCharles.Forsyth 	return 1;
427*46439007SCharles.Forsyth }
428*46439007SCharles.Forsyth 
429*46439007SCharles.Forsyth short
motorwrite(const DirectoryEntry * dp,ushort offset,ushort count,uchar * data)430*46439007SCharles.Forsyth motorwrite(const DirectoryEntry *dp, ushort offset, ushort count, uchar *data)
431*46439007SCharles.Forsyth {
432*46439007SCharles.Forsyth 	short mode[3], power[3];
433*46439007SCharles.Forsyth 	uchar flag[3];
434*46439007SCharles.Forsyth 	short i;
435*46439007SCharles.Forsyth 
436*46439007SCharles.Forsyth 	if (offset != 0)
437*46439007SCharles.Forsyth 		return -1;
438*46439007SCharles.Forsyth 	flag[0] = flag[1] = flag[2] = 0;
439*46439007SCharles.Forsyth 	if (dp->qid == QID_MOTOR_012) {
440*46439007SCharles.Forsyth 		if (count != 6)
441*46439007SCharles.Forsyth 			return -1;
442*46439007SCharles.Forsyth 		if (!motorparse(flag, mode, power, data)
443*46439007SCharles.Forsyth 		 || !motorparse(flag + 1, mode + 1, power + 1, data + 2)
444*46439007SCharles.Forsyth 		 || !motorparse(flag + 2, mode + 2, power + 2, data + 4))
445*46439007SCharles.Forsyth 			return -1;
446*46439007SCharles.Forsyth 	}
447*46439007SCharles.Forsyth 	else {
448*46439007SCharles.Forsyth 		if (count != 2)
449*46439007SCharles.Forsyth 			return -1;
450*46439007SCharles.Forsyth 		i = dp->qid - QID_MOTOR_0;
451*46439007SCharles.Forsyth 		if (!motorparse(flag + i, mode + i, power + i, data))
452*46439007SCharles.Forsyth 			return -1;
453*46439007SCharles.Forsyth 	}
454*46439007SCharles.Forsyth 	for (i = 0; i < 3; i++)
455*46439007SCharles.Forsyth 		if (flag[i])
456*46439007SCharles.Forsyth 			control_motor(MOTOR_0 + i, mode[i], power[i]);
457*46439007SCharles.Forsyth 	return count;
458*46439007SCharles.Forsyth }
459*46439007SCharles.Forsyth 
460*46439007SCharles.Forsyth const uchar qid_root[8] = { QID_ROOT, 0, 0, 0x80 };
461*46439007SCharles.Forsyth 
462*46439007SCharles.Forsyth const DirectoryEntry dir_root[], dir_slash[];
463*46439007SCharles.Forsyth 
464*46439007SCharles.Forsyth const DirectoryEntry dir_motor[] = {
465*46439007SCharles.Forsyth 	{ "..", QID_ROOT, dir_root },
466*46439007SCharles.Forsyth 	{ "0", QID_MOTOR_0,	0, 0, motorwrite },
467*46439007SCharles.Forsyth 	{ "1", QID_MOTOR_1,	0, 0, motorwrite },
468*46439007SCharles.Forsyth 	{ "2", QID_MOTOR_2,	0, 0, motorwrite },
469*46439007SCharles.Forsyth 	{ "012", QID_MOTOR_012, 0, 0, motorwrite },
470*46439007SCharles.Forsyth 	{ 0 }
471*46439007SCharles.Forsyth };
472*46439007SCharles.Forsyth 
473*46439007SCharles.Forsyth const DirectoryEntry dir_sensor[] = {
474*46439007SCharles.Forsyth 	{ "..", QID_ROOT, dir_root },
475*46439007SCharles.Forsyth 	{ "0", QID_SENSOR_0,	0, sensorread, sensorwrite },
476*46439007SCharles.Forsyth 	{ "1", QID_SENSOR_1,	0, sensorread, sensorwrite },
477*46439007SCharles.Forsyth 	{ "2", QID_SENSOR_2,	0, sensorread, sensorwrite },
478*46439007SCharles.Forsyth 	{ 0 }
479*46439007SCharles.Forsyth };
480*46439007SCharles.Forsyth 
481*46439007SCharles.Forsyth const DirectoryEntry dir_root[] = {
482*46439007SCharles.Forsyth 	{ "..", QID_ROOT, dir_slash },
483*46439007SCharles.Forsyth 	{ "motor", QID_MOTOR, dir_motor },
484*46439007SCharles.Forsyth 	{ "sensor", QID_SENSOR, dir_sensor },
485*46439007SCharles.Forsyth 	{ 0 }
486*46439007SCharles.Forsyth };
487*46439007SCharles.Forsyth 
488*46439007SCharles.Forsyth const DirectoryEntry dir_slash[] = {
489*46439007SCharles.Forsyth 	{ "/", QID_ROOT, dir_root },
490*46439007SCharles.Forsyth 	{ 0 }
491*46439007SCharles.Forsyth };
492*46439007SCharles.Forsyth 
493*46439007SCharles.Forsyth const DirectoryEntry *qid_map[] = {
494*46439007SCharles.Forsyth 	/* QID_ROOT */		&dir_slash[0],
495*46439007SCharles.Forsyth 	/* QID_MOTOR */		&dir_root[1],
496*46439007SCharles.Forsyth 	/* QID_MOTOR_0 */	&dir_motor[1],
497*46439007SCharles.Forsyth 	/* QID_MOTOR_1 */	&dir_motor[2],
498*46439007SCharles.Forsyth 	/* QID_MOTOR_2 */	&dir_motor[3],
499*46439007SCharles.Forsyth 	/* QID_MOTOR_012 */	&dir_motor[4],
500*46439007SCharles.Forsyth 	/* QID_SENSOR */	&dir_root[2],
501*46439007SCharles.Forsyth 	/* QID_SENSOR_0 */	&dir_sensor[1],
502*46439007SCharles.Forsyth 	/* QID_SENSOR_1 */	&dir_sensor[2],
503*46439007SCharles.Forsyth 	/* QID_SENSOR_2 */	&dir_sensor[3],
504*46439007SCharles.Forsyth };
505*46439007SCharles.Forsyth 
506*46439007SCharles.Forsyth #define QID_MAP_MAX (sizeof(qid_map) / sizeof(qid_map[0]))
507*46439007SCharles.Forsyth 
508*46439007SCharles.Forsyth typedef struct Fid {
509*46439007SCharles.Forsyth 	struct Fid *next;
510*46439007SCharles.Forsyth 	ushort fid;
511*46439007SCharles.Forsyth 	uchar open;
512*46439007SCharles.Forsyth 	uchar qid[8];
513*46439007SCharles.Forsyth } Fid;
514*46439007SCharles.Forsyth 
515*46439007SCharles.Forsyth Fid *fids;
516*46439007SCharles.Forsyth 
517*46439007SCharles.Forsyth Fid *
fidfind(ushort fid)518*46439007SCharles.Forsyth fidfind(ushort fid)
519*46439007SCharles.Forsyth {
520*46439007SCharles.Forsyth 	Fid *fp;
521*46439007SCharles.Forsyth 	for (fp = fids; fp && fp->fid != fid; fp = fp->next)
522*46439007SCharles.Forsyth 		;
523*46439007SCharles.Forsyth 	return fp;
524*46439007SCharles.Forsyth }
525*46439007SCharles.Forsyth 
526*46439007SCharles.Forsyth Fid *
fidcreate(ushort fid,const uchar qid[8])527*46439007SCharles.Forsyth fidcreate(ushort fid, const uchar qid[8])
528*46439007SCharles.Forsyth {
529*46439007SCharles.Forsyth 	Fid *fp;
530*46439007SCharles.Forsyth 	fp = malloc(sizeof(Fid));
531*46439007SCharles.Forsyth 	ASSERT(fp);
532*46439007SCharles.Forsyth 	fp->open = 0;
533*46439007SCharles.Forsyth 	fp->fid = fid;
534*46439007SCharles.Forsyth 	fp->next = fids;
535*46439007SCharles.Forsyth 	memcpy(fp->qid, qid, 8);
536*46439007SCharles.Forsyth 	fids = fp;
537*46439007SCharles.Forsyth 	return fp;
538*46439007SCharles.Forsyth }
539*46439007SCharles.Forsyth 
540*46439007SCharles.Forsyth int
matchfp(Reader * rp,void * magic)541*46439007SCharles.Forsyth matchfp(Reader *rp, void *magic)
542*46439007SCharles.Forsyth {
543*46439007SCharles.Forsyth 	if (rp->fid == ((Fid *)magic)->fid) {
544*46439007SCharles.Forsyth 		return 1;
545*46439007SCharles.Forsyth 	}
546*46439007SCharles.Forsyth 	return 0;
547*46439007SCharles.Forsyth }
548*46439007SCharles.Forsyth 
549*46439007SCharles.Forsyth void
fiddelete(Fid * fp)550*46439007SCharles.Forsyth fiddelete(Fid *fp)
551*46439007SCharles.Forsyth {
552*46439007SCharles.Forsyth 	Fid **fpp;
553*46439007SCharles.Forsyth 	/* clobber any outstanding reads on this fid */
554*46439007SCharles.Forsyth 	allreaderlistfindanddestroy(matchfp, fp);
555*46439007SCharles.Forsyth 	/* now clobber the fid */
556*46439007SCharles.Forsyth 	for (fpp = &fids; *fpp; fpp = &(*fpp)->next)
557*46439007SCharles.Forsyth 		if (*fpp == fp) {
558*46439007SCharles.Forsyth 			*fpp = fp->next;
559*46439007SCharles.Forsyth 			free(fp);
560*46439007SCharles.Forsyth 			return;
561*46439007SCharles.Forsyth 		}
562*46439007SCharles.Forsyth 	FATAL;
563*46439007SCharles.Forsyth }
564*46439007SCharles.Forsyth 
565*46439007SCharles.Forsyth const DirectoryEntry *
nthentry(const DirectoryEntry * dp,ushort n)566*46439007SCharles.Forsyth nthentry(const DirectoryEntry *dp, ushort n)
567*46439007SCharles.Forsyth {
568*46439007SCharles.Forsyth 	const DirectoryEntry *sdp;
569*46439007SCharles.Forsyth 	ASSERT(dp->sub);
570*46439007SCharles.Forsyth 	for (sdp = dp->sub; sdp->name; sdp++)
571*46439007SCharles.Forsyth 		if (strcmp(sdp->name, "..") != 0) {
572*46439007SCharles.Forsyth 			if (n == 0)
573*46439007SCharles.Forsyth 				return sdp;
574*46439007SCharles.Forsyth 			n--;
575*46439007SCharles.Forsyth 		}
576*46439007SCharles.Forsyth 	return 0;
577*46439007SCharles.Forsyth }
578*46439007SCharles.Forsyth 
579*46439007SCharles.Forsyth int
fidwalk(Fid * fp,char name[28])580*46439007SCharles.Forsyth fidwalk(Fid *fp, char name[28])
581*46439007SCharles.Forsyth {
582*46439007SCharles.Forsyth 	const DirectoryEntry *sdp;
583*46439007SCharles.Forsyth 	const DirectoryEntry *dp;
584*46439007SCharles.Forsyth 
585*46439007SCharles.Forsyth 	if (fp->open)
586*46439007SCharles.Forsyth 		return -1;
587*46439007SCharles.Forsyth 	ASSERT(fp->qid[0] < QID_MAP_MAX);
588*46439007SCharles.Forsyth 	dp = qid_map[fp->qid[0]];
589*46439007SCharles.Forsyth 	if (dp->sub == 0)
590*46439007SCharles.Forsyth 		return -1;
591*46439007SCharles.Forsyth 	for (sdp = dp->sub; sdp->name; sdp++)
592*46439007SCharles.Forsyth 		if (strcmp(sdp->name, name) == 0) {
593*46439007SCharles.Forsyth 			fp->qid[0] = sdp->qid;
594*46439007SCharles.Forsyth 			fp->qid[3] = sdp->sub ? 0x80 : 0;
595*46439007SCharles.Forsyth 			return 1;
596*46439007SCharles.Forsyth 		}
597*46439007SCharles.Forsyth 	return 0;
598*46439007SCharles.Forsyth }
599*46439007SCharles.Forsyth 
600*46439007SCharles.Forsyth void
mkdirent(const DirectoryEntry * dp,uchar * dir)601*46439007SCharles.Forsyth mkdirent(const DirectoryEntry *dp, uchar *dir)
602*46439007SCharles.Forsyth {
603*46439007SCharles.Forsyth 	memset(dir, 0, DIRLEN);
604*46439007SCharles.Forsyth 	strcpy(dir, dp->name);
605*46439007SCharles.Forsyth 	strcpy(dir + 28, "lego");
606*46439007SCharles.Forsyth 	strcpy(dir + 56, "lego");
607*46439007SCharles.Forsyth 	dir[84] = dp->qid;
608*46439007SCharles.Forsyth 	dir[92] = dp->sub ? 0555 : 0666;
609*46439007SCharles.Forsyth 	dir[93] = dp->sub ? (0555 >> 8) : (0666 >> 8);
610*46439007SCharles.Forsyth 	dir[95] = dp->sub ? 0x80 : 0;
611*46439007SCharles.Forsyth }
612*46439007SCharles.Forsyth 
613*46439007SCharles.Forsyth int
fidstat(Fid * fp,uchar * dir)614*46439007SCharles.Forsyth fidstat(Fid *fp, uchar *dir)
615*46439007SCharles.Forsyth {
616*46439007SCharles.Forsyth 	const DirectoryEntry *dp;
617*46439007SCharles.Forsyth 	if (fp->open)
618*46439007SCharles.Forsyth 		return -1;
619*46439007SCharles.Forsyth 	ASSERT(fp->qid[0] < QID_MAP_MAX);
620*46439007SCharles.Forsyth 	dp = qid_map[fp->qid[0]];
621*46439007SCharles.Forsyth 	mkdirent(dp, dir);
622*46439007SCharles.Forsyth 	return 1;
623*46439007SCharles.Forsyth }
624*46439007SCharles.Forsyth 
625*46439007SCharles.Forsyth int
fidopen(Fid * fp,uchar mode)626*46439007SCharles.Forsyth fidopen(Fid *fp, uchar mode)
627*46439007SCharles.Forsyth {
628*46439007SCharles.Forsyth 	if (fp->open
629*46439007SCharles.Forsyth 	    || (mode & ORCLOSE)
630*46439007SCharles.Forsyth 	    /*|| (mode & OTRUNC) */)
631*46439007SCharles.Forsyth 		return 0;
632*46439007SCharles.Forsyth 	if (fp->qid[3] && (mode == OWRITE || mode == ORDWR))
633*46439007SCharles.Forsyth 		/* can't write directories */
634*46439007SCharles.Forsyth 		return 0;
635*46439007SCharles.Forsyth 	fp->open = 1;
636*46439007SCharles.Forsyth 	return 1;
637*46439007SCharles.Forsyth }
638*46439007SCharles.Forsyth 
639*46439007SCharles.Forsyth short
fidread(Fid * fp,ushort tag,ushort offset,ushort count)640*46439007SCharles.Forsyth fidread(Fid *fp, ushort tag, ushort offset, ushort count)
641*46439007SCharles.Forsyth {
642*46439007SCharles.Forsyth 	short k;
643*46439007SCharles.Forsyth 	uchar *p;
644*46439007SCharles.Forsyth 	const DirectoryEntry *dp;
645*46439007SCharles.Forsyth 	uchar *buf;
646*46439007SCharles.Forsyth 
647*46439007SCharles.Forsyth 	ASSERT(fp->qid[0] < QID_MAP_MAX);
648*46439007SCharles.Forsyth 	dp = qid_map[fp->qid[0]];
649*46439007SCharles.Forsyth 
650*46439007SCharles.Forsyth 	if (fp->qid[3] & 0x80) {
651*46439007SCharles.Forsyth 		if (!fp->open)
652*46439007SCharles.Forsyth 			return -1;
653*46439007SCharles.Forsyth 		if (count % DIRLEN != 0 || offset % DIRLEN != 0)
654*46439007SCharles.Forsyth 			return -1;
655*46439007SCharles.Forsyth 		count /= DIRLEN;
656*46439007SCharles.Forsyth 		offset /= DIRLEN;
657*46439007SCharles.Forsyth 		buf = send_fid_reply_payload();
658*46439007SCharles.Forsyth 		p = buf + 3;
659*46439007SCharles.Forsyth 		for (k = 0; k < count; k++) {
660*46439007SCharles.Forsyth 			const DirectoryEntry *sdp = nthentry(dp, offset + k);
661*46439007SCharles.Forsyth 			if (sdp == 0)
662*46439007SCharles.Forsyth 				break;
663*46439007SCharles.Forsyth 			mkdirent(sdp, p);
664*46439007SCharles.Forsyth 			p += DIRLEN;
665*46439007SCharles.Forsyth 		}
666*46439007SCharles.Forsyth /* a read beyond just returns 0
667*46439007SCharles.Forsyth 		if (k == 0 && count)
668*46439007SCharles.Forsyth 			return -1;
669*46439007SCharles.Forsyth */
670*46439007SCharles.Forsyth 		k *= DIRLEN;
671*46439007SCharles.Forsyth 		buf[0] = k;
672*46439007SCharles.Forsyth 		buf[1] = k >> 8;
673*46439007SCharles.Forsyth 		buf[2] = 0;
674*46439007SCharles.Forsyth 		send_fid_reply(Rread, tag, fp->fid, 0, k + 3);
675*46439007SCharles.Forsyth 		return 0;
676*46439007SCharles.Forsyth 	}
677*46439007SCharles.Forsyth 	/* right, that's that out of the way */
678*46439007SCharles.Forsyth 	if (!dp->read)
679*46439007SCharles.Forsyth 		return -1;
680*46439007SCharles.Forsyth 	return (*dp->read)(dp, tag, fp->fid, offset, count);
681*46439007SCharles.Forsyth }
682*46439007SCharles.Forsyth 
683*46439007SCharles.Forsyth short
fidwrite(Fid * fp,ushort offset,ushort count,uchar * buf)684*46439007SCharles.Forsyth fidwrite(Fid *fp, ushort offset, ushort count, uchar *buf)
685*46439007SCharles.Forsyth {
686*46439007SCharles.Forsyth 	const DirectoryEntry *dp;
687*46439007SCharles.Forsyth 	if (fp->qid[3] & 0x80)
688*46439007SCharles.Forsyth 		return -1;		/* can't write directories */
689*46439007SCharles.Forsyth 	if (!fp->open)
690*46439007SCharles.Forsyth 		return -1;
691*46439007SCharles.Forsyth 	ASSERT(fp->qid[0] < QID_MAP_MAX);
692*46439007SCharles.Forsyth 	dp = qid_map[fp->qid[0]];
693*46439007SCharles.Forsyth 	if (!dp->write)
694*46439007SCharles.Forsyth 		return -1;		/* no write method */
695*46439007SCharles.Forsyth 	return (*dp->write)(dp, offset, count, buf);
696*46439007SCharles.Forsyth }
697*46439007SCharles.Forsyth 
698*46439007SCharles.Forsyth int
rlencode(unsigned char * out,int limit,unsigned char * in,int len)699*46439007SCharles.Forsyth rlencode(unsigned char *out, int limit, unsigned char *in, int len)
700*46439007SCharles.Forsyth {
701*46439007SCharles.Forsyth 	unsigned char *ip, *op;
702*46439007SCharles.Forsyth 	int oc, zc;
703*46439007SCharles.Forsyth 
704*46439007SCharles.Forsyth 	if (len == 0)
705*46439007SCharles.Forsyth 		return -1;
706*46439007SCharles.Forsyth 	ip = in;
707*46439007SCharles.Forsyth 	op = out;
708*46439007SCharles.Forsyth 	zc = 0;
709*46439007SCharles.Forsyth 
710*46439007SCharles.Forsyth 	oc = 0;
711*46439007SCharles.Forsyth 
712*46439007SCharles.Forsyth 	for (;;) {
713*46439007SCharles.Forsyth 		int last = ip >= in + len;
714*46439007SCharles.Forsyth 		if (*ip != 0 || last)
715*46439007SCharles.Forsyth 		{
716*46439007SCharles.Forsyth 			switch (zc) {
717*46439007SCharles.Forsyth 			case 1:
718*46439007SCharles.Forsyth 				if (oc >= len - 1)
719*46439007SCharles.Forsyth 					return -1;
720*46439007SCharles.Forsyth 				*op++ = 0;
721*46439007SCharles.Forsyth 				oc++;
722*46439007SCharles.Forsyth 				break;
723*46439007SCharles.Forsyth 			case 2:
724*46439007SCharles.Forsyth 				if (oc >= len - 2)
725*46439007SCharles.Forsyth 					return -1;
726*46439007SCharles.Forsyth 				*op++ = 0;
727*46439007SCharles.Forsyth 				*op++ = 0;
728*46439007SCharles.Forsyth 				oc += 2;
729*46439007SCharles.Forsyth 				break;
730*46439007SCharles.Forsyth 			case 0:
731*46439007SCharles.Forsyth 				break;
732*46439007SCharles.Forsyth 			default:
733*46439007SCharles.Forsyth 				if (oc >= len - 2)
734*46439007SCharles.Forsyth 					return -1;
735*46439007SCharles.Forsyth 				*op++ = 0x88;
736*46439007SCharles.Forsyth 				*op++ = zc - 2;
737*46439007SCharles.Forsyth 				oc += 2;
738*46439007SCharles.Forsyth 				break;
739*46439007SCharles.Forsyth 			}
740*46439007SCharles.Forsyth 			zc = 0;
741*46439007SCharles.Forsyth 		}
742*46439007SCharles.Forsyth 		if (last)
743*46439007SCharles.Forsyth 			break;
744*46439007SCharles.Forsyth 		if (*ip == 0x88) {
745*46439007SCharles.Forsyth 			if (oc >= len - 2)
746*46439007SCharles.Forsyth 				return -1;
747*46439007SCharles.Forsyth 			*op++ = 0x88;
748*46439007SCharles.Forsyth 			*op++ = 0x00;
749*46439007SCharles.Forsyth 			oc += 2;
750*46439007SCharles.Forsyth 		}
751*46439007SCharles.Forsyth 		else if (*ip == 0x00)
752*46439007SCharles.Forsyth 		{
753*46439007SCharles.Forsyth 			zc++;
754*46439007SCharles.Forsyth 		}
755*46439007SCharles.Forsyth 		else {
756*46439007SCharles.Forsyth 			if (oc >= len - 1)
757*46439007SCharles.Forsyth 				return -1;
758*46439007SCharles.Forsyth 			*op++ = *ip;
759*46439007SCharles.Forsyth 			oc++;
760*46439007SCharles.Forsyth 		}
761*46439007SCharles.Forsyth 		ip++;
762*46439007SCharles.Forsyth 	}
763*46439007SCharles.Forsyth 	return oc;
764*46439007SCharles.Forsyth }
765*46439007SCharles.Forsyth 
766*46439007SCharles.Forsyth int
rldecode(unsigned char * out,unsigned char * in,int len)767*46439007SCharles.Forsyth rldecode(unsigned char *out, unsigned char *in, int len)
768*46439007SCharles.Forsyth {
769*46439007SCharles.Forsyth 	int oc, k;
770*46439007SCharles.Forsyth 
771*46439007SCharles.Forsyth 	oc = 0;
772*46439007SCharles.Forsyth 
773*46439007SCharles.Forsyth 	while (len) {
774*46439007SCharles.Forsyth 		if (*in != 0x88) {
775*46439007SCharles.Forsyth 			*out++ = *in++;
776*46439007SCharles.Forsyth 			oc++;
777*46439007SCharles.Forsyth 			len--;
778*46439007SCharles.Forsyth 			continue;
779*46439007SCharles.Forsyth 		}
780*46439007SCharles.Forsyth 		in++;
781*46439007SCharles.Forsyth 		switch (*in) {
782*46439007SCharles.Forsyth 		case 0:
783*46439007SCharles.Forsyth 			*out++ = 0x88;
784*46439007SCharles.Forsyth 			oc++;
785*46439007SCharles.Forsyth 			break;
786*46439007SCharles.Forsyth 		default:
787*46439007SCharles.Forsyth 			k = *in + 2;
788*46439007SCharles.Forsyth 			oc += k;
789*46439007SCharles.Forsyth 			while (k-- > 0)
790*46439007SCharles.Forsyth 				*out++ = 0;
791*46439007SCharles.Forsyth 		}
792*46439007SCharles.Forsyth 		in++;
793*46439007SCharles.Forsyth 		len -= 2;
794*46439007SCharles.Forsyth 	}
795*46439007SCharles.Forsyth 	return oc;
796*46439007SCharles.Forsyth }
797*46439007SCharles.Forsyth 
798*46439007SCharles.Forsyth void
prepare_transmission(void)799*46439007SCharles.Forsyth prepare_transmission(void)
800*46439007SCharles.Forsyth {
801*46439007SCharles.Forsyth 	if (prepared)
802*46439007SCharles.Forsyth 		return;
803*46439007SCharles.Forsyth 	compressed_reply_len = rlencode(compressed_reply + 3, sizeof(compressed_reply) - 3, reply, reply_len);
804*46439007SCharles.Forsyth 	if (compressed_reply_len < 0) {
805*46439007SCharles.Forsyth 		memcpy(compressed_reply + 3, reply, reply_len);
806*46439007SCharles.Forsyth 		compressed_reply_len = reply_len;
807*46439007SCharles.Forsyth 		compressed_reply[2] = 0x0;
808*46439007SCharles.Forsyth 	}
809*46439007SCharles.Forsyth 	else
810*46439007SCharles.Forsyth 		compressed_reply[2] = LLP_COMPRESSION;
811*46439007SCharles.Forsyth 	if (reader_count)
812*46439007SCharles.Forsyth 		compressed_reply[2] |= LLP_POLL_PERIODIC;
813*46439007SCharles.Forsyth 	compressed_reply[2] |= !alternating_bit;
814*46439007SCharles.Forsyth 	compressed_reply_len++;
815*46439007SCharles.Forsyth 	compressed_reply[0] = compressed_reply_len;
816*46439007SCharles.Forsyth 	compressed_reply[1] = compressed_reply_len >> 8;
817*46439007SCharles.Forsyth 	compressed_reply_len += 2;
818*46439007SCharles.Forsyth 	prepared = 1;
819*46439007SCharles.Forsyth }
820*46439007SCharles.Forsyth 
821*46439007SCharles.Forsyth void
transmit(void)822*46439007SCharles.Forsyth transmit(void)
823*46439007SCharles.Forsyth {
824*46439007SCharles.Forsyth 	prepare_transmission();
825*46439007SCharles.Forsyth 	transmitted_reply_len = reply_len;
826*46439007SCharles.Forsyth 	send_message(compressed_reply, compressed_reply_len);
827*46439007SCharles.Forsyth }
828*46439007SCharles.Forsyth 
829*46439007SCharles.Forsyth void
flush_reply_buffer(void)830*46439007SCharles.Forsyth flush_reply_buffer(void)
831*46439007SCharles.Forsyth {
832*46439007SCharles.Forsyth 	if (reply_len > transmitted_reply_len)
833*46439007SCharles.Forsyth 		memcpy(reply, reply + transmitted_reply_len, reply_len - transmitted_reply_len);
834*46439007SCharles.Forsyth 	reply_len -= transmitted_reply_len;
835*46439007SCharles.Forsyth 	prepared = 0;
836*46439007SCharles.Forsyth }
837*46439007SCharles.Forsyth 
838*46439007SCharles.Forsyth void
send_reply(unsigned char type,unsigned short tag,unsigned char * msg,short len)839*46439007SCharles.Forsyth send_reply(unsigned char type, unsigned short tag, unsigned char *msg, short len)
840*46439007SCharles.Forsyth {
841*46439007SCharles.Forsyth 	uchar *p = reply + reply_len;
842*46439007SCharles.Forsyth 	p[0] = type;
843*46439007SCharles.Forsyth 	p[1] = tag & 0xff;
844*46439007SCharles.Forsyth 	p[2] = tag >> 8;
845*46439007SCharles.Forsyth 	if (msg)
846*46439007SCharles.Forsyth 		memcpy(p + 3, msg, len);
847*46439007SCharles.Forsyth 	reply_len += len + 3;
848*46439007SCharles.Forsyth 	prepared = 0;
849*46439007SCharles.Forsyth }
850*46439007SCharles.Forsyth 
851*46439007SCharles.Forsyth void
send_error_reply(unsigned short tag,char * msg)852*46439007SCharles.Forsyth send_error_reply(unsigned short tag, char *msg)
853*46439007SCharles.Forsyth {
854*46439007SCharles.Forsyth 	short len;
855*46439007SCharles.Forsyth 	uchar *p = reply + reply_len;
856*46439007SCharles.Forsyth 	p[0] = Rerror;
857*46439007SCharles.Forsyth 	p[1] = tag & 0xff;
858*46439007SCharles.Forsyth 	p[2] = tag >> 8;
859*46439007SCharles.Forsyth 	len = (short)strlen(msg);
860*46439007SCharles.Forsyth 	if (len > 64)
861*46439007SCharles.Forsyth 		len = 64;
862*46439007SCharles.Forsyth 	memcpy(p + 3, msg, len);
863*46439007SCharles.Forsyth 	reply_len += 67;
864*46439007SCharles.Forsyth 	prepared = 0;
865*46439007SCharles.Forsyth }
866*46439007SCharles.Forsyth 
867*46439007SCharles.Forsyth uchar *
send_fid_reply_payload(void)868*46439007SCharles.Forsyth send_fid_reply_payload(void)
869*46439007SCharles.Forsyth {
870*46439007SCharles.Forsyth 	return reply + reply_len + 5;
871*46439007SCharles.Forsyth }
872*46439007SCharles.Forsyth 
873*46439007SCharles.Forsyth void
send_fid_reply(uchar type,ushort tag,ushort fid,uchar * msg,short len)874*46439007SCharles.Forsyth send_fid_reply(uchar type, ushort tag, ushort fid, uchar *msg, short len)
875*46439007SCharles.Forsyth {
876*46439007SCharles.Forsyth 	uchar *p = reply + reply_len;
877*46439007SCharles.Forsyth 	p[0] = type;
878*46439007SCharles.Forsyth 	p[1] = tag & 0xff;
879*46439007SCharles.Forsyth 	p[2] = tag >> 8;
880*46439007SCharles.Forsyth 	p[3] = fid & 0xff;
881*46439007SCharles.Forsyth 	p[4] = fid >> 8;
882*46439007SCharles.Forsyth 	if (msg)
883*46439007SCharles.Forsyth 		memcpy(p + 5, msg, len);
884*46439007SCharles.Forsyth 	reply_len += len + 5;
885*46439007SCharles.Forsyth 	prepared = 0;
886*46439007SCharles.Forsyth }
887*46439007SCharles.Forsyth 
888*46439007SCharles.Forsyth int
matchtag(Reader * rp,void * oldtag)889*46439007SCharles.Forsyth matchtag(Reader *rp, void *oldtag)
890*46439007SCharles.Forsyth {
891*46439007SCharles.Forsyth 	if (rp->tag == (ushort)oldtag) {
892*46439007SCharles.Forsyth 		return 1;
893*46439007SCharles.Forsyth 	}
894*46439007SCharles.Forsyth 	return 0;
895*46439007SCharles.Forsyth }
896*46439007SCharles.Forsyth 
897*46439007SCharles.Forsyth void
flushtag(ushort oldtag)898*46439007SCharles.Forsyth flushtag(ushort oldtag)
899*46439007SCharles.Forsyth {
900*46439007SCharles.Forsyth 	/* a little inefficient this - there can be at most one match! */
901*46439007SCharles.Forsyth 	allreaderlistfindanddestroy(matchtag, (void *)oldtag);
902*46439007SCharles.Forsyth }
903*46439007SCharles.Forsyth 
904*46439007SCharles.Forsyth void
process_styx_message(unsigned char * msg,short len)905*46439007SCharles.Forsyth process_styx_message(unsigned char *msg, short len)
906*46439007SCharles.Forsyth {
907*46439007SCharles.Forsyth 	unsigned char type;
908*46439007SCharles.Forsyth 	ushort tag, oldtag, fid, newfid;
909*46439007SCharles.Forsyth 	ushort offset, count;
910*46439007SCharles.Forsyth 	short extra;
911*46439007SCharles.Forsyth 	Fid *fp, *nfp;
912*46439007SCharles.Forsyth 	short written;
913*46439007SCharles.Forsyth 	uchar buf[2];
914*46439007SCharles.Forsyth 
915*46439007SCharles.Forsyth 	ASSERT(len >= 3);
916*46439007SCharles.Forsyth 
917*46439007SCharles.Forsyth 	type = *msg++; len--;
918*46439007SCharles.Forsyth 	tag = (msg[1] << 8) | msg[0]; len -= 2; msg += 2;
919*46439007SCharles.Forsyth 
920*46439007SCharles.Forsyth 	switch (type) {
921*46439007SCharles.Forsyth 	case Tnop:
922*46439007SCharles.Forsyth 		send_reply(Rnop, tag, 0, 0);
923*46439007SCharles.Forsyth 		goto done;
924*46439007SCharles.Forsyth 	case Tflush:
925*46439007SCharles.Forsyth 		ASSERT(len == 2);
926*46439007SCharles.Forsyth 		oldtag = (msg[1] << 8) | msg[0];
927*46439007SCharles.Forsyth 		flushtag(oldtag);
928*46439007SCharles.Forsyth 		send_reply(Rflush, tag, 0, 0);
929*46439007SCharles.Forsyth 		goto done;
930*46439007SCharles.Forsyth 	}
931*46439007SCharles.Forsyth 	/* all other messages take a fid as well */
932*46439007SCharles.Forsyth 	ASSERT(len >= 2);
933*46439007SCharles.Forsyth 	fid = (msg[1] << 8) | msg[0]; len -= 2; msg += 2;
934*46439007SCharles.Forsyth 	fp = fidfind(fid);
935*46439007SCharles.Forsyth 
936*46439007SCharles.Forsyth 	switch (type) {
937*46439007SCharles.Forsyth 	case Tattach:
938*46439007SCharles.Forsyth 		ASSERT(len == 56);
939*46439007SCharles.Forsyth 		if (fp) {
940*46439007SCharles.Forsyth 		fid_in_use:
941*46439007SCharles.Forsyth 			send_error_reply(tag, "fid in use");
942*46439007SCharles.Forsyth 		}
943*46439007SCharles.Forsyth 		else {
944*46439007SCharles.Forsyth 			fp = fidcreate(fid, qid_root);
945*46439007SCharles.Forsyth 			send_fid_reply(Rattach, tag, fid, fp->qid, 8);
946*46439007SCharles.Forsyth 		}
947*46439007SCharles.Forsyth 		break;
948*46439007SCharles.Forsyth 	case Tclunk:
949*46439007SCharles.Forsyth 	case Tremove:
950*46439007SCharles.Forsyth 		ASSERT(len == 0);
951*46439007SCharles.Forsyth 		if (!fp) {
952*46439007SCharles.Forsyth 		no_such_fid:
953*46439007SCharles.Forsyth 			send_error_reply(tag, "no such fid");
954*46439007SCharles.Forsyth 		}
955*46439007SCharles.Forsyth 		else {
956*46439007SCharles.Forsyth 			fiddelete(fp);
957*46439007SCharles.Forsyth 			if (type == Tremove)
958*46439007SCharles.Forsyth 				send_error_reply(tag, "can't remove");
959*46439007SCharles.Forsyth 			else
960*46439007SCharles.Forsyth 				send_fid_reply(Rclunk, tag, fid, 0, 0);
961*46439007SCharles.Forsyth 		}
962*46439007SCharles.Forsyth 		break;
963*46439007SCharles.Forsyth 	case Tclone:
964*46439007SCharles.Forsyth 		ASSERT(len == 2);
965*46439007SCharles.Forsyth 		newfid = (msg[1] << 8) | msg[0];
966*46439007SCharles.Forsyth 		nfp = fidfind(newfid);
967*46439007SCharles.Forsyth 		if (!fp)
968*46439007SCharles.Forsyth 			goto no_such_fid;
969*46439007SCharles.Forsyth 		if (fp->open) {
970*46439007SCharles.Forsyth 			send_error_reply(tag, "can't clone");
971*46439007SCharles.Forsyth 			break;
972*46439007SCharles.Forsyth 		}
973*46439007SCharles.Forsyth 		if (nfp)
974*46439007SCharles.Forsyth 			goto fid_in_use;
975*46439007SCharles.Forsyth 		nfp = fidcreate(newfid, fp->qid);
976*46439007SCharles.Forsyth 		send_fid_reply(Rclone, tag, fid, 0, 0);
977*46439007SCharles.Forsyth 		break;
978*46439007SCharles.Forsyth 	case Twalk:
979*46439007SCharles.Forsyth 		ASSERT(len == 28);
980*46439007SCharles.Forsyth 		if (!fidwalk(fp, msg))
981*46439007SCharles.Forsyth 			send_error_reply(tag, "no such name");
982*46439007SCharles.Forsyth 		else
983*46439007SCharles.Forsyth 			send_fid_reply(Rwalk, tag, fid, fp->qid, 8);
984*46439007SCharles.Forsyth 		break;
985*46439007SCharles.Forsyth 	case Tstat:
986*46439007SCharles.Forsyth 		ASSERT(len == 0);
987*46439007SCharles.Forsyth 		if (!fidstat(fp, dir))
988*46439007SCharles.Forsyth 			send_error_reply(tag, "can't stat");
989*46439007SCharles.Forsyth 		else
990*46439007SCharles.Forsyth 			send_fid_reply(Rstat, tag, fid, dir, 116);
991*46439007SCharles.Forsyth 		break;
992*46439007SCharles.Forsyth 		ASSERT(len == 0);
993*46439007SCharles.Forsyth 	case Tcreate:
994*46439007SCharles.Forsyth 		ASSERT(len == 33);
995*46439007SCharles.Forsyth 		send_error_reply(tag, "can't create");
996*46439007SCharles.Forsyth 		break;
997*46439007SCharles.Forsyth 	case Topen:
998*46439007SCharles.Forsyth 		ASSERT(len == 1);
999*46439007SCharles.Forsyth 		if (!fidopen(fp, msg[0]))
1000*46439007SCharles.Forsyth 			send_error_reply(tag, "can't open");
1001*46439007SCharles.Forsyth 		else
1002*46439007SCharles.Forsyth 			send_fid_reply(Ropen, tag, fid, fp->qid, 8);
1003*46439007SCharles.Forsyth 		break;
1004*46439007SCharles.Forsyth 	case Tread:
1005*46439007SCharles.Forsyth 		ASSERT(len == 10);
1006*46439007SCharles.Forsyth 		offset = (msg[1] << 8) | msg[0];
1007*46439007SCharles.Forsyth 		count = (msg[9] << 8) | msg[8];
1008*46439007SCharles.Forsyth 		if (fidread(fp, tag, offset, count) < 0)
1009*46439007SCharles.Forsyth 			send_error_reply(tag, "can't read");
1010*46439007SCharles.Forsyth 		break;
1011*46439007SCharles.Forsyth 	case Twrite:
1012*46439007SCharles.Forsyth 		ASSERT(len >= 11);
1013*46439007SCharles.Forsyth 		offset = (msg[1] << 8) | msg[0];
1014*46439007SCharles.Forsyth 		count = (msg[9] << 8) | msg[8];
1015*46439007SCharles.Forsyth 		msg += 11;
1016*46439007SCharles.Forsyth 		len -= 11;
1017*46439007SCharles.Forsyth 		ASSERT(count == len);
1018*46439007SCharles.Forsyth 		written = fidwrite(fp, offset, count, msg);
1019*46439007SCharles.Forsyth 		if (written < 0)
1020*46439007SCharles.Forsyth 			send_error_reply(tag, "can't write");
1021*46439007SCharles.Forsyth 		else {
1022*46439007SCharles.Forsyth 			buf[0] = written;
1023*46439007SCharles.Forsyth 			buf[1] = written >> 8;
1024*46439007SCharles.Forsyth 			send_fid_reply(Rwrite, tag, fid, buf, 2);
1025*46439007SCharles.Forsyth 		}
1026*46439007SCharles.Forsyth 		break;
1027*46439007SCharles.Forsyth 	default:
1028*46439007SCharles.Forsyth 		FATAL;
1029*46439007SCharles.Forsyth 	}
1030*46439007SCharles.Forsyth done:
1031*46439007SCharles.Forsyth 	;
1032*46439007SCharles.Forsyth }
1033*46439007SCharles.Forsyth 
1034*46439007SCharles.Forsyth void
process_llp_message(unsigned char * msg,short len)1035*46439007SCharles.Forsyth process_llp_message(unsigned char *msg, short len)
1036*46439007SCharles.Forsyth {
1037*46439007SCharles.Forsyth 	short styxlen;
1038*46439007SCharles.Forsyth 	switch (msg[0]) {
1039*46439007SCharles.Forsyth 	case 0x45:
1040*46439007SCharles.Forsyth 	case 0x4d:
1041*46439007SCharles.Forsyth 		if (len != 5)
1042*46439007SCharles.Forsyth 			FATAL;
1043*46439007SCharles.Forsyth 		styxlen = compressed_incoming[0] | (compressed_incoming[1] << 8);
1044*46439007SCharles.Forsyth 		/* transfer the transmitted checksum to the end */
1045*46439007SCharles.Forsyth 		compressed_incoming[styxlen + 2 - 1] = msg[3];
1046*46439007SCharles.Forsyth 		/* check alternating bit */
1047*46439007SCharles.Forsyth #ifdef ABP
1048*46439007SCharles.Forsyth 		if ((compressed_incoming[2] & 1) != alternating_bit ||
1049*46439007SCharles.Forsyth 		    ((msg[0] & 8) != 0) != alternating_bit) {
1050*46439007SCharles.Forsyth 			transmit();
1051*46439007SCharles.Forsyth 			break;
1052*46439007SCharles.Forsyth 		}
1053*46439007SCharles.Forsyth #endif
1054*46439007SCharles.Forsyth 		alternating_bit = !alternating_bit;
1055*46439007SCharles.Forsyth 		flush_reply_buffer();
1056*46439007SCharles.Forsyth 		if (styxlen > 1) {
1057*46439007SCharles.Forsyth 			if (compressed_incoming[2] & LLP_COMPRESSION) {
1058*46439007SCharles.Forsyth 				/* decompress everything but length and link header */
1059*46439007SCharles.Forsyth 				styxlen = rldecode(incoming, compressed_incoming + 3, styxlen - 1);
1060*46439007SCharles.Forsyth 				process_styx_message(incoming, styxlen);
1061*46439007SCharles.Forsyth 			}
1062*46439007SCharles.Forsyth 			else
1063*46439007SCharles.Forsyth 				process_styx_message(compressed_incoming + 3, styxlen - 1);
1064*46439007SCharles.Forsyth 		}
1065*46439007SCharles.Forsyth 		transmit();
1066*46439007SCharles.Forsyth 		break;
1067*46439007SCharles.Forsyth 	default:
1068*46439007SCharles.Forsyth 		FATAL;
1069*46439007SCharles.Forsyth 	}
1070*46439007SCharles.Forsyth }
1071*46439007SCharles.Forsyth 
1072*46439007SCharles.Forsyth int
main(void)1073*46439007SCharles.Forsyth main (void)
1074*46439007SCharles.Forsyth {
1075*46439007SCharles.Forsyth 	int count = 0;
1076*46439007SCharles.Forsyth 	char buf[16];
1077*46439007SCharles.Forsyth 	char temp[64];
1078*46439007SCharles.Forsyth 
1079*46439007SCharles.Forsyth 	mem_init();
1080*46439007SCharles.Forsyth 	memset(temp,0, sizeof(temp));
1081*46439007SCharles.Forsyth 
1082*46439007SCharles.Forsyth 	/* Initialize */
1083*46439007SCharles.Forsyth 
1084*46439007SCharles.Forsyth 	init_timer(&temp[6], &dispatch[0]);
1085*46439007SCharles.Forsyth 	init_power();
1086*46439007SCharles.Forsyth 	init_sensors();
1087*46439007SCharles.Forsyth 	init_serial(&temp[4], &temp[6], 1, 1);
1088*46439007SCharles.Forsyth 
1089*46439007SCharles.Forsyth 	set_lcd_number(LCD_UNSIGNED, 0, LCD_DECIMAL_0);
1090*46439007SCharles.Forsyth 	set_lcd_segment(LCD_WALKING);
1091*46439007SCharles.Forsyth 	refresh_display();
1092*46439007SCharles.Forsyth 
1093*46439007SCharles.Forsyth 	set_data_pointer(compressed_incoming);
1094*46439007SCharles.Forsyth 
1095*46439007SCharles.Forsyth 	alternating_bit = 0;
1096*46439007SCharles.Forsyth 	compressed_reply_len = 0;
1097*46439007SCharles.Forsyth 	reply_len = 0;
1098*46439007SCharles.Forsyth 	prepared = 0;
1099*46439007SCharles.Forsyth 
1100*46439007SCharles.Forsyth 	while (poll_power() != 0) {
1101*46439007SCharles.Forsyth 
1102*46439007SCharles.Forsyth 		/* If a message has arrived, send a response with opcode inverted */
1103*46439007SCharles.Forsyth 
1104*46439007SCharles.Forsyth 		if (check_valid()) {
1105*46439007SCharles.Forsyth 			int len = receive_message(buf, sizeof(buf));
1106*46439007SCharles.Forsyth 			msgcount++;
1107*46439007SCharles.Forsyth 			process_llp_message(buf, len);
1108*46439007SCharles.Forsyth 		}
1109*46439007SCharles.Forsyth 		sensorpoll();
1110*46439007SCharles.Forsyth 	}
1111*46439007SCharles.Forsyth 
1112*46439007SCharles.Forsyth 	return 0;
1113*46439007SCharles.Forsyth }
1114