2 * Copyright (c) 1992, 1993, 1995 Eugene W. Stark
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
33 static const char rcsid[] =
34 "$FreeBSD: src/libexec/xtend/packet.c,v 1.8 1999/08/28 00:10:30 peter Exp $";
42 char *X10housenames[] = {
43 "A", "B", "C", "D", "E", "F", "G", "H",
44 "I", "J", "K", "L", "M", "N", "O", "P",
48 char *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",
58 * Log a packet and update device status accordingly
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)");
75 * Process a received packet p, updating device status information both
76 * in core and on disk.
87 * If the packet had the error flag set, there is no other useful info.
89 if(p[0] & TW_RCV_ERROR) return;
91 * First update in-core status information for the device.
94 if(k < 16) { /* We received a unit code, to select a particular device */
96 s->selected = SELECTED;
97 s->lastchange = time(NULL);
99 } else { /* We received a key code, to execute some function */
101 * Change in status depends on the key code received
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
114 for(i = 0; i < 16; i++) {
116 switch(s->selected) {
117 case SELECTED: /* Selected, but not being dimmed or brightened */
123 if(s->brightness < 0) s->brightness = 0;
124 s->selected = DIMMING;
125 s->lastchange = time(NULL);
128 case DIMMING: /* Selected and being dimmed */
130 if(s->brightness < 0) s->brightness = 0;
131 s->lastchange = time(NULL);
134 case BRIGHTENING: /* Selected and being brightened (an error) */
136 s->lastchange = time(NULL);
143 } else if(k == BRIGHT) {
145 * Same problem here...
147 for(i = 0; i < 16; i++) {
149 switch(s->selected) {
150 case SELECTED: /* Selected, but not being dimmed or brightened */
156 if(s->brightness > 15) s->brightness = 15;
157 s->selected = BRIGHTENING;
158 s->lastchange = time(NULL);
161 case DIMMING: /* Selected and being dimmed (an error) */
163 s->lastchange = time(NULL);
166 case BRIGHTENING: /* Selected and being brightened */
168 if(s->brightness > 15) s->brightness = 15;
169 s->lastchange = time(NULL);
176 } else { /* Other key codes besides Bright and Dim */
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
182 for(j = 0; j < 16; j++) {
183 for(i = 0; i < 16; i++) {
185 if(s->selected == BRIGHTENING || s->selected == DIMMING) {
187 s->lastchange = time(NULL);
194 for(i = 0; i < 16; i++) {
199 s->lastchange = time(NULL);
204 /* Does AllLightsOn cancel selectedness of non-lights? */
205 for(i = 0; i < 16; i++) {
207 if(s->devcap & ISLIGHT) {
211 s->lastchange = time(NULL);
217 for(i = 0; i < 16; i++) {
219 if(s->selected == SELECTED) {
223 s->lastchange = time(NULL);
229 for(i = 0; i < 16; i++) {
231 if(s->selected == SELECTED) {
234 s->lastchange = time(NULL);
240 /* Does AllLightsOff cancel selectedness of non-lights? */
241 for(i = 0; i < 16; i++) {
243 if(s->devcap & ISLIGHT) {
246 s->lastchange = time(NULL);
254 for(i = 0; i < 16; i++) {
256 if(s->selected == SELECTED) {
257 s->selected = HAILED;
258 s->lastchange = time(NULL);
263 case HAILACKNOWLEDGE:
264 /* Do these commands cancel selection of devices not affected? */
265 for(i = 0; i < 16; i++) {
267 if(s->selected == HAILED) {
269 s->lastchange = time(NULL);
276 /* I don't really understand these */
277 for(i = 0; i < 16; i++) {
279 if(s->selected == SELECTED) {
281 s->lastchange = time(NULL);
287 /* Who knows? The TW523 can't receive these anyway. */
290 for(i = 0; i < 16; i++) {
292 if(s->selected == REQUESTED) {
295 s->lastchange = time(NULL);
301 for(i = 0; i < 16; i++) {
302 if(s->selected == REQUESTED) {
307 s->lastchange = time(NULL);
312 for(i = 0; i < 16; i++) {
315 s->selected = REQUESTED;
316 s->lastchange = time(NULL);