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
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 $
40 char *X10housenames[] = {
41 "A", "B", "C", "D", "E", "F", "G", "H",
42 "I", "J", "K", "L", "M", "N", "O", "P",
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",
56 * Log a packet and update device status accordingly
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)");
73 * Process a received packet p, updating device status information both
74 * in core and on disk.
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.
92 if(k < 16) { /* We received a unit code, to select a particular device */
94 s->selected = SELECTED;
95 s->lastchange = time(NULL);
97 } else { /* We received a key code, to execute some function */
99 * Change in status depends on the key code received
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
112 for(i = 0; i < 16; i++) {
114 switch(s->selected) {
115 case SELECTED: /* Selected, but not being dimmed or brightened */
121 if(s->brightness < 0) s->brightness = 0;
122 s->selected = DIMMING;
123 s->lastchange = time(NULL);
126 case DIMMING: /* Selected and being dimmed */
128 if(s->brightness < 0) s->brightness = 0;
129 s->lastchange = time(NULL);
132 case BRIGHTENING: /* Selected and being brightened (an error) */
134 s->lastchange = time(NULL);
141 } else if(k == BRIGHT) {
143 * Same problem here...
145 for(i = 0; i < 16; i++) {
147 switch(s->selected) {
148 case SELECTED: /* Selected, but not being dimmed or brightened */
154 if(s->brightness > 15) s->brightness = 15;
155 s->selected = BRIGHTENING;
156 s->lastchange = time(NULL);
159 case DIMMING: /* Selected and being dimmed (an error) */
161 s->lastchange = time(NULL);
164 case BRIGHTENING: /* Selected and being brightened */
166 if(s->brightness > 15) s->brightness = 15;
167 s->lastchange = time(NULL);
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++) {
183 if(s->selected == BRIGHTENING || s->selected == DIMMING) {
185 s->lastchange = time(NULL);
192 for(i = 0; i < 16; i++) {
197 s->lastchange = time(NULL);
202 /* Does AllLightsOn cancel selectedness of non-lights? */
203 for(i = 0; i < 16; i++) {
205 if(s->devcap & ISLIGHT) {
209 s->lastchange = time(NULL);
215 for(i = 0; i < 16; i++) {
217 if(s->selected == SELECTED) {
221 s->lastchange = time(NULL);
227 for(i = 0; i < 16; i++) {
229 if(s->selected == SELECTED) {
232 s->lastchange = time(NULL);
238 /* Does AllLightsOff cancel selectedness of non-lights? */
239 for(i = 0; i < 16; i++) {
241 if(s->devcap & ISLIGHT) {
244 s->lastchange = time(NULL);
252 for(i = 0; i < 16; i++) {
254 if(s->selected == SELECTED) {
255 s->selected = HAILED;
256 s->lastchange = time(NULL);
261 case HAILACKNOWLEDGE:
262 /* Do these commands cancel selection of devices not affected? */
263 for(i = 0; i < 16; i++) {
265 if(s->selected == HAILED) {
267 s->lastchange = time(NULL);
274 /* I don't really understand these */
275 for(i = 0; i < 16; i++) {
277 if(s->selected == SELECTED) {
279 s->lastchange = time(NULL);
285 /* Who knows? The TW523 can't receive these anyway. */
288 for(i = 0; i < 16; i++) {
290 if(s->selected == REQUESTED) {
293 s->lastchange = time(NULL);
299 for(i = 0; i < 16; i++) {
300 if(s->selected == REQUESTED) {
305 s->lastchange = time(NULL);
310 for(i = 0; i < 16; i++) {
313 s->selected = REQUESTED;
314 s->lastchange = time(NULL);