Initial import from FreeBSD RELENG_4:
[dragonfly.git] / libexec / xtend / packet.c
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1992, 1993, 1995 Eugene W. Stark
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Eugene W. Stark.
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#ifndef lint
33static const char rcsid[] =
34 "$FreeBSD: src/libexec/xtend/packet.c,v 1.8 1999/08/28 00:10:30 peter Exp $";
35#endif /* not lint */
36
37#include <stdio.h>
38#include <sys/time.h>
39#include "xtend.h"
40#include "xten.h"
41
42char *X10housenames[] = {
43 "A", "B", "C", "D", "E", "F", "G", "H",
44 "I", "J", "K", "L", "M", "N", "O", "P",
45 NULL
46};
47
48char *X10cmdnames[] = {
49 "1", "2", "3", "4", "5", "6", "7", "8",
50 "9", "10", "11", "12", "13", "14", "15", "16",
51 "AllUnitsOff", "AllLightsOn", "On", "Off", "Dim", "Bright", "AllLightsOff",
52 "ExtendedCode", "HailRequest", "HailAcknowledge", "PreSetDim0", "PreSetDim1",
53 "ExtendedData", "StatusOn", "StatusOff", "StatusRequest",
54 NULL
55};
56
57/*
58 * Log a packet and update device status accordingly
59 */
60
61void
62logpacket(p)
63unsigned char *p;
64{
65 fprintf(Log, "%s: %s %s ", thedate(),
66 X10housenames[p[1]], X10cmdnames[p[2]]);
67 if(p[0] & TW_RCV_LOCAL) fprintf(Log, "(loc,");
68 else fprintf(Log, "(rem,");
69 if(p[0] & TW_RCV_ERROR) fprintf(Log, "err)");
70 else fprintf(Log, " ok)");
71 fprintf(Log, "\n");
72}
73
74/*
75 * Process a received packet p, updating device status information both
76 * in core and on disk.
77 */
78
79void
80processpacket(p)
81unsigned char *p;
82{
83 int i, j, h, k;
84 STATUS *s;
85
86 /*
87 * If the packet had the error flag set, there is no other useful info.
88 */
89 if(p[0] & TW_RCV_ERROR) return;
90 /*
91 * First update in-core status information for the device.
92 */
93 h = p[1]; k = p[2];
94 if(k < 16) { /* We received a unit code, to select a particular device */
95 s = &Status[h][k];
96 s->selected = SELECTED;
97 s->lastchange = time(NULL);
98 s->changed = 1;
99 } else { /* We received a key code, to execute some function */
100 /*
101 * Change in status depends on the key code received
102 */
103 if(k == DIM) {
104 /*
105 * We can't really track DIM/BRIGHT properly the way things are right
106 * now. The TW523 reports the first, fourth, seventh, etc. Dim packet.
107 * We don't really have any way to tell when gaps occur, to cancel
108 * selection. For now, we'll assume that successive sequences of
109 * Dim/Bright commands are never transmitted without some other
110 * intervening command, and we make a good guess about how many units of
111 * dim/bright are represented by each packet actually reported by the
112 * TW523.
113 */
114 for(i = 0; i < 16; i++) {
115 s = &Status[h][i];
116 switch(s->selected) {
117 case SELECTED: /* Selected, but not being dimmed or brightened */
118 if(s->onoff == 0) {
119 s->onoff = 1;
120 s->brightness = 15;
121 }
122 s->brightness -= 2;
123 if(s->brightness < 0) s->brightness = 0;
124 s->selected = DIMMING;
125 s->lastchange = time(NULL);
126 s->changed = 1;
127 break;
128 case DIMMING: /* Selected and being dimmed */
129 s->brightness -=3;
130 if(s->brightness < 0) s->brightness = 0;
131 s->lastchange = time(NULL);
132 s->changed = 1;
133 break;
134 case BRIGHTENING: /* Selected and being brightened (an error) */
135 s->selected = IDLE;
136 s->lastchange = time(NULL);
137 s->changed = 1;
138 break;
139 default:
140 break;
141 }
142 }
143 } else if(k == BRIGHT) {
144 /*
145 * Same problem here...
146 */
147 for(i = 0; i < 16; i++) {
148 s = &Status[h][i];
149 switch(s->selected) {
150 case SELECTED: /* Selected, but not being dimmed or brightened */
151 if(s->onoff == 0) {
152 s->onoff = 1;
153 s->brightness = 15;
154 }
155 s->brightness += 2;
156 if(s->brightness > 15) s->brightness = 15;
157 s->selected = BRIGHTENING;
158 s->lastchange = time(NULL);
159 s->changed = 1;
160 break;
161 case DIMMING: /* Selected and being dimmed (an error) */
162 s->selected = IDLE;
163 s->lastchange = time(NULL);
164 s->changed = 1;
165 break;
166 case BRIGHTENING: /* Selected and being brightened */
167 s->brightness +=3;
168 if(s->brightness > 15) s->brightness = 15;
169 s->lastchange = time(NULL);
170 s->changed = 1;
171 break;
172 default:
173 break;
174 }
175 }
176 } else { /* Other key codes besides Bright and Dim */
177 /*
178 * We cancel brightening and dimming on ALL units on ALL house codes,
179 * because the arrival of a different packet indicates a gap that
180 * terminates any prior sequence of brightening and dimming
181 */
182 for(j = 0; j < 16; j++) {
183 for(i = 0; i < 16; i++) {
184 s = &Status[j][i];
185 if(s->selected == BRIGHTENING || s->selected == DIMMING) {
186 s->selected = IDLE;
187 s->lastchange = time(NULL);
188 s->changed = 1;
189 }
190 }
191 }
192 switch(k) {
193 case ALLUNITSOFF:
194 for(i = 0; i < 16; i++) {
195 s = &Status[h][i];
196 s->onoff = 0;
197 s->selected = IDLE;
198 s->brightness = 0;
199 s->lastchange = time(NULL);
200 s->changed = 1;
201 }
202 break;
203 case ALLLIGHTSON:
204 /* Does AllLightsOn cancel selectedness of non-lights? */
205 for(i = 0; i < 16; i++) {
206 s = &Status[h][i];
207 if(s->devcap & ISLIGHT) {
208 s->onoff = 1;
209 s->selected = IDLE;
210 s->brightness = 15;
211 s->lastchange = time(NULL);
212 s->changed = 1;
213 }
214 }
215 break;
216 case UNITON:
217 for(i = 0; i < 16; i++) {
218 s = &Status[h][i];
219 if(s->selected == SELECTED) {
220 s->onoff = 1;
221 s->selected = IDLE;
222 s->brightness = 15;
223 s->lastchange = time(NULL);
224 s->changed = 1;
225 }
226 }
227 break;
228 case UNITOFF:
229 for(i = 0; i < 16; i++) {
230 s = &Status[h][i];
231 if(s->selected == SELECTED) {
232 s->onoff = 0;
233 s->selected = IDLE;
234 s->lastchange = time(NULL);
235 s->changed = 1;
236 }
237 }
238 break;
239 case ALLLIGHTSOFF:
240 /* Does AllLightsOff cancel selectedness of non-lights? */
241 for(i = 0; i < 16; i++) {
242 s = &Status[h][i];
243 if(s->devcap & ISLIGHT) {
244 s->onoff = 0;
245 s->selected = IDLE;
246 s->lastchange = time(NULL);
247 s->changed = 1;
248 }
249 }
250 break;
251 case EXTENDEDCODE:
252 break;
253 case HAILREQUEST:
254 for(i = 0; i < 16; i++) {
255 s = &Status[h][i];
256 if(s->selected == SELECTED) {
257 s->selected = HAILED;
258 s->lastchange = time(NULL);
259 s->changed = 1;
260 }
261 }
262 break;
263 case HAILACKNOWLEDGE:
264 /* Do these commands cancel selection of devices not affected? */
265 for(i = 0; i < 16; i++) {
266 s = &Status[h][i];
267 if(s->selected == HAILED) {
268 s->selected = IDLE;
269 s->lastchange = time(NULL);
270 s->changed = 1;
271 }
272 }
273 break;
274 case PRESETDIM0:
275 case PRESETDIM1:
276 /* I don't really understand these */
277 for(i = 0; i < 16; i++) {
278 s = &Status[h][i];
279 if(s->selected == SELECTED) {
280 s->selected = IDLE;
281 s->lastchange = time(NULL);
282 s->changed = 1;
283 }
284 }
285 break;
286 case EXTENDEDDATA:
287 /* Who knows? The TW523 can't receive these anyway. */
288 break;
289 case STATUSON:
290 for(i = 0; i < 16; i++) {
291 s = &Status[h][i];
292 if(s->selected == REQUESTED) {
293 s->onoff = 1;
294 s->selected = IDLE;
295 s->lastchange = time(NULL);
296 s->changed = 1;
297 }
298 }
299 break;
300 case STATUSOFF:
301 for(i = 0; i < 16; i++) {
302 if(s->selected == REQUESTED) {
303 s = &Status[h][i];
304 s->onoff = 0;
305 s->selected = IDLE;
306 s->brightness = 0;
307 s->lastchange = time(NULL);
308 s->changed = 1;
309 }
310 }
311 case STATUSREQUEST:
312 for(i = 0; i < 16; i++) {
313 s = &Status[h][i];
314 if(s->selected) {
315 s->selected = REQUESTED;
316 s->lastchange = time(NULL);
317 s->changed = 1;
318 }
319 }
320 break;
321 }
322 }
323 }
324}