1 /*----------------------------------------------------------------------------+
2 | |
3 | Enhanced HEYU Functionality |
4 | |
5 | Enhancements copyright 2004-2008 Charles W. Sullivan |
6 | |
7 | Changes for use with CM11A copyright 1996, 1997 Daniel B. Suthers, |
8 | Pleasanton Ca, 94588 USA |
9 | |
10 | Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA |
11 | (maynard!campbell). |
12 | |
13 | John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted |
14 | by doing the System V port and adding some nice features. Thanks! |
15 | |
16 | |
17 | As used herein, HEYU is a trademark of Daniel B. Suthers. |
18 | X10, CM11A, and ActiveHome are trademarks of X-10 (USA) Inc. |
19 | The author is not affiliated with either entity. |
20 | |
21 | Charles W. Sullivan |
22 | Co-author and Maintainer |
23 | Greensboro, North Carolina |
24 | Email ID: cwsulliv01 |
25 | Email domain: -at- heyu -dot- org |
26 | |
27 +----------------------------------------------------------------------------*/
28
29 /*
30 * This program is free software: you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation, either version 3 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License
41 * along with this program. If not, see <http://www.gnu.org/licenses/>.
42 *
43 */
44
45 #include <stdio.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <unistd.h>
49 #include <ctype.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #if defined(SYSV) || defined(FREEBSD) || defined(OPENBSD)
53 #include <string.h>
54 #else
55 #include <strings.h>
56 #endif
57 #include <time.h>
58 #include <signal.h>
59 #include "x10.h"
60 #include <syslog.h>
61 #include "process.h"
62 #include "x10state.h"
63 #include "oregon.h"
64
65 #ifdef __GLIBC__
66 /* msf - added for glibc/rh 5.0 */
67 #include <sys/types.h>
68 #endif
69
70 extern int sptty;
71
72 extern CONFIG config;
73 extern CONFIG *configp;
74
75 extern struct x10global_st x10global;
76 extern x10hcode_t *x10state;
77
78 extern int i_am_monitor, i_am_state, i_am_rfxmeter;
79 extern int verbose;
80
81 extern int xread(int, unsigned char *, int, int);
82
83 extern int is_ring ( void );
84 extern int reread_config ( void );
85
86 unsigned char bootflag = R_NOTATSTART;
87
88 /*----------------------------------------------------------------------------+
89 | Determine the maximum number of bytes for a received function available in |
90 | the buffer. Arguments lenbyte and fmapbyte are the first two bytes from |
91 | the buffer, representing the length of the buffer and a bitmapped function |
92 | indicator. The return value is determined by the lesser the length of the |
93 | buffer or the distance to the next indicated function from the function |
94 | indicator byte. |
95 +----------------------------------------------------------------------------*/
max_funclen(unsigned char lenbyte,unsigned char fmapbyte,int pos)96 int max_funclen ( unsigned char lenbyte, unsigned char fmapbyte, int pos )
97 {
98 int k, maxlen;
99
100 if ( !(fmapbyte & (1 << pos)) || lenbyte > 9 )
101 return 0;
102
103 maxlen = 1;
104 for ( k = pos + 1; k < (int)(lenbyte - 1); k++ ) {
105 if ( !(fmapbyte & (1 << k)) )
106 maxlen++;
107 else
108 break;
109 }
110 return maxlen;
111 }
112
113
114 /*
115 * The CM11A sends data back to the computer whenever it sees a command
116 * come in over the AC buss. This should (theoretically) allow the compuer
117 * to track the status of all modules. Upon startup, this program should
118 * check for a poll before anything else.
119 *
120 * Check for a poll (0x5a) from the CM11A, If we get one within a
121 * second, we should send 0xc3 to tell it that we are ready to read
122 * it's output.
123 *
124 * If the showdata flag is set, we print. Otherwise we just eat the output.
125 */
126
127
128 extern char *datstrf(void);
129 unsigned int signal_source;
130 extern FILE *fdsout;
131 extern FILE *fdserr;
132 extern FILE *fprfxo;
133 extern FILE *fprfxe;
134
check4poll(int showdata,int timeout)135 int check4poll( int showdata, int timeout )
136 {
137 static int lastunit;
138 static char lasthc = '_';
139 int temperat, fdata;
140 int n, i, j;
141 int to_read;
142 char hc;
143 unsigned char predim, xcmd, xtype, xdata, subunit;
144 int unit;
145 int macro_report;
146 char *func;
147 int funcbits;
148 static int wasflag = 0;
149 unsigned char buf[128];
150 char outbuf[256];
151 unsigned char snochange;
152 extern char *b2s();
153 off_t f_offset;
154 unsigned int mac_addr, bitmap;
155 extern void acknowledge_hail();
156 extern int special_func;
157 extern int display_expanded_macro();
158 int ichksum;
159 int identify_sent(unsigned char *, int, unsigned char *);
160 char *translate_other(unsigned char *, int, unsigned char *);
161 extern char *translate_sent(unsigned char *, int, int *);
162 extern char *translate_rf_sent(unsigned char *, int *);
163 #if 0
164 extern int find_powerfail_launcher( unsigned char );
165 extern int find_rfflood_launcher( void );
166 extern int find_lockup_launcher( void );
167 #endif
168 extern int find_powerfail_scripts ( unsigned char );
169 extern int find_rfflood_scripts ( void );
170 extern int find_lockup_scripts ( void );
171
172 extern int set_globsec_flags( unsigned char );
173 extern char *display_armed_status ( void );
174 extern int clear_tamper_flags ( void );
175 extern int engine_local_setup ( int );
176 extern char *translate_rfxtype_message ( unsigned char * );
177 extern char *translate_rfxsensor_ident ( unsigned char * );
178 extern char *display_variable_aux_data ( unsigned char * );
179 extern int set_counter ( int, unsigned short, unsigned char );
180 extern char *translate_counter_action ( unsigned char * );
181 extern char *translate_kaku ( unsigned char *, unsigned char *, int * );
182 extern char *translate_visonic ( unsigned char *, unsigned char *, int * );
183 extern char *display_binbuffer ( unsigned char * );
184 int launch_script_cmd ( unsigned char * );
185 int launchp = -1;
186 char maclabel[MACRO_LEN + 1];
187 int macfound;
188 unsigned int squelch;
189 unsigned char hcode;
190
191 static int chksum_alert = -1;
192 extern char *funclabel[18];
193 static unsigned char newbuf[8], hexaddr = 0;
194 static char *send_prefix = "sndc";
195 static unsigned char waitflag = 0;
196
197 int sent_type;
198 unsigned char tag;
199 int maxlen;
200 unsigned char level;
201 static unsigned char defer_dim;
202 char minibuf[32];
203 char *transp;
204 mode_t oldumask;
205 char *sp;
206
207
208
209 static char *rcs_status[] = {
210 "System_mode = OFF", "System_mode = HEAT", "System_mode = COOL", "System_mode = AUTO",
211 "Fan = ON", "Fan = OFF", "Setback = ON", "Setback = OFF", "Temp Change", "Setpoint Change",
212 "Outside Temp", "Heat Setpoint", "Cooling Setpoint",
213 };
214 static unsigned int source_type[] = {SNDC, SNDS, SNDP, SNDA, RCVA};
215 static char *source_name[] = {"sndc", "snds", "sndp", "snda", "rcva"};
216
217 if ( i_am_state ) {
218 /* Redirect output to the Heyu log file */
219 oldumask = umask((mode_t)configp->log_umask);
220 fdsout = freopen(configp->logfile, "a", stdout);
221 fdserr = freopen(configp->logfile, "a", stderr);
222 umask(oldumask);
223 }
224
225 /* Note: When invoked as the normal 'heyu monitor' (i_am_monitor), */
226 /* fdsout and fdserr will have been set to stdout and stderr. */
227 /* But when invoked as 'heyu monitor rfxmeter' (i_am_rfxmeter), */
228 /* they will have been redirected to /dev/null so the only output */
229 /* to that xterm will be RFXMeter data via file pointer fprfxo. */
230
231 unit = -1;
232 hc = '\0';
233 func = "" ;
234
235 if ( timeout == 0 ) { /* only do a read if there is data */
236 if( sptty < 0 ) {
237 return 0;
238 }
239 f_offset = lseek(sptty, 0, SEEK_CUR);
240 if ( f_offset == lseek(sptty, 0, SEEK_END) ) {
241 return 0;
242 }
243 lseek(sptty, f_offset, SEEK_SET);
244 timeout = 1;
245 }
246
247
248 n = xread(sptty, buf, 1, timeout);
249 if ( n != 0 ) {
250 /* Three 0xff bytes in a row indicate that I sent a transmission to
251 * the CM11, I.E a command. The byte following the 3 0xFF bytes
252 * indicates how long the sent command was. We need to suck these
253 * off the stack if we are monitoring.
254 */
255 while ( buf[0] == 0xff ) { /* CM11A may be responding to a transmission */
256 if ( ++wasflag == 3 ) {
257 wasflag = 0;
258 n = xread(sptty, buf, 1, timeout); /* length of xmit */
259 if( n != 1 ) {
260 return(0);
261 }
262 if ( buf[0] == 0xff && chksum_alert == 0xff ) {
263 /*
264 * We have received four 0xff bytes in a row,
265 * looks like the first one was the checksum expected,
266 * so drop one of them and loop one more time.
267 */
268 chksum_alert = -1;
269 wasflag = 2;
270 continue;
271 }
272 n = buf[0];
273
274 if ( n < 127 ) {
275 unsigned char chksum;
276
277 n = xread(sptty, buf, n, timeout);
278
279 /* Identify the type of sent command from the leading */
280 /* byte and the length of the buffer. */
281 sent_type = identify_sent(buf, n, &chksum);
282
283 if ( sent_type == SENT_STCMD ) {
284 /* A command for the monitor/state process */
285 if ( buf[1] == ST_SOURCE ) {
286 signal_source = source_type[buf[2]];
287 send_prefix = source_name[buf[2]];
288 }
289 else if ( buf[1] == ST_TESTPOINT && i_am_monitor ) {
290 fprintf(fdsout, "%s Testpoint %d\n", datstrf(), buf[2]);
291 }
292 else if ( buf[1] == ST_LAUNCH && i_am_state ) {
293 configp->script_ctrl = buf[2];
294 fprintf(fdsout, "%s Scripts %s\n", datstrf(), (buf[2] == ENABLE ? "enabled" : "disabled"));
295 }
296 else if ( buf[1] == ST_INIT_ALL && i_am_state ) {
297 x10state_init_all();
298 write_x10state_file();
299 }
300 else if ( buf[1] == ST_INIT && i_am_state ) {
301 x10state_init_old(buf[2]);
302 write_x10state_file();
303 }
304 else if ( buf[1] == ST_INIT_OTHERS && i_am_state ) {
305 x10state_init_others();
306 write_x10state_file();
307 }
308 else if ( buf[1] == ST_WRITE && i_am_state ) {
309 write_x10state_file();
310 }
311 else if ( buf[1] == ST_EXIT && i_am_state ) {
312 write_x10state_file();
313 unlock_state_engine();
314 exit(0);
315 }
316 else if ( buf[1] == ST_RESETRF && (i_am_state || i_am_monitor) ) {
317 fprintf(fdsout, "%s Reset CM17A\n", datstrf());
318 }
319 else if ( buf[1] == ST_BUSYWAIT && (i_am_state || i_am_monitor) ) {
320 waitflag = buf[2];
321 if ( configp->auto_wait == 0 ) {
322 if ( waitflag > 0 )
323 fprintf(fdsout, "%s Wait macro completion.\n", datstrf());
324 else
325 fprintf(fdsout, "%s Wait timeout.\n", datstrf());
326 }
327 }
328 else if ( buf[1] == ST_CHKSUM ) {
329 chksum_alert = buf[2];
330 }
331 else if ( buf[1] == ST_REWIND ) {
332 for ( j = 0; j < 10; j++ ) {
333 if ( lseek(sptty, (off_t)0, SEEK_END) <= (off_t)(SPOOLFILE_ABSMIN/2) )
334 break;
335 sleep(1);
336 }
337 fprintf(fdsout, "%s Spoolfile exceeded max size and was rewound.\n", datstrf());
338 }
339 else if ( buf[1] == ST_SHOWBYTE && (i_am_state || i_am_monitor) ) {
340 fprintf(fdsout, "%s Byte value = 0x%02x\n", datstrf(), buf[2]);
341 }
342 else if ( buf[1] == ST_RESTART && (i_am_state || i_am_monitor || i_am_rfxmeter) ) {
343 reread_config();
344 if ( i_am_state ) {
345 syslog(LOG_ERR, "engine reconfiguration-\n");
346 engine_local_setup(E_RESTART);
347 fprintf(fdsout, "%s Engine reconfiguration\n", datstrf());
348 fflush(fdsout);
349 // syslog(LOG_ERR, "engine reconfiguration-\n");
350 }
351 else if ( i_am_rfxmeter ) {
352 fprintf(fprfxo, "RFXMeter monitor reconfiguration\n");
353 fflush(fprfxo);
354 }
355 else {
356 fprintf(fdsout, "%s Monitor reconfiguration\n", datstrf());
357 fflush(fdsout);
358 }
359 }
360 else if ( buf[1] == ST_SECFLAGS && (i_am_state || i_am_monitor)) {
361 if ( buf[2] != 0 ) {
362 warn_zone_faults(fdsout, datstrf());
363 }
364 set_globsec_flags(buf[2]);
365 write_x10state_file();
366 fprintf(fdsout, "%s %s\n", datstrf(), display_armed_status());
367 fflush(fdsout);
368 }
369 else if ( buf[1] == ST_CLRTIMERS && (i_am_state || i_am_monitor)) {
370 reset_user_timers();
371 write_x10state_file();
372 fprintf(fdsout, "%s Reset timers 1-16\n", datstrf());
373 fflush(fdsout);
374 }
375 else if ( buf[1] == ST_CLRTAMPER && (i_am_state || i_am_monitor)) {
376 clear_tamper_flags();
377 write_x10state_file();
378 fprintf(fdsout, "%s Clear tamper flags\n", datstrf());
379 fflush(fdsout);
380 }
381 }
382 else if ( sent_type == SENT_WRMI ) {
383 /* WRMI - Ignore */
384 }
385 else if ( sent_type == SENT_ADDR ) {
386 /* An address */
387 if ( *(transp = translate_sent(buf, n, &launchp)) )
388 fprintf(fdsout, "%s %s %s\n", datstrf(), send_prefix, transp);
389 if (signal_source != RCVA)
390 chksum_alert = chksum;
391 if ( launchp >= 0 && i_am_state) {
392 launch_scripts(&launchp);
393 }
394 }
395 else if ( sent_type == SENT_FUNC ) {
396 /* Standard function */
397 if ( *(transp = translate_sent(buf, n, &launchp)) )
398 fprintf(fdsout, "%s %s %s\n", datstrf(), send_prefix, transp);
399 if (signal_source != RCVA)
400 chksum_alert = chksum;
401 if ( launchp >= 0 && i_am_state) {
402 launch_scripts(&launchp);
403 }
404 }
405 else if ( sent_type == SENT_EXTFUNC ) {
406 /* Extended function */
407 if ( *(transp = translate_sent(buf, n, &launchp)) )
408 fprintf(fdsout,"%s %s %s\n", datstrf(), send_prefix, transp);
409 chksum_alert = chksum;
410 if ( launchp >= 0 && i_am_state) {
411 launch_scripts(&launchp);
412 }
413 }
414 else if ( sent_type == SENT_RF ) {
415 /* CM17A command */
416 fprintf(fdsout,"%s %s %s\n", datstrf(), "xmtf", translate_rf_sent(buf, &launchp));
417 if ( launchp >= 0 && i_am_state ) {
418 launch_scripts(&launchp);
419 }
420 }
421 else if ( sent_type == SENT_FLAGS && i_am_state ) {
422 update_flags(buf);
423 write_x10state_file();
424 }
425 else if ( sent_type == SENT_FLAGS32 && i_am_state ) {
426 update_flags_32(buf);
427 write_x10state_file();
428 }
429 else if ( sent_type == SENT_VDATA ) {
430 strcpy(outbuf, translate_virtual(buf, 9 /*8*/, &snochange, &launchp));
431 if ( *outbuf && !(snochange && config.hide_unchanged == YES && launchp < 0) )
432 fprintf(fdsout,"%s %s %s\n", datstrf(), send_prefix, outbuf);
433 if ( i_am_state && launchp >= 0 ) {
434 launch_scripts(&launchp);
435 }
436 }
437 else if ( sent_type == SENT_GENLONG ) {
438 strcpy(outbuf, translate_gen_longdata(buf, &snochange, &launchp));
439 if ( *outbuf && !(snochange && config.hide_unchanged == YES && launchp < 0) )
440 fprintf(fdsout,"%s %s %s\n", datstrf(), send_prefix, outbuf);
441 if ( i_am_state && launchp >= 0 ) {
442 launch_scripts(&launchp);
443 }
444 }
445 else if ( sent_type == SENT_ORE_EMU ) {
446 strcpy(outbuf, translate_ore_emu(buf, &snochange, &launchp));
447 if ( *outbuf && !(snochange && config.hide_unchanged == YES && launchp < 0) )
448 fprintf(fdsout,"%s %s %s\n", datstrf(), send_prefix, outbuf);
449 if ( i_am_state && launchp >= 0 ) {
450 launch_scripts(&launchp);
451 }
452 }
453 else if ( sent_type == SENT_KAKU ) {
454 strcpy(outbuf, translate_kaku(buf, &snochange, &launchp));
455 if ( *outbuf && !(snochange && config.hide_unchanged == YES && launchp < 0) )
456 fprintf(fdsout,"%s", outbuf);
457 if ( i_am_state && launchp >= 0 ) {
458 launch_scripts(&launchp);
459 }
460 }
461 else if ( sent_type == SENT_VISONIC ) {
462 strcpy(outbuf, translate_visonic(buf, &snochange, &launchp));
463 if ( *outbuf && !(snochange && config.hide_unchanged == YES && launchp < 0) )
464 fprintf(fdsout,"%s", outbuf);
465 if ( i_am_state && launchp >= 0 ) {
466 launch_scripts(&launchp);
467 }
468 }
469 else if ( sent_type == SENT_LONGVDATA ) {
470 if ( i_am_rfxmeter ) {
471 /* This and only this data gets sent to the special */
472 /* 'heyu monitor rfxmeter' window */
473 strcpy(outbuf, translate_long_virtual(buf, &snochange, &launchp) );
474 if ( (sp = strchr(outbuf, '\n')) != NULL )
475 *sp = '\0';
476 fprintf(fprfxo, "%s\n", outbuf);
477 fflush(fprfxo);
478 }
479 else {
480 /* This and all other data are not sent to the rfxmeter window */
481 strcpy(outbuf, translate_long_virtual(buf, &snochange, &launchp) );
482 if ( *outbuf && !(snochange && config.hide_unchanged == YES && launchp < 0) ) {
483 if ( (sp = strchr(outbuf, '\n')) != NULL ) {
484 *sp = '\0';
485 fprintf(fdsout,"%s %s %s\n", datstrf(), send_prefix, outbuf);
486 fprintf(fdsout,"%s %s\n", datstrf(), sp + 1);
487 }
488 else {
489 fprintf(fdsout,"%s %s %s\n", datstrf(), send_prefix, outbuf);
490 }
491 }
492 if ( i_am_state && launchp >= 0 ) {
493 launch_scripts(&launchp);
494 }
495 }
496 }
497 else if ( sent_type == SENT_COUNTER && (i_am_state || i_am_monitor)) {
498 set_counter(buf[2] | (buf[3] << 8), buf[4] | (buf[5] << 8), buf[6]);
499 write_x10state_file();
500 fprintf(fdsout, "%s %s\n", datstrf(), translate_counter_action(buf));
501 fflush(fdsout);
502 }
503 else if ( sent_type == SENT_CLRSTATUS && i_am_state ) {
504 clear_statusflags(buf[2], (buf[3] << 8 | buf[4]));
505 write_x10state_file();
506 }
507 else if ( sent_type == SENT_MESSAGE && (i_am_monitor || i_am_state) ) {
508 fprintf(fdsout, "%s %s\n", datstrf(), buf + 3);
509 }
510 else if ( sent_type == SENT_PFAIL && (i_am_state || i_am_monitor) ) {
511 bootflag = buf[2];
512 if ( bootflag & R_ATSTART )
513 fprintf(fdsout, "%s Powerfail signal received at startup.\n", datstrf());
514 else
515 fprintf(fdsout, "%s Powerfail signal received.\n", datstrf());
516 if ( i_am_state && (launchp = find_powerfail_scripts(bootflag)) >= 0 )
517 launch_scripts(&launchp);
518 }
519 else if ( sent_type == SENT_RFFLOOD && (i_am_state || i_am_monitor) ) {
520 fprintf(fdsout, "%s RF_Flood signal received.\n", datstrf());
521 if ( i_am_state && (launchp = find_rfflood_scripts()) >= 0 )
522 launch_scripts(&launchp);
523 }
524 else if ( sent_type == SENT_LOCKUP && (i_am_state || i_am_monitor) ) {
525 fprintf(fdsout, "%s Interface lockup signal received, reason %02x.\n", datstrf(), buf[2]);
526 if ( i_am_state && (launchp = find_lockup_scripts()) >= 0 )
527 launch_scripts(&launchp);
528 }
529 else if ( sent_type == SENT_SETTIMER && (i_am_state || i_am_monitor) ) {
530 fprintf(fdsout, "%s %s\n", datstrf(), translate_settimer_message(buf));
531 // if ( i_am_state )
532 // write_x10state_file();
533 }
534 else if ( sent_type == SENT_RFXTYPE && (i_am_state || i_am_monitor) ) {
535 fprintf(fdsout, "%s %s %s\n", datstrf(), send_prefix, translate_rfxtype_message(buf));
536 }
537 else if ( sent_type == SENT_RFXSERIAL && (i_am_state || i_am_monitor) ) {
538 fprintf(fdsout, "%s %s %s\n", datstrf(), send_prefix, translate_rfxsensor_ident(buf));
539 }
540 else if ( sent_type == SENT_RFVARIABLE && (i_am_state || i_am_monitor) ) {
541 fprintf(fdsout, "%s %s %s\n", datstrf(), send_prefix, display_variable_aux_data(buf));
542 }
543 else if ( sent_type == SENT_SCRIPT && (i_am_state) ) {
544 launch_script_cmd(buf);
545 }
546 else if ( sent_type == SENT_INITSTATE && (i_am_state) ) {
547 x10state_init(buf[2], buf[3] | (buf[4] << 8));
548 }
549 else if ( sent_type == SENT_SHOWBUFFER && i_am_monitor ) {
550 fprintf(fdsout, "%s %s\n", datstrf(), display_binbuffer(buf + 2));
551 }
552 else if ( sent_type == SENT_OTHER ) {
553 /* Other command */
554 if ( *(transp = translate_other(buf, n, &chksum)) )
555 fprintf(fdsout, "%s %s\n", datstrf(), transp);
556 chksum_alert = chksum;
557 launchp = -1;
558 }
559
560 }
561 else {
562 n = xread(sptty, buf, n - 127, timeout);
563 }
564
565 fflush(fdsout);
566 return(0);
567 }
568 else
569 n = xread(sptty, buf, 1, timeout);
570
571 if( n != 1 ) {
572 return(0);
573 }
574
575 } /* end of while */
576
577
578 /* print out the saved 0xff from the buffer */
579 if ( buf[0] != 0xff && wasflag > 0 ) {
580 if (chksum_alert == 0xff) {
581 /* a single 0xff was apparently a checksum */
582 chksum_alert = -1;
583 wasflag--;
584 }
585 n = buf[0];
586 for(i = 0; i < wasflag;i++)
587 buf[i] = 0xff;
588 buf[i] = n;
589 n = wasflag + 1;
590 wasflag = 0;
591 }
592
593 if ( buf[0] == chksum_alert ) {
594 /* this is the checksum expected, just drop it */
595 chksum_alert = -1;
596 return 0;
597 }
598
599 if (chksum_alert >= 0) {
600 /*
601 * Instead of the checksum expected, we've received something else.
602 * Don't expect that checksum to appear any longer. Either the
603 * interface didn't respond with a checksum, busy with an incomming
604 * transmission or a macro, or we are completely out of sync.
605 */
606 chksum_alert = -1;
607 }
608
609 macro_report = 0;
610 if ( buf[0] == 0x5a ) {
611 /* CM11A has polling info for me */
612 /* The xread is executed a second time on failure because the
613 dim commands may be tieing up the CM11.
614 */
615 n = xread(sptty, buf, 1, 2); /* get the buffer size */
616 if ( n == 0)
617 n = xread(sptty, buf, 1, 2); /* get the buffer size */
618
619 if ( n > 0 ) {
620 /* We have a byte count */
621 to_read = buf[0]; /* number of bytes to read */
622 if ( to_read == 0x5a ) {
623 /* Darn. Another polling indicator */
624 timeout = 2;
625 return ( check4poll(showdata, timeout) );
626 }
627 else if ( to_read == 0x5b ) { /* Macro report coming in */
628 to_read = 2;
629 macro_report = 1;
630 }
631
632 if ( to_read > (int)sizeof(buf) ) {
633 if( verbose )
634 fprintf(fdserr, "Polling read size exceeds buffer");
635 return(-1);
636 }
637
638 n = xread(sptty, buf, to_read , timeout);
639 if ( n != to_read ) {
640 fprintf(fdsout, "Poll only got %d of %d bytes\n",
641 n, to_read);
642 fflush(fdsout);
643 return 0;
644 }
645
646 if ( showdata > 0 && (verbose != 0) )
647 fprintf(fdsout, "I received a poll %d bytes long.\n", n);
648
649 if ( macro_report == 1 ) { /* CM11A is reporting a macro execution.*/
650 if ( showdata ) {
651 mac_addr = ((buf[0] & 0x07u) << 8) + buf[1];
652 /* Get macro label (or "Unknown") and saved image checksum */
653 macfound = lookup_macro(mac_addr, maclabel, &ichksum);
654
655 if ( buf[0] & 0x70u ) {
656 /* Macro was executed by a Trigger */
657 if ( macfound == 1 && ichksum != -1 && loadcheck_image(ichksum) ) {
658
659 /* Determine and display the inferred trigger. */
660 /* Launch a script if warranted. */
661 signal_source = RCVT;
662 tag = (buf[0] & 0x70u) >> 4;
663 display_trigger(datstrf(), mac_addr, tag);
664
665 /* Announce the execution of the macro */
666 fprintf(fdsout, "%s Trigger executed macro : %s, address 0x%03x\n",
667 datstrf(), maclabel, mac_addr);
668
669 /* Decipher and display macro elements from image file. */
670 /* Launch script(s) when warranted. */
671 signal_source = SNDT;
672 expand_macro(datstrf(), mac_addr, TRIGGER_EXEC);
673 }
674 else {
675 fprintf(fdsout, "%s Trigger executed macro : %s, address 0x%03x\n",
676 datstrf(), maclabel, mac_addr);
677 }
678 }
679 else {
680 /* Macro was executed by a Timer */
681 set_macro_timestamp(time(NULL));
682 if ( macfound == 1 && ichksum != -1 && loadcheck_image(ichksum) ) {
683 fprintf(fdsout, "%s Timer executed macro : %s, address 0x%03x\n",
684 datstrf(), maclabel, mac_addr);
685 /* Decipher and display macro elements from image file. */
686 /* Launch script(s) when warranted. */
687 signal_source = SNDM;
688 expand_macro(datstrf(), mac_addr, TIMER_EXEC);
689 }
690 else {
691 fprintf(fdsout, "%s Timer executed macro : %s, address 0x%03x\n",
692 datstrf(), maclabel, mac_addr);
693 }
694 }
695 }
696 }
697 else {
698 signal_source = RCVI;
699 #if 0
700 if ( showdata ) {
701 for ( i = 1; i < to_read; i++)
702 fprintf(fdsout, " %02x", buf[i]);
703 fprintf(fdsout, "\n");
704 }
705 #endif
706
707
708 for ( i = 1; i < to_read; i++) {
709 xcmd = xdata = subunit = predim = level = 0;
710
711 if ( defer_dim &&
712 ( (funcbits = (newbuf[0] & 0x0Fu)) == DIM || funcbits == BRIGHT) ) {
713 /* Finish handling a deferred Dim or Bright function */
714 newbuf[1] = buf[i];
715 signal_source = RCVI;
716 x10state_update_func(newbuf, &launchp);
717 hc = code2hc((newbuf[0] & 0xF0u) >> 4);
718 level = buf[i];
719 defer_dim = 0;
720 newbuf[0] = 0;
721 if( showdata ) {
722 fprintf(fdsout, "%s rcvi func %12s : hc %c %s %%%02.0f [%d]\n",
723 datstrf(), funclabel[funcbits], hc,
724 ((funcbits == DIM) ? "dim" : "bright"),
725 100.*(float)level/210., level);
726 }
727 }
728 else if ( (buf[0] & (0x01 << (i-1))) != 0) {
729 /* A function has been received */
730 signal_source = RCVI;
731
732 /* Determine the maximum number of bytes */
733 /* available in the buffer for the function */
734 maxlen = max_funclen(to_read, buf[0], (i-1));
735
736 hc = code2hc( ((buf[i] & 0xF0u) >> 4) );
737 funcbits = buf[i] & 0x0Fu;
738 func = funclabel[buf[i] & 0x0Fu];
739
740 if ( funcbits == DIM || funcbits == BRIGHT ) {
741 if ( maxlen > 1 ) {
742 /* We have the dim level - handle it here */
743 x10state_update_func(buf + i, &launchp);
744 level = buf[i+1];
745 defer_dim = 0;
746 i++;
747 }
748 else {
749 /* Otherwise, defer until we've got the dim level */
750 newbuf[0] = buf[i];
751 defer_dim = 1;
752 }
753 }
754 else if ( funcbits == PRESET1 || funcbits == PRESET2) {
755 func = "Preset";
756 x10state_update_func(buf + i, &launchp);
757
758 predim = rev_low_nybble((buf[i] & 0xF0u) >> 4) + 1;
759
760 if ( funcbits == PRESET2 )
761 predim += 16;
762
763 fdata = predim;
764 }
765 else if ( funcbits == EXTCODE ) {
766 if ( maxlen >= 4 ) {
767 /* Buffer looks OK. (Sometimes it gets */
768 /* garbled when ext code functions are */
769 /* received by a firmware 1 interface.) */
770 unit = code2unit(buf[i+1] & 0x0fu);
771 subunit = (buf[i+1] & 0xf0u) >> 4;
772 bitmap = 1 << (buf[i+1] & 0x0fu);
773 xdata = buf[i+2];
774 xcmd = buf[i+3];
775 xtype = (xcmd & 0xf0u) >> 4;
776 if ( xtype == 3 ) {
777 x10state_update_ext3func(buf + i, &launchp);
778 }
779 #ifdef HASEXT0
780 else if ( xtype == 0 ) {
781 x10state_update_ext0func(buf + i, &launchp);
782 }
783 #endif
784 else {
785 x10state_update_extotherfunc(buf + i, &launchp);
786 }
787 i += 3;
788 }
789 else {
790 /* Garbled buffer - dump it */
791 unit = 0;
792 bitmap = 0;
793 xdata = 0;
794 xcmd = 0xff;
795 i = to_read;
796 }
797 }
798 else {
799 x10state_update_func(buf + i, &launchp);
800 }
801
802
803 if ( showdata ) {
804
805 hcode = hc2code(hc);
806 squelch = x10state[hcode].squelch;
807 if ( squelch != 0 && (x10state[hcode].lastactive & squelch) == 0 ) {
808 fprintf(fdsout, "%s rcvi addr unit %3d : hu %c%-2d (%s)\n",
809 datstrf(), code2unit(single_bmap_unit(squelch)),
810 hc, code2unit(single_bmap_unit(squelch)), lookup_label(hc, squelch) );
811 x10state[hcode].squelch = squelch = 0;
812 }
813 else if ( squelch != 0 && ((squelch & x10state[hcode].state[ChgState]) || launchp >= 0) ) {
814 fprintf(fdsout, "%s rcvi addr unit %3d : hu %c%-2d (%s)\n",
815 datstrf(), code2unit(single_bmap_unit(squelch)),
816 hc, code2unit(single_bmap_unit(squelch)), lookup_label(hc, squelch) );
817 x10state[hcode].squelch = squelch = 0;
818 }
819
820
821
822 if ( (funcbits == DIM || funcbits == BRIGHT) && squelch == 0 ) {
823 if ( !defer_dim )
824 fprintf(fdsout, "%s rcvi func %12s : hc %c %s %%%02.0f [%d]\n",
825 datstrf(), funclabel[funcbits], toupper((int)hc),
826 ((funcbits == DIM) ? "dim" : "bright"),
827 100.*(float)level/210., level);
828 }
829 else if ( (funcbits == PRESET1 || funcbits == PRESET2) && squelch == 0 ) {
830 fprintf(fdsout, "%s rcvi func %12s : level %d\n",
831 datstrf(), func, predim);
832 if ( i_am_monitor &&
833 configp->rcs_temperature & (1 << hc2code(lasthc)) ) {
834 /* Special funcs for RCS compatible thermometers */
835 if ( lastunit > 10 ) {
836 temperat = -60 + (predim - 1) + 32 * (lastunit - 11);
837 sprintf(minibuf, "Temperature = %d", temperat);
838 fprintf(fdsout, "%s %-22s : hu %c0 (%s)\n",
839 datstrf(), minibuf, toupper((int)lasthc), lookup_label(lasthc, 0));
840 }
841 else if ( lastunit == 6 && predim < sizeof(rcs_status) / sizeof(*rcs_status) + 1 ) {
842 fprintf(fdsout, "%s %-22s : hu %c0 (%s)\n",
843 datstrf(), rcs_status[predim - 1], toupper((int)lasthc),
844 lookup_label(lasthc, 0));
845 }
846 }
847 }
848 else if ( funcbits == EXTCODE && squelch == 0 ) {
849 char tmp[10], stmp[16];
850 sprintf(tmp, "%d", unit);
851 bitmap = 1 << unit2code(unit);
852 if ( subunit == 0 )
853 stmp[0] = '\0';
854 else
855 sprintf(stmp, " subunit %02d", subunit);
856
857 if ( xcmd == 0x31 ) {
858 if ( xdata & 0xc0u ) {
859 fprintf(fdsout,
860 "%s rcvi func xPreset : hu %c%-2d%s level %d ramp %d (%s)\n",
861 datstrf(), hc, unit, stmp, xdata & 0x3f, (xdata & 0xc0) >> 6,
862 lookup_label(hc, bitmap));
863 }
864 else {
865 fprintf(fdsout,
866 "%s rcvi func xPreset : hu %c%-2d%s level %d (%s)\n",
867 datstrf(), hc, unit, stmp, xdata, lookup_label(hc, bitmap));
868 }
869 }
870 else if ( xcmd == 0x3b )
871 fprintf(fdsout, "%s rcvi func xConfig : hc %c mode=%d\n",
872 datstrf(), hc, xdata);
873 else if ( xcmd == 0x33 )
874 fprintf(fdsout, "%s rcvi func xAllOn : hc %c\n",
875 datstrf(), hc);
876 else if ( xcmd == 0x34 )
877 fprintf(fdsout, "%s rcvi func xAllOff : hc %c\n",
878 datstrf(), hc);
879 else if ( xcmd == 0x37 ) {
880 if ( (xdata & 0x30u) == 0 ) {
881 fprintf(fdsout, "%s rcvi func xStatusReq : hu %c%-2d%s (%s)\n",
882 datstrf(), hc, unit, stmp, lookup_label(hc, bitmap));
883 }
884 else if ( (xdata & 0x30u) == 0x10 ) {
885 fprintf(fdsout, "%s rcvi func xPowerUp : hu %c%-2d%s (%s)\n",
886 datstrf(), hc, unit, stmp, lookup_label(hc, bitmap));
887 }
888 else if ( (xdata & 0x30u) == 0x20 ) {
889 fprintf(fdsout, "%s rcvi func xGrpStatus : hu %c%-2d%s group %d (%s)\n",
890 datstrf(), hc, unit, stmp, (xdata & 0xc0u) >> 6, lookup_label(hc, bitmap));
891 }
892 else {
893 fprintf(fdsout, "%s rcvi func xGrpStatus : hu %c%-2d%s group %d.%-2d (%s)\n",
894 datstrf(), hc, unit, stmp, (xdata & 0xc0u) >> 6, (xdata & 0x0fu) + 1, lookup_label(hc, bitmap));
895 }
896 }
897 else if ( xcmd == 0x38 ) {
898 if ( xdata & 0x40u )
899 fprintf(fdsout, "%s rcvi func xStatusAck : hu %c%-2d%s Switch %-3s %s (%s)\n",
900 datstrf(), hc, unit, stmp, ((xdata & 0x3fu) ? "On " : "Off"),
901 ((xdata & 0x80u) ? "LoadOK" : "NoLoad"),
902 lookup_label(hc, bitmap));
903 else
904 fprintf(fdsout, "%s rcvi func xStatusAck : hu %c%-2d%s Lamp level %d, %s (%s)\n",
905 datstrf(), hc, unit, stmp, xdata & 0x3fu,
906 ((xdata & 0x80u) ? "BulbOK" : "NoBulb"),
907 lookup_label(hc, bitmap));
908 }
909 else if ( xcmd == 0x30 ) {
910 if ( (xdata & 0x20u) == 0 ) {
911 fprintf(fdsout, "%s rcvi func xGrpAdd : hu %c%-2d%s group %d (%s)\n",
912 datstrf(), hc, unit, stmp, (xdata & 0xc0u) >> 6, lookup_label(hc, bitmap));
913
914 }
915 else {
916 fprintf(fdsout, "%s rcvi func xGrpAdd : hu %c%-2d%s group %d.%-2d (%s)\n",
917 datstrf(), hc, unit, stmp, (xdata & 0xc0u) >> 6, (xdata & 0x0fu) + 1, lookup_label(hc, bitmap));
918 }
919 }
920 else if ( xcmd == 0x32 ) {
921 fprintf(fdsout, "%s rcvi func xGrpAddLvl : hu %c%-2d%s group %d level %d (%s)\n",
922 datstrf(), hc, unit, stmp, (xdata & 0xc0u) >> 6, xdata & 0x3fu, lookup_label(hc, bitmap));
923 }
924 else if ( xcmd == 0x35 ) {
925 if ( (xdata & 0x30) == 0 ) {
926 fprintf(fdsout, "%s rcvi func xGrpRem : hu %c%-2d%s group(s) %s (%s)\n",
927 datstrf(), hc, unit, stmp, linmap2list(xdata & 0x0f), lookup_label(hc, bitmap));
928 }
929 else {
930 fprintf(fdsout, "%s rcvi func xGrpRemAll : hc %c group(s) %s\n",
931 datstrf(), hc, linmap2list(xdata & 0x0f));
932
933 }
934 }
935 else if ( xcmd == 0x36 ) {
936 if ( (xdata & 0x30u) == 0 ) {
937 fprintf(fdsout, "%s rcvi func xGrpExec : hc %c group %d\n",
938 datstrf(), hc, (xdata & 0xc0u) >> 6);
939 }
940 else if ( (xdata & 0x30u) == 0x20u ) {
941 fprintf(fdsout, "%s rcvi func xGrpExec : hc %c group %d.%-2d\n",
942 datstrf(), hc, (xdata & 0xc0u) >> 6, (xdata & 0x0fu) + 1);
943 }
944 else if ( (xdata & 0x30u) == 0x10u ) {
945 fprintf(fdsout, "%s rcvi func xGrpOff : hc %c group %d\n",
946 datstrf(), hc, (xdata & 0xc0u) >> 6);
947 }
948 else {
949 fprintf(fdsout, "%s rcvi func xGrpOff : hc %c group %d.%-2d\n",
950 datstrf(), hc, (xdata & 0xc0u) >> 6, (xdata & 0x0fu) + 1);
951 }
952 }
953 else if ( xcmd == 0x39 ) {
954 fprintf(fdsout, "%s rcvi func xGrpAck : hu %c%-2d%s group %d level %d (%s)\n",
955 datstrf(), hc, unit, stmp, (xdata & 0xc0) >> 6, xdata & 0x3fu, lookup_label(hc, bitmap));
956 }
957 else if ( xcmd == 0x3A ) {
958 fprintf(fdsout, "%s rcvi func xGrpNack : hu %c%-2d%s group %d (%s)\n",
959 datstrf(), hc, unit, stmp, (xdata & 0xc0) >> 6, lookup_label(hc, bitmap));
960 }
961 else if ( xcmd == 0x3C ) {
962 if ( (xdata & 0x30u) == 0 ) {
963 fprintf(fdsout, "%s rcvi func xGrpDim : hc %c group %d\n",
964 datstrf(), hc, (xdata & 0xc0u) >> 6);
965 }
966 else if ( (xdata & 0x30u) == 0x10 ) {
967 fprintf(fdsout, "%s rcvi func xGrpBright : hc %c group %d\n",
968 datstrf(), hc, (xdata & 0xc0u) >> 6);
969 }
970 else if ( (xdata & 0x30u) == 0x20 ) {
971 fprintf(fdsout, "%s rcvi func xGrpDim : hc %c group %d.%-2d\n",
972 datstrf(), hc, (xdata & 0xc0u) >> 6, (xdata & 0x0fu) + 1);
973 }
974 else {
975 fprintf(fdsout, "%s rcvi func xGrpBright : hc %c group %d.%-2d\n",
976 datstrf(), hc, (xdata & 0xc0u) >> 6, (xdata & 0x0fu) + 1);
977 }
978
979 }
980 else if ( xcmd == 0x01 )
981 fprintf(fdsout, "%s rcvi func shOpenLim : hu %c%-2d%s level %d (%s)\n",
982 datstrf(), hc, unit, stmp, xdata, lookup_label(hc, bitmap));
983 else if ( xcmd == 0x03 )
984 fprintf(fdsout, "%s rcvi func shOpen : hu %c%-2d%s level %d (%s)\n",
985 datstrf(), hc, unit, stmp, xdata, lookup_label(hc, bitmap));
986 else if ( xcmd == 0x02 )
987 fprintf(fdsout, "%s rcvi func shSetLim : hu %c%-2d%s level %d (%s)\n",
988 datstrf(), hc, unit, stmp, xdata, lookup_label(hc, bitmap));
989 else if ( xcmd == 0x04 )
990 fprintf(fdsout, "%s rcvi func shOpenAll : hc %c\n",
991 datstrf(), hc);
992 else if ( xcmd == 0x0B )
993 fprintf(fdsout, "%s rcvi func shCloseAll : hc %c\n",
994 datstrf(), hc);
995
996 else if ( xcmd == 0xff )
997 fprintf(fdsout, "%s rcvi func ExtCode : Incomplete xcode in buffer.\n",
998 datstrf());
999 else {
1000 fprintf(fdsout, "%s rcvi func xFunc %02x : hu %c%-2d%s data=0x%02x (%s)\n",
1001 datstrf(), xcmd, hc, unit, stmp, xdata, lookup_label(hc, bitmap));
1002 }
1003 }
1004 else {
1005 hcode = hc2code(hc);
1006 squelch = x10state[hcode].squelch;
1007 if ( squelch == 0 ) {
1008 fprintf(fdsout, "%s rcvi func %12s : hc %c\n",
1009 datstrf(), func, hc);
1010 }
1011
1012 if ( funcbits == 8 && i_am_state && configp->ack_hails == YES ) {
1013 acknowledge_hail();
1014 }
1015 }
1016 x10state[hcode].squelch = 0;
1017
1018 }
1019
1020 if ( special_func > 0 ) {
1021 if( (funcbits == PRESET1 || funcbits == PRESET2) ) {
1022 if ( lastunit > 10 ) {
1023 temperat = -60 + (predim - 1) + 32 * (lastunit - 11);
1024 fprintf(fdsout, "%s Temperature = %-3d : hu %c0 (%s)\n",
1025 datstrf(), temperat, lasthc, lookup_label(lasthc, 0));
1026 }
1027 else if ( lastunit == 6 && predim < 9 ) {
1028 fprintf(fdsout, "%s %s : hu %c0 (%s)\n",
1029 datstrf(), rcs_status[predim - 1], toupper((int)lasthc),
1030 lookup_label(lasthc, 0));
1031 }
1032 }
1033 }
1034 }
1035 else {
1036 /* an address byte was received */
1037 signal_source = RCVI;
1038 hcode = (buf[i] & 0xF0u) >> 4;
1039 hc = code2hc(hcode);
1040 unit = code2unit( buf[i] & 0x0Fu) ;
1041 hexaddr = buf[i];
1042 bitmap = 1 << (buf[i] & 0x0fu);
1043 lasthc = hc;
1044 lastunit = unit;
1045 x10state_update_addr(buf[i], &launchp);
1046 x10state_update_sticky_addr(buf[i]);
1047
1048
1049 if ( showdata ) {
1050 squelch = x10state[hcode].squelch;
1051 if ( squelch == 0 ) {
1052 fprintf(fdsout, "%s rcvi addr unit %3d : hu %c%-2d (%s)\n",
1053 datstrf(), unit, hc, unit, lookup_label(hc, bitmap) );
1054 }
1055 else if ( squelch != 0 && squelch != bitmap ) {
1056 /* Different address - display deferred squelch address and cancel it */
1057 x10state[hcode].squelch = 0;
1058 fprintf(fdsout, "%s rcvi addr unit %3d : hu %c%-2d (%s)\n",
1059 datstrf(), code2unit(single_bmap_unit(squelch)), hc, code2unit(single_bmap_unit(squelch)), lookup_label(hc, squelch) );
1060 fprintf(fdsout, "%s rcvi addr unit %3d : hu %c%-2d (%s)\n",
1061 datstrf(), unit, hc, unit, lookup_label(hc, bitmap) );
1062 }
1063 }
1064 }
1065
1066 fflush(fdsout);
1067
1068 if ( launchp >= 0 && i_am_state) {
1069 launch_scripts(&launchp);
1070 }
1071 }
1072 fflush(fdsout);
1073 }
1074 }
1075 else {
1076 if (verbose)
1077 fprintf(fdsout, "%s Bytes received = %d; the interface didn't answer a getinfo response.\n", datstrf(), n);
1078 else
1079 fprintf(fdsout, "%s The interface didn't answer a getinfo response.\n", datstrf());
1080 }
1081 }
1082 else if ( buf[0] == 0xa5 && showdata ) {
1083 /* Device experienced an AC power interruption */
1084 if ( configp->device_type & DEV_CM10A )
1085 fprintf(fdsout, "%s CM10A experienced an AC power interruption. %s",
1086 datstrf(), "It requested a restart.\n");
1087 else
1088 fprintf(fdsout, "%s CM11A experienced an AC power interruption. %s",
1089 datstrf(), "It requested a time update.\n");
1090 }
1091 else if ( buf[0] == 0x5b ) {
1092 /* The CM11A is reporting a macro execution */
1093 to_read = 2;
1094 n = xread(sptty, buf, to_read, timeout);
1095 if ( showdata ) {
1096 mac_addr = ((buf[0] & 0x07u) << 8) + buf[1];
1097 /* Get macro label (or "Unknown") and saved image checksum */
1098 macfound = lookup_macro(mac_addr, maclabel, &ichksum);
1099
1100 if ( buf[0] & 0x70u ) {
1101 /* The macro was executed by a Trigger */
1102 if ( macfound == 1 && ichksum != -1 && loadcheck_image(ichksum) ) {
1103
1104 /* Determine and display the inferred trigger. */
1105 /* Launch script if warranted. */
1106 tag = (buf[0] & 0x70u) >> 4;
1107 signal_source = RCVT;
1108 display_trigger(datstrf(), mac_addr, tag);
1109
1110 /* Announce the execution of the macro */
1111 fprintf(fdsout, "%s Trigger executed macro : %s, address 0x%03x\n",
1112 datstrf(), maclabel, mac_addr);
1113
1114 /* Decipher and display macro elements from image file. */
1115 /* Launch script(s) if warranted. */
1116 signal_source = SNDT;
1117 expand_macro(datstrf(), mac_addr, TRIGGER_EXEC);
1118 }
1119 else {
1120 fprintf(fdsout, "%s Trigger executed macro : %s, address 0x%03x\n",
1121 datstrf(), maclabel, mac_addr);
1122 }
1123 }
1124 else {
1125 /* The macro was executed by a Timer */
1126 if ( macfound == 1 && ichksum != -1 && loadcheck_image(ichksum) ) {
1127
1128 /* Announce the execution of the macro */
1129 fprintf(fdsout, "%s Timer executed macro : %s, address 0x%03x\n",
1130 datstrf(), maclabel, mac_addr);
1131
1132 /* Decipher and display macro elements from image file */
1133 /* and launch script(s) if warranted. */
1134 signal_source = SNDM;
1135 expand_macro(datstrf(), mac_addr, TIMER_EXEC);
1136 }
1137 else {
1138 fprintf(fdsout, "%s Timer executed macro : %s, address 0x%03x\n",
1139 datstrf(), maclabel, mac_addr);
1140 }
1141 }
1142 }
1143 }
1144 else if ( buf[0] == ((configp->ring_ctrl == DISABLE) ? 0xdb : 0xeb) && waitflag ) {
1145 waitflag = 0;
1146 }
1147 else if ( !(buf[0] == 0x55 && n == 1) ) {
1148 /* There's some sort of timing problem with the 0x55 ("ready to */
1149 /* receive") signal from the interface after a long bright/dim */
1150 /* or extended command is sent. Ignore it, but alert to other */
1151 /* unknown values. */
1152 fprintf(fdsout,
1153 "%s Poll received unknown value (%d bytes), leading byte = %0x\n",
1154 datstrf(), n, buf[0]);
1155 }
1156
1157 fflush(fdsout);
1158 }
1159 return 0;
1160 }
1161
1162