undo.1: Add some words about the new fake transaction id warning.
[dragonfly.git] / libexec / xtend / packet.c
blob7783f15b7c8eadf662300e4691fa2fa32b7db1b3
1 /*-
2 * Copyright (c) 1992, 1993, 1995 Eugene W. Stark
3 * All rights reserved.
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.
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.
31 * $FreeBSD: src/libexec/xtend/packet.c,v 1.8 1999/08/28 00:10:30 peter Exp $
32 * $DragonFly: src/libexec/xtend/packet.c,v 1.2 2003/06/17 04:27:08 dillon Exp $
35 #include <stdio.h>
36 #include <sys/time.h>
37 #include "xtend.h"
38 #include "xten.h"
40 char *X10housenames[] = {
41 "A", "B", "C", "D", "E", "F", "G", "H",
42 "I", "J", "K", "L", "M", "N", "O", "P",
43 NULL
46 char *X10cmdnames[] = {
47 "1", "2", "3", "4", "5", "6", "7", "8",
48 "9", "10", "11", "12", "13", "14", "15", "16",
49 "AllUnitsOff", "AllLightsOn", "On", "Off", "Dim", "Bright", "AllLightsOff",
50 "ExtendedCode", "HailRequest", "HailAcknowledge", "PreSetDim0", "PreSetDim1",
51 "ExtendedData", "StatusOn", "StatusOff", "StatusRequest",
52 NULL
56 * Log a packet and update device status accordingly
59 void
60 logpacket(p)
61 unsigned char *p;
63 fprintf(Log, "%s: %s %s ", thedate(),
64 X10housenames[p[1]], X10cmdnames[p[2]]);
65 if(p[0] & TW_RCV_LOCAL) fprintf(Log, "(loc,");
66 else fprintf(Log, "(rem,");
67 if(p[0] & TW_RCV_ERROR) fprintf(Log, "err)");
68 else fprintf(Log, " ok)");
69 fprintf(Log, "\n");
73 * Process a received packet p, updating device status information both
74 * in core and on disk.
77 void
78 processpacket(p)
79 unsigned char *p;
81 int i, j, h, k;
82 STATUS *s;
85 * If the packet had the error flag set, there is no other useful info.
87 if(p[0] & TW_RCV_ERROR) return;
89 * First update in-core status information for the device.
91 h = p[1]; k = p[2];
92 if(k < 16) { /* We received a unit code, to select a particular device */
93 s = &Status[h][k];
94 s->selected = SELECTED;
95 s->lastchange = time(NULL);
96 s->changed = 1;
97 } else { /* We received a key code, to execute some function */
99 * Change in status depends on the key code received
101 if(k == DIM) {
103 * We can't really track DIM/BRIGHT properly the way things are right
104 * now. The TW523 reports the first, fourth, seventh, etc. Dim packet.
105 * We don't really have any way to tell when gaps occur, to cancel
106 * selection. For now, we'll assume that successive sequences of
107 * Dim/Bright commands are never transmitted without some other
108 * intervening command, and we make a good guess about how many units of
109 * dim/bright are represented by each packet actually reported by the
110 * TW523.
112 for(i = 0; i < 16; i++) {
113 s = &Status[h][i];
114 switch(s->selected) {
115 case SELECTED: /* Selected, but not being dimmed or brightened */
116 if(s->onoff == 0) {
117 s->onoff = 1;
118 s->brightness = 15;
120 s->brightness -= 2;
121 if(s->brightness < 0) s->brightness = 0;
122 s->selected = DIMMING;
123 s->lastchange = time(NULL);
124 s->changed = 1;
125 break;
126 case DIMMING: /* Selected and being dimmed */
127 s->brightness -=3;
128 if(s->brightness < 0) s->brightness = 0;
129 s->lastchange = time(NULL);
130 s->changed = 1;
131 break;
132 case BRIGHTENING: /* Selected and being brightened (an error) */
133 s->selected = IDLE;
134 s->lastchange = time(NULL);
135 s->changed = 1;
136 break;
137 default:
138 break;
141 } else if(k == BRIGHT) {
143 * Same problem here...
145 for(i = 0; i < 16; i++) {
146 s = &Status[h][i];
147 switch(s->selected) {
148 case SELECTED: /* Selected, but not being dimmed or brightened */
149 if(s->onoff == 0) {
150 s->onoff = 1;
151 s->brightness = 15;
153 s->brightness += 2;
154 if(s->brightness > 15) s->brightness = 15;
155 s->selected = BRIGHTENING;
156 s->lastchange = time(NULL);
157 s->changed = 1;
158 break;
159 case DIMMING: /* Selected and being dimmed (an error) */
160 s->selected = IDLE;
161 s->lastchange = time(NULL);
162 s->changed = 1;
163 break;
164 case BRIGHTENING: /* Selected and being brightened */
165 s->brightness +=3;
166 if(s->brightness > 15) s->brightness = 15;
167 s->lastchange = time(NULL);
168 s->changed = 1;
169 break;
170 default:
171 break;
174 } else { /* Other key codes besides Bright and Dim */
176 * We cancel brightening and dimming on ALL units on ALL house codes,
177 * because the arrival of a different packet indicates a gap that
178 * terminates any prior sequence of brightening and dimming
180 for(j = 0; j < 16; j++) {
181 for(i = 0; i < 16; i++) {
182 s = &Status[j][i];
183 if(s->selected == BRIGHTENING || s->selected == DIMMING) {
184 s->selected = IDLE;
185 s->lastchange = time(NULL);
186 s->changed = 1;
190 switch(k) {
191 case ALLUNITSOFF:
192 for(i = 0; i < 16; i++) {
193 s = &Status[h][i];
194 s->onoff = 0;
195 s->selected = IDLE;
196 s->brightness = 0;
197 s->lastchange = time(NULL);
198 s->changed = 1;
200 break;
201 case ALLLIGHTSON:
202 /* Does AllLightsOn cancel selectedness of non-lights? */
203 for(i = 0; i < 16; i++) {
204 s = &Status[h][i];
205 if(s->devcap & ISLIGHT) {
206 s->onoff = 1;
207 s->selected = IDLE;
208 s->brightness = 15;
209 s->lastchange = time(NULL);
210 s->changed = 1;
213 break;
214 case UNITON:
215 for(i = 0; i < 16; i++) {
216 s = &Status[h][i];
217 if(s->selected == SELECTED) {
218 s->onoff = 1;
219 s->selected = IDLE;
220 s->brightness = 15;
221 s->lastchange = time(NULL);
222 s->changed = 1;
225 break;
226 case UNITOFF:
227 for(i = 0; i < 16; i++) {
228 s = &Status[h][i];
229 if(s->selected == SELECTED) {
230 s->onoff = 0;
231 s->selected = IDLE;
232 s->lastchange = time(NULL);
233 s->changed = 1;
236 break;
237 case ALLLIGHTSOFF:
238 /* Does AllLightsOff cancel selectedness of non-lights? */
239 for(i = 0; i < 16; i++) {
240 s = &Status[h][i];
241 if(s->devcap & ISLIGHT) {
242 s->onoff = 0;
243 s->selected = IDLE;
244 s->lastchange = time(NULL);
245 s->changed = 1;
248 break;
249 case EXTENDEDCODE:
250 break;
251 case HAILREQUEST:
252 for(i = 0; i < 16; i++) {
253 s = &Status[h][i];
254 if(s->selected == SELECTED) {
255 s->selected = HAILED;
256 s->lastchange = time(NULL);
257 s->changed = 1;
260 break;
261 case HAILACKNOWLEDGE:
262 /* Do these commands cancel selection of devices not affected? */
263 for(i = 0; i < 16; i++) {
264 s = &Status[h][i];
265 if(s->selected == HAILED) {
266 s->selected = IDLE;
267 s->lastchange = time(NULL);
268 s->changed = 1;
271 break;
272 case PRESETDIM0:
273 case PRESETDIM1:
274 /* I don't really understand these */
275 for(i = 0; i < 16; i++) {
276 s = &Status[h][i];
277 if(s->selected == SELECTED) {
278 s->selected = IDLE;
279 s->lastchange = time(NULL);
280 s->changed = 1;
283 break;
284 case EXTENDEDDATA:
285 /* Who knows? The TW523 can't receive these anyway. */
286 break;
287 case STATUSON:
288 for(i = 0; i < 16; i++) {
289 s = &Status[h][i];
290 if(s->selected == REQUESTED) {
291 s->onoff = 1;
292 s->selected = IDLE;
293 s->lastchange = time(NULL);
294 s->changed = 1;
297 break;
298 case STATUSOFF:
299 for(i = 0; i < 16; i++) {
300 if(s->selected == REQUESTED) {
301 s = &Status[h][i];
302 s->onoff = 0;
303 s->selected = IDLE;
304 s->brightness = 0;
305 s->lastchange = time(NULL);
306 s->changed = 1;
309 case STATUSREQUEST:
310 for(i = 0; i < 16; i++) {
311 s = &Status[h][i];
312 if(s->selected) {
313 s->selected = REQUESTED;
314 s->lastchange = time(NULL);
315 s->changed = 1;
318 break;