Line data Source code
1 : /********************************************************************\
2 :
3 : Name: msc.c
4 : Created by: Stefan Ritt
5 :
6 : Contents: Command-line interface for the Midas Slow Control Bus
7 :
8 : $Id$
9 :
10 : \********************************************************************/
11 :
12 : #ifdef _MSC_VER
13 : #define OS_WINNT
14 : #endif
15 : #if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
16 : #define OS_LINUX
17 : #endif
18 :
19 : #ifdef OS_WINNT
20 :
21 : #include <windows.h>
22 : #include <conio.h>
23 : #include <io.h>
24 : #include <sys/timeb.h>
25 : #include <time.h>
26 :
27 : #elif defined(OS_LINUX)
28 :
29 : #define O_BINARY 0
30 :
31 : #include <unistd.h>
32 : #include <ctype.h>
33 : #include <sys/termios.h>
34 : #include <sys/time.h>
35 : #include <sys/types.h>
36 : #include <pthread.h>
37 :
38 : #endif
39 :
40 : #include "mscb.h"
41 : #include "mscbxx.h"
42 :
43 : #include <stdio.h>
44 : #include <assert.h>
45 : #include <string.h>
46 : #include <stdlib.h>
47 : #include <fcntl.h>
48 : #include <time.h>
49 : #include <sys/timeb.h>
50 : #include "mscbrpc.h"
51 : #include "mxml.h"
52 : #include "mstrlcpy.h"
53 :
54 : extern int cmd_edit(const char *prompt, char *cmd, int(*dir)(char *, int *), int(*idle)(void));
55 :
56 0 : int cmd_dir(char *line, int *cursor) {
57 0 : return FALSE;
58 : }
59 :
60 : /*------------------------------------------------------------------*/
61 :
62 : typedef struct {
63 : char id;
64 : char name[32];
65 : } NAME_TABLE;
66 :
67 : NAME_TABLE prefix_table[] = {
68 : {(char) PRFX_PICO, "pico",},
69 : {(char) PRFX_NANO, "nano",},
70 : {(char) PRFX_MICRO, "micro",},
71 : {(char) PRFX_MILLI, "milli",},
72 : {(char) PRFX_NONE, "",},
73 : {(char) PRFX_KILO, "kilo",},
74 : {(char) PRFX_MEGA, "mega",},
75 : {(char) PRFX_GIGA, "giga",},
76 : {(char) PRFX_TERA, "tera",},
77 : {(char) 99}
78 : };
79 :
80 : NAME_TABLE unit_table[] = {
81 :
82 : {UNIT_METER, "meter",},
83 : {UNIT_GRAM, "gram",},
84 : {UNIT_SECOND, "second",},
85 : {UNIT_MINUTE, "minute",},
86 : {UNIT_HOUR, "hour",},
87 : {UNIT_AMPERE, "ampere",},
88 : {UNIT_KELVIN, "kelvin",},
89 : {UNIT_CELSIUS, "deg. celsius",},
90 : {UNIT_FARENHEIT, "deg. farenheit",},
91 : {UNIT_JOULE, "joule",},
92 : {UNIT_NEWTON, "newton",},
93 :
94 : {UNIT_HERTZ, "hertz",},
95 : {UNIT_PASCAL, "pascal",},
96 : {UNIT_BAR, "bar",},
97 : {UNIT_WATT, "watt",},
98 : {UNIT_VOLT, "volt",},
99 : {UNIT_OHM, "ohm",},
100 : {UNIT_TESLA, "tesls",},
101 : {UNIT_LITERPERSEC, "liter/sec",},
102 : {UNIT_RPM, "RPM",},
103 : {UNIT_FARAD, "farad",},
104 :
105 : {UNIT_BOOLEAN, "boolean",},
106 : {UNIT_BYTE, "byte",},
107 : {UNIT_WORD, "word",},
108 : {UNIT_DWORD, "dword",},
109 : {UNIT_ASCII, "ascii",},
110 : {UNIT_STRING, "string",},
111 : {UNIT_BAUD, "baud",},
112 :
113 : {UNIT_PERCENT, "percent",},
114 : {UNIT_PPM, "RPM",},
115 : {UNIT_COUNT, "counts",},
116 : {UNIT_FACTOR, "factor",},
117 : {UNIT_VOLTPERVOLT, "volt/volt",},
118 : {0}
119 : };
120 :
121 : /*------------------------------------------------------------------*/
122 :
123 : /* special characters */
124 : #define CH_BS 8
125 : #define CH_TAB 9
126 : #define CH_CR 13
127 :
128 : #define CH_EXT 0x100
129 :
130 : #define CH_HOME (CH_EXT+0)
131 : #define CH_INSERT (CH_EXT+1)
132 : #define CH_DELETE (CH_EXT+2)
133 : #define CH_END (CH_EXT+3)
134 : #define CH_PUP (CH_EXT+4)
135 : #define CH_PDOWN (CH_EXT+5)
136 : #define CH_UP (CH_EXT+6)
137 : #define CH_DOWN (CH_EXT+7)
138 : #define CH_RIGHT (CH_EXT+8)
139 : #define CH_LEFT (CH_EXT+9)
140 :
141 0 : int ss_getchar(int reset) {
142 : #ifdef OS_LINUX
143 :
144 : static int init = FALSE;
145 : static struct termios save_termios;
146 : struct termios buf;
147 : int i, fd;
148 : char c[3];
149 :
150 0 : fd = fileno(stdin);
151 :
152 0 : if (reset) {
153 0 : if (init)
154 0 : tcsetattr(fd, TCSAFLUSH, &save_termios);
155 0 : init = FALSE;
156 0 : return 0;
157 : }
158 :
159 0 : if (!init) {
160 0 : tcgetattr(fd, &save_termios);
161 0 : memcpy(&buf, &save_termios, sizeof(buf));
162 :
163 0 : buf.c_lflag &= ~(ECHO | ICANON | IEXTEN);
164 :
165 0 : buf.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON);
166 :
167 0 : buf.c_cflag &= ~(CSIZE | PARENB);
168 0 : buf.c_cflag |= CS8;
169 : /* buf.c_oflag &= ~(OPOST); */
170 0 : buf.c_cc[VMIN] = 0;
171 0 : buf.c_cc[VTIME] = 0;
172 :
173 0 : tcsetattr(fd, TCSAFLUSH, &buf);
174 0 : init = TRUE;
175 : }
176 :
177 0 : memset(c, 0, 3);
178 0 : i = read(fd, c, 1);
179 :
180 0 : if (i == 0) {
181 0 : Sleep(10);
182 0 : return 0;
183 : }
184 :
185 : /* check if ESC */
186 0 : if (c[0] == 27) {
187 0 : i = read(fd, c, 2);
188 0 : if (i == 0) /* return if only ESC */
189 0 : return 27;
190 :
191 : /* cursor keys return 2 chars, others 3 chars */
192 0 : if (c[1] < 65)
193 0 : read(fd, c, 1);
194 :
195 : /* convert ESC sequence to CH_xxx */
196 0 : switch (c[1]) {
197 0 : case 49:
198 0 : return CH_HOME;
199 0 : case 50:
200 0 : return CH_INSERT;
201 0 : case 51:
202 0 : return CH_DELETE;
203 0 : case 52:
204 0 : return CH_END;
205 0 : case 53:
206 0 : return CH_PUP;
207 0 : case 54:
208 0 : return CH_PDOWN;
209 0 : case 65:
210 0 : return CH_UP;
211 0 : case 66:
212 0 : return CH_DOWN;
213 0 : case 67:
214 0 : return CH_RIGHT;
215 0 : case 68:
216 0 : return CH_LEFT;
217 : }
218 : }
219 :
220 : /* BS/DEL -> BS */
221 0 : if (c[0] == 127)
222 0 : return CH_BS;
223 :
224 0 : return c[0];
225 :
226 : #elif defined(OS_WINNT)
227 :
228 : static BOOL init = FALSE;
229 : static INT repeat_count = 0;
230 : static INT repeat_char;
231 : HANDLE hConsole;
232 : DWORD nCharsRead;
233 : INPUT_RECORD ir;
234 :
235 : hConsole = GetStdHandle(STD_INPUT_HANDLE);
236 :
237 : if (reset) {
238 : SetConsoleMode(hConsole, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
239 : init = FALSE;
240 : return 0;
241 : }
242 :
243 : if (!init) {
244 : SetConsoleMode(hConsole, ENABLE_PROCESSED_INPUT);
245 : init = TRUE;
246 : }
247 :
248 : if (repeat_count) {
249 : repeat_count--;
250 : return repeat_char;
251 : }
252 :
253 : PeekConsoleInput(hConsole, &ir, 1, &nCharsRead);
254 :
255 : if (nCharsRead == 0)
256 : return 0;
257 :
258 : ReadConsoleInput(hConsole, &ir, 1, &nCharsRead);
259 :
260 : if (ir.EventType != KEY_EVENT)
261 : return ss_getchar(0);
262 :
263 : if (!ir.Event.KeyEvent.bKeyDown)
264 : return ss_getchar(0);
265 :
266 : if (ir.Event.KeyEvent.wRepeatCount > 1) {
267 : repeat_count = ir.Event.KeyEvent.wRepeatCount - 1;
268 : repeat_char = ir.Event.KeyEvent.uChar.AsciiChar;
269 : return repeat_char;
270 : }
271 :
272 : if (ir.Event.KeyEvent.uChar.AsciiChar)
273 : return ir.Event.KeyEvent.uChar.AsciiChar;
274 :
275 : if (ir.Event.KeyEvent.dwControlKeyState & (ENHANCED_KEY)) {
276 : switch (ir.Event.KeyEvent.wVirtualKeyCode) {
277 : case 33:
278 : return CH_PUP;
279 : case 34:
280 : return CH_PDOWN;
281 : case 35:
282 : return CH_END;
283 : case 36:
284 : return CH_HOME;
285 : case 37:
286 : return CH_LEFT;
287 : case 38:
288 : return CH_UP;
289 : case 39:
290 : return CH_RIGHT;
291 : case 40:
292 : return CH_DOWN;
293 : case 45:
294 : return CH_INSERT;
295 : case 46:
296 : return CH_DELETE;
297 : }
298 :
299 : return ir.Event.KeyEvent.wVirtualKeyCode;
300 : }
301 :
302 : return ss_getchar(0);
303 :
304 : #endif
305 : return -1;
306 : }
307 :
308 : /*------------------------------------------------------------------*/
309 :
310 0 : unsigned int ss_millitime() {
311 : #ifdef OS_WINNT
312 :
313 : return (int) GetTickCount();
314 :
315 : #endif /* OS_WINNT */
316 : #ifdef OS_LINUX
317 : {
318 : struct timeval tv;
319 :
320 0 : gettimeofday(&tv, NULL);
321 :
322 0 : return tv.tv_sec * 1000 + tv.tv_usec / 1000;
323 : }
324 :
325 : #endif /* OS_LINUX */
326 : return 0;
327 : }
328 :
329 : /*------------------------------------------------------------------*/
330 :
331 0 : char *ss_gets(char *string, int size) {
332 : char *p;
333 :
334 : do {
335 0 : p = fgets(string, size, stdin);
336 0 : } while (p == NULL);
337 :
338 :
339 0 : if (strlen(p) > 0 && p[strlen(p) - 1] == '\n')
340 0 : p[strlen(p) - 1] = 0;
341 :
342 0 : return p;
343 : }
344 :
345 : /*------------------------------------------------------------------*/
346 :
347 0 : void print_help() {
348 0 : puts("Available commands:\n");
349 0 : puts("addr <addr> Address individual node");
350 0 : puts("baddr Address all nodes (broadcast)");
351 0 : puts("baud Set baud rate of MSCB bus");
352 0 : puts("debug 0/1/2 Turn debuggin off/on, 2=show on screen");
353 0 : puts("echo [fc] Perform echo test [fast,continuous]");
354 0 : puts("flash Flash parameters into EEPROM");
355 0 : puts("gaddr <addr> Address group of nodes");
356 0 : puts("info Retrive node info");
357 0 : puts("load <file> Load node variables");
358 0 : puts("ping <addr> [r] Ping node and set address [repeat mode]");
359 0 : puts("read <index> [r] [a] Read node variable [repeat mode] [all variables]");
360 0 : puts("read <i1>-<i2> [r] [a] Read range of node variables [repeat] [all]");
361 0 : puts("reboot Reboot addressed node");
362 0 : puts("sa <addr> Set node address of addressed node");
363 0 : puts("save <file> [first last] Save current node variables [save range]");
364 0 : puts("scan [r] [a] [q] Scan bus for nodes [repeat mode] [all] [quick]");
365 0 : puts("sg <addr> Set group address of addressed node(s)");
366 0 : puts("sn <name> Set node name (up to 16 characters)");
367 0 : puts("sr Reset current submaster");
368 0 : puts("submaster Show info for current submaster");
369 0 : puts("sync Synchronize local time with node(s)");
370 0 : puts("terminal Enter teminal mode for SCS-210");
371 0 : puts("upload [slot] <filename> [debug] Upload new firmware to node in [slot] [with debug info]");
372 0 : puts("download [slot] <filename> Download firmware from node in [slot] to file");
373 0 : puts("memrd <slot> <adr> <count> Read from memory in <slot>");
374 0 : puts("memwr <slot> <adr> <value> Write to memory in <slot>");
375 0 : puts("mup <hex-file> <a1> <a2> Upload new firmware to nodes a1-a2");
376 0 : puts("mwr <index> <value> <n1> <n2> Write a variable to nodes from <n1> to <n2>");
377 0 : puts("verify [adr] <hex-file> Compare current firmware in [adr] with file");
378 0 : puts("version Display version number");
379 0 : puts("write <index> <value> [r] Write node variable");
380 0 : puts("write <i1>-<i2> <value> Write range of node variables");
381 0 : puts("log [c] Read log / clear Log [c]");
382 :
383 0 : puts("");
384 0 : }
385 :
386 : /*------------------------------------------------------------------*/
387 :
388 0 : void print_channel_str(int index, MSCB_INFO_VAR *info_chn, void *pdata, int verbose,
389 : char *line) {
390 : char str[80];
391 : int i, data;
392 :
393 0 : line[0] = 0;
394 0 : if (verbose) {
395 0 : memset(str, 0, sizeof(str));
396 0 : strncpy(str, info_chn->name, sizeof(str));
397 0 : for (i = strlen(str); i < (int) sizeof(info_chn->name) + 1; i++)
398 0 : str[i] = ' ';
399 0 : snprintf(line + strlen(line), 256 - strlen(line), "%3d: %s ", index, str);
400 : } else {
401 0 : memset(str, 0, sizeof(str));
402 0 : strncpy(str, info_chn->name, sizeof(str));
403 0 : snprintf(line, 256, "%s: ", str);
404 : }
405 :
406 0 : if (info_chn->unit == UNIT_STRING) {
407 0 : memset(str, 0, sizeof(str));
408 0 : strncpy(str, (const char *) pdata, info_chn->width);
409 0 : if (verbose)
410 0 : snprintf(line + strlen(line), 256 - strlen(line), "STR%02d \"", info_chn->width);
411 0 : for (i = 0; i < (int) strlen(str); i++)
412 0 : switch (str[i]) {
413 0 : case 1:
414 0 : strcat(line, "\\001");
415 0 : break;
416 0 : case 2:
417 0 : strcat(line, "\\002");
418 0 : break;
419 0 : case 9:
420 0 : strcat(line, "\\t");
421 0 : break;
422 0 : case 10:
423 0 : strcat(line, "\\n");
424 0 : break;
425 0 : case 13:
426 0 : strcat(line, "\\r");
427 0 : break;
428 0 : default:
429 0 : line[strlen(line) + 1] = 0;
430 0 : line[strlen(line)] = str[i];
431 0 : break;
432 : }
433 0 : strcat(line, "\"");
434 : } else {
435 0 : data = *((int *) pdata);
436 0 : switch (info_chn->width) {
437 0 : case 0:
438 0 : printf(" 0bit");
439 0 : break;
440 :
441 0 : case 1:
442 0 : data &= 0xFF;
443 0 : if (info_chn->flags & MSCBF_SIGNED) {
444 0 : if (verbose)
445 0 : snprintf(line + strlen(line), 256 - strlen(line), " 8bit S %15d (0x%02X/", (char) data, data);
446 : else
447 0 : snprintf(line + strlen(line), 256 - strlen(line), "%15d (0x%02X/", (char) data, data);
448 : } else {
449 0 : if (verbose)
450 0 : snprintf(line + strlen(line), 256 - strlen(line), " 8bit U %15u (0x%02X/", data, data);
451 : else
452 0 : snprintf(line + strlen(line), 256 - strlen(line), "%15u (0x%02X/", data, data);
453 : }
454 0 : for (i = 0; i < 8; i++)
455 0 : if (data & (0x80 >> i))
456 0 : snprintf(line + strlen(line), 256 - strlen(line), "1");
457 : else
458 0 : snprintf(line + strlen(line), 256 - strlen(line), "0");
459 0 : snprintf(line + strlen(line), 256 - strlen(line), ")");
460 0 : break;
461 :
462 0 : case 2:
463 0 : data &= 0xFFFF;
464 0 : if (info_chn->flags & MSCBF_SIGNED) {
465 0 : if (verbose)
466 0 : snprintf(line + strlen(line), 256 - strlen(line), "16bit S %15d (0x%04X)", (short) data, data);
467 : else
468 0 : snprintf(line + strlen(line), 256 - strlen(line), "%15d (0x%04X)", (short) data, data);
469 : } else {
470 0 : if (verbose)
471 0 : snprintf(line + strlen(line), 256 - strlen(line), "16bit U %15u (0x%04X)", data, data);
472 : else
473 0 : snprintf(line + strlen(line), 256 - strlen(line), "%15u (0x%04X)", data, data);
474 : }
475 0 : break;
476 :
477 0 : case 3:
478 0 : data &= 0xFFFFFF;
479 0 : if (info_chn->flags & MSCBF_SIGNED) {
480 0 : if (verbose)
481 0 : snprintf(line + strlen(line), 256 - strlen(line), "24bit S %15ld (0x%06X)", (long) data, data);
482 : else
483 0 : snprintf(line + strlen(line), 256 - strlen(line), "%15ld (0x%06X)", (long) data, data);
484 : } else {
485 0 : if (verbose)
486 0 : snprintf(line + strlen(line), 256 - strlen(line), "24bit U %15u (0x%06X)", data, data);
487 : else
488 0 : snprintf(line + strlen(line), 256 - strlen(line), "%15ld (0x%06X)", (long) data, data);
489 : }
490 0 : break;
491 :
492 0 : case 4:
493 0 : data &= 0xFFFFFFFF;
494 0 : if (info_chn->flags & MSCBF_FLOAT) {
495 0 : if (verbose)
496 0 : snprintf(line + strlen(line), 256 - strlen(line), "32bit F %15.6lg",
497 0 : *((float *) (void *) &data));
498 : else
499 0 : snprintf(line + strlen(line), 256 - strlen(line), "%15.6lg", *((float *) (void *) &data));
500 : } else {
501 0 : if (info_chn->flags & MSCBF_SIGNED) {
502 0 : if (verbose)
503 0 : snprintf(line + strlen(line), 256 - strlen(line), "32bit S %15d (0x%08X)", data, data);
504 : else
505 0 : snprintf(line + strlen(line), 256 - strlen(line), "%15d (0x%08X)", data, data);
506 : } else {
507 0 : if (verbose)
508 0 : snprintf(line + strlen(line), 256 - strlen(line), "32bit U %15u (0x%08X)", data, data);
509 : else
510 0 : snprintf(line + strlen(line), 256 - strlen(line), "%15u (0x%08X)", data, data);
511 : }
512 : }
513 0 : break;
514 :
515 0 : case 8:
516 0 : unsigned long int qdata = *((unsigned long int *) pdata);
517 0 : if (info_chn->flags & MSCBF_SIGNED) {
518 0 : if (verbose)
519 0 : snprintf(line + strlen(line), 256 - strlen(line), "64bit S (0x%016lX) %ld", qdata, qdata);
520 : else
521 0 : snprintf(line + strlen(line), 256 - strlen(line), "(0x%016lX) %ld", qdata, qdata);
522 : } else {
523 0 : if (verbose)
524 0 : snprintf(line + strlen(line), 256 - strlen(line), "64bit U (0x%016lX) %lu", qdata, qdata);
525 : else
526 0 : snprintf(line + strlen(line), 256 - strlen(line), "(0x%016lX) %lu", qdata, qdata);
527 : }
528 0 : break;
529 : }
530 : }
531 :
532 0 : snprintf(line + strlen(line), 256 - strlen(line), " ");
533 :
534 : /* evaluate prefix */
535 0 : if (info_chn->prefix) {
536 0 : for (i = 0; prefix_table[i].id != 99; i++)
537 0 : if ((unsigned char) prefix_table[i].id == info_chn->prefix)
538 0 : break;
539 0 : if (prefix_table[i].id)
540 0 : strcpy(line + strlen(line), prefix_table[i].name);
541 : }
542 :
543 : /* evaluate unit */
544 0 : if (info_chn->unit && info_chn->unit != UNIT_STRING) {
545 0 : for (i = 0; unit_table[i].id; i++)
546 0 : if ((unsigned char) unit_table[i].id == info_chn->unit)
547 0 : break;
548 0 : if (unit_table[i].id)
549 0 : strcpy(line + strlen(line), unit_table[i].name);
550 : }
551 :
552 0 : if (verbose)
553 0 : snprintf(line + strlen(line), 256 - strlen(line), "\n");
554 : else
555 0 : snprintf(line + strlen(line), 256 - strlen(line), " \r");
556 0 : }
557 :
558 0 : void print_channel(int index, MSCB_INFO_VAR *info_chn, void *pdata, int verbose) {
559 : char str[256];
560 :
561 0 : print_channel_str(index, info_chn, pdata, verbose, str);
562 0 : fputs(str, stdout);
563 0 : }
564 :
565 : /*------------------------------------------------------------------*/
566 :
567 0 : void save_node_xml(MXML_WRITER *writer, int fd, int addr) {
568 : int i, j, status, size;
569 : char str[256], line[256], data[256];
570 : MSCB_INFO info;
571 : MSCB_INFO_VAR info_var;
572 :
573 0 : status = mscb_info(fd, (unsigned short) addr, &info);
574 0 : if (status == MSCB_CRC_ERROR) {
575 0 : puts("CRC Error");
576 0 : return;
577 0 : } else if (status != MSCB_SUCCESS) {
578 0 : puts("No response from node");
579 0 : return;
580 : }
581 :
582 0 : mxml_start_element(writer, "Node");
583 :
584 0 : mxml_start_element(writer, "Name");
585 0 : mxml_write_value(writer, info.node_name);
586 0 : mxml_end_element(writer);
587 :
588 0 : mxml_start_element(writer, "NodeAddress");
589 0 : snprintf(str, sizeof(str), "%d (0x%X)", addr, addr);
590 0 : mxml_write_value(writer, str);
591 0 : mxml_end_element(writer);
592 :
593 0 : mxml_start_element(writer, "GroupAddress");
594 0 : snprintf(str, sizeof(str), "%d (0x%X)", info.group_address, info.group_address);
595 0 : mxml_write_value(writer, str);
596 0 : mxml_end_element(writer);
597 :
598 0 : mxml_start_element(writer, "ProtocolVersion");
599 0 : snprintf(str, sizeof(str), "%d.%d", info.protocol_version / 16, info.protocol_version % 16);
600 0 : mxml_write_value(writer, str);
601 0 : mxml_end_element(writer);
602 :
603 0 : mxml_start_element(writer, "Variables");
604 0 : for (i = 0; i < info.n_variables; i++) {
605 0 : mxml_start_element(writer, "Variable");
606 :
607 0 : mscb_info_variable(fd, (unsigned short) addr, (unsigned char) i, &info_var);
608 0 : size = sizeof(data);
609 0 : mscb_read(fd, (unsigned short) addr, (unsigned char) i, data, &size);
610 :
611 0 : mxml_start_element(writer, "Index");
612 0 : snprintf(str, sizeof(str), "%d", i);
613 0 : mxml_write_value(writer, str);
614 0 : mxml_end_element(writer);
615 :
616 0 : mxml_start_element(writer, "Name");
617 0 : strncpy(str, info_var.name, sizeof(str));
618 0 : str[8] = 0;
619 0 : mxml_write_value(writer, str);
620 0 : mxml_end_element(writer);
621 :
622 0 : mxml_start_element(writer, "Width");
623 0 : snprintf(str, sizeof(str), "%dbit", info_var.width * 8);
624 0 : mxml_write_value(writer, str);
625 0 : mxml_end_element(writer);
626 :
627 0 : print_channel_str(i, &info_var, data, 1, line);
628 :
629 0 : mstrlcpy(str, line + 29, sizeof(str));
630 0 : for (j = 0; j < (int) strlen(str); j++)
631 0 : if (str[j] == ' ')
632 0 : break;
633 0 : str[j] = 0;
634 0 : mxml_start_element(writer, "Flags");
635 0 : mxml_write_value(writer, str);
636 0 : mxml_end_element(writer);
637 :
638 0 : for (j += 29; j < (int) strlen(line); j++)
639 0 : if (line[j] != ' ')
640 0 : break;
641 :
642 0 : mstrlcpy(str, line + j, sizeof(str));
643 0 : for (j = 0; j < (int) strlen(str); j++)
644 0 : if (str[j] == ' ')
645 0 : break;
646 0 : str[j] = 0;
647 0 : mxml_start_element(writer, "Value");
648 0 : mxml_write_value(writer, str);
649 0 : mxml_end_element(writer);
650 :
651 0 : if (line[39] == '(') {
652 0 : mstrlcpy(str, line + 40, sizeof(str));
653 0 : for (j = 0; j < (int) strlen(str); j++)
654 0 : if (str[j] == ')')
655 0 : break;
656 0 : str[j] = 0;
657 0 : mxml_start_element(writer, "HexBinValue");
658 0 : mxml_write_value(writer, str);
659 0 : mxml_end_element(writer);
660 0 : j += 42;
661 : } else
662 0 : j = 39;
663 :
664 0 : mstrlcpy(str, line + j, sizeof(str));
665 0 : for (j = 0; j < (int) strlen(str); j++)
666 0 : if (!isalnum(str[j]))
667 0 : break;
668 0 : str[j] = 0;
669 0 : mxml_start_element(writer, "Unit");
670 0 : mxml_write_value(writer, str);
671 0 : mxml_end_element(writer);
672 :
673 0 : mxml_end_element(writer); // "Variable"
674 : }
675 :
676 0 : mxml_end_element(writer); // "Variables"
677 0 : mxml_end_element(writer); // "Node"
678 : }
679 :
680 : /*------------------------------------------------------------------*/
681 :
682 0 : void load_nodes_xml(int fd, char *file_name, int flash) {
683 : int i, j, index, status, ivar, addr;
684 : char str[256], error[256], chn_name[256][17], name[256], value[256];
685 : unsigned int data;
686 : float fvalue;
687 : PMXML_NODE root, node, nvarroot, nvar, nsub;
688 : MSCB_INFO info;
689 : MSCB_INFO_VAR info_var;
690 :
691 0 : root = mxml_parse_file(file_name, error, sizeof(error), NULL);
692 0 : if (root == NULL) {
693 0 : printf("Error loading \"%s\": %s\n", file_name, error);
694 0 : return;
695 : }
696 :
697 0 : root = mxml_find_node(root, "/MSCBDump");
698 0 : if (root == NULL) {
699 0 : printf("Error loading \"%s\": No MSCBDump structure in file\n", file_name);
700 0 : return;
701 : }
702 :
703 : /* loop over all nodes in file */
704 0 : for (index = 0; index < mxml_get_number_of_children(root); index++) {
705 0 : node = mxml_subnode(root, index);
706 :
707 0 : nsub = mxml_find_node(node, "NodeAddress");
708 0 : if (nsub == NULL) {
709 0 : printf("Error loading \"%s\": Node #%d does not contain NodeAddress\n",
710 : file_name, index);
711 0 : return;
712 : }
713 :
714 0 : printf("\nLoading node #%s\n", mxml_get_value(nsub));
715 0 : addr = atoi(mxml_get_value(nsub));
716 :
717 0 : nvarroot = mxml_find_node(node, "Variables");
718 0 : if (nvarroot == NULL) {
719 0 : printf("Error loading \"%s\": Node #%d does not contain Variables\n", file_name,
720 : index);
721 0 : return;
722 : }
723 :
724 : /* get list of channel names from node */
725 0 : if (mscb_info(fd, (unsigned short) addr, &info) != MSCB_SUCCESS) {
726 0 : printf("No response from node %d, skip node.\n", addr);
727 0 : continue;
728 : }
729 :
730 0 : memset(chn_name, 0, sizeof(chn_name));
731 0 : for (i = 0; i < info.n_variables; i++) {
732 0 : mscb_info_variable(fd, (unsigned short) addr, (unsigned char) i, &info_var);
733 0 : strncpy(chn_name[i], info_var.name, sizeof(chn_name[i]));
734 : }
735 :
736 : /* loop over variables */
737 0 : for (ivar = 0; ivar < mxml_get_number_of_children(nvarroot); ivar++) {
738 :
739 0 : nvar = mxml_subnode(nvarroot, ivar);
740 0 : nsub = mxml_find_node(nvar, "Index");
741 0 : if (nsub == NULL) {
742 0 : printf("Found variable without index\n");
743 0 : continue;
744 : }
745 0 : nsub = mxml_find_node(nvar, "Name");
746 0 : if (nsub == NULL) {
747 0 : printf("Found variable without name\n");
748 0 : continue;
749 : }
750 :
751 0 : strcpy(name, mxml_get_value(nsub));
752 :
753 0 : nsub = mxml_find_node(nvar, "Value");
754 0 : if (nsub == NULL) {
755 0 : printf("Found variable without value\n");
756 0 : continue;
757 : }
758 :
759 0 : strcpy(value, mxml_get_value(nsub));
760 :
761 : /* search for channel with same name */
762 0 : for (i = 0; chn_name[i][0]; i++)
763 0 : if (strcmp(chn_name[i], name) == 0) {
764 0 : mscb_info_variable(fd, (unsigned short) addr, (unsigned char) i,
765 : &info_var);
766 :
767 0 : if (info_var.unit == UNIT_STRING) {
768 0 : memset(str, 0, sizeof(str));
769 0 : mstrlcpy(str, value, sizeof(str));
770 0 : str[info_var.width] = 0;
771 0 : if (strlen(str) > 0 && str[strlen(str) - 1] == '\n')
772 0 : str[strlen(str) - 1] = 0;
773 :
774 : status =
775 0 : mscb_write(fd, (unsigned short) addr, (unsigned char) i, str,
776 0 : info_var.width);
777 0 : if (status != MSCB_SUCCESS)
778 0 : printf("Error writing to node %d, variable %d\n", addr, i);
779 :
780 : } else {
781 0 : if (info_var.flags & MSCBF_FLOAT) {
782 0 : fvalue = (float) atof(value);
783 0 : memcpy(&data, &fvalue, sizeof(float));
784 : } else {
785 0 : data = atoi(value);
786 : }
787 :
788 : status =
789 0 : mscb_write(fd, (unsigned short) addr, (unsigned char) i, &data,
790 0 : info_var.width);
791 0 : if (status != MSCB_SUCCESS)
792 0 : printf("Error writing to node %d, variable %d\n", addr, i);
793 :
794 : /* blank padding */
795 0 : for (j = strlen(name); j < 8; j++)
796 0 : name[j] = ' ';
797 0 : name[j] = 0;
798 :
799 0 : printf("%3d: %s %s\n", i, name, value);
800 : }
801 :
802 0 : break;
803 : }
804 :
805 0 : if (chn_name[i][0] == 0)
806 0 : printf("Variable \"%s\" from file not in node, variable skipped\n", name);
807 : }
808 :
809 0 : if (flash)
810 0 : mscb_flash(fd, addr, -1, 0);
811 : }
812 : }
813 :
814 : /*------------------------------------------------------------------*/
815 :
816 0 : int match(const char *str, const char *cmd) {
817 : int i;
818 :
819 0 : if (str[0] == '\r' || str[0] == '\n' || str[0] == 0)
820 0 : return 0;
821 :
822 0 : for (i = 0; i < (int) strlen(str); i++) {
823 0 : if (toupper(str[i]) != toupper(cmd[i]) && str[i] != '\r' && str[i] != '\n')
824 0 : return 0;
825 : }
826 :
827 0 : return 1;
828 : }
829 :
830 : /*------------------------------------------------------------------*/
831 :
832 0 : void cmd_loop(int fd, char *cmd, unsigned short adr) {
833 : int i, j, status, size, nparam, current_addr, current_group, reference_addr,
834 0 : first, last, broadcast, read_all, repeat, index, idx1, idx2, wait = 0, n_found, slot;
835 : int ping_addr[0x10000];
836 : unsigned short addr;
837 : unsigned int data, uptime, mem_addr;
838 : unsigned long int qdata;
839 : unsigned char c;
840 : float value;
841 : char str[256], line[256], dbuf[100 * 1024], param[10][100], *pc, lib[32],
842 : prot[32], *pdata, prompt[256], filename[256];
843 0 : FILE *cmd_file = NULL;
844 : MSCB_INFO info;
845 : MSCB_INFO_VAR info_var_array[256];
846 : MSCB_INFO_VAR info_var;
847 : time_t now;
848 : MXML_WRITER *writer;
849 : struct tm *ptm;
850 :
851 : /* open command file */
852 0 : if (cmd[0] == '@') {
853 0 : cmd_file = fopen(cmd + 1, "r");
854 0 : if (cmd_file == NULL) {
855 0 : printf("Command file %s not found.\n", cmd + 1);
856 0 : return;
857 : }
858 : }
859 :
860 0 : if (cmd[0])
861 : /* assumed some node correctly addressed in command mode */
862 0 : current_addr = 0;
863 : else
864 0 : current_addr = -1;
865 :
866 0 : current_group = -1;
867 :
868 0 : if (adr)
869 0 : current_addr = adr;
870 :
871 0 : broadcast = 0;
872 0 : reference_addr = 0;
873 0 : status = 0;
874 :
875 : /* fill table of possible addresses */
876 0 : for (i = 0; i < 0x10000; i++)
877 0 : ping_addr[i] = 0;
878 0 : for (i = 0; i < 1000; i++) // 0..999
879 0 : ping_addr[i] = 1;
880 0 : for (i = 0; i < 0x10000; i += 100) // 100, 200, ...
881 0 : ping_addr[i] = 1;
882 0 : for (i = 0; i < 0x10000; i += 0x100)
883 0 : ping_addr[i] = 1; // 256, 512, ...
884 0 : for (i = 0xFF00; i < 0xFFFF; i++)
885 0 : ping_addr[i] = 1; // 0xFF00-0xFFFF
886 :
887 : do {
888 : /* print prompt */
889 0 : if (!cmd[0]) {
890 0 : if (current_addr >= 0)
891 0 : snprintf(prompt, sizeof(prompt), "node%d(0x%X)> ", current_addr, current_addr);
892 0 : else if (current_group >= 0)
893 0 : snprintf(prompt, sizeof(prompt), "group%d> ", current_group);
894 0 : else if (broadcast)
895 0 : snprintf(prompt, sizeof(prompt), "all> ");
896 : else
897 0 : snprintf(prompt, sizeof(prompt), "> ");
898 0 : memset(line, 0, sizeof(line));
899 :
900 0 : cmd_edit(prompt, line, cmd_dir, NULL);
901 :
902 0 : } else if (cmd[0] != '@')
903 0 : strcpy(line, cmd);
904 : else {
905 0 : memset(line, 0, sizeof(line));
906 0 : fgets(line, sizeof(line), cmd_file);
907 :
908 0 : if (line[0] == 0)
909 0 : break;
910 :
911 : /* cut off CR */
912 0 : while (strlen(line) > 0 && line[strlen(line) - 1] == '\n')
913 0 : line[strlen(line) - 1] = 0;
914 :
915 0 : if (line[0] == 0)
916 0 : continue;
917 : }
918 :
919 : /* analyze line */
920 0 : nparam = 0;
921 0 : pc = line;
922 0 : while (*pc == ' ')
923 0 : pc++;
924 :
925 0 : memset(param, 0, sizeof(param));
926 : do {
927 0 : if (*pc == '"') {
928 0 : pc++;
929 0 : for (i = 0; *pc && *pc != '"'; i++)
930 0 : param[nparam][i] = *pc++;
931 0 : if (*pc)
932 0 : pc++;
933 0 : } else if (*pc == '\'') {
934 0 : pc++;
935 0 : for (i = 0; *pc && *pc != '\''; i++)
936 0 : param[nparam][i] = *pc++;
937 0 : if (*pc)
938 0 : pc++;
939 0 : } else if (*pc == '`') {
940 0 : pc++;
941 0 : for (i = 0; *pc && *pc != '`'; i++)
942 0 : param[nparam][i] = *pc++;
943 0 : if (*pc)
944 0 : pc++;
945 : } else
946 0 : for (i = 0; *pc && *pc != ' '; i++)
947 0 : param[nparam][i] = *pc++;
948 0 : param[nparam][i] = 0;
949 0 : while (*pc == ' ' || *pc == '\r' || *pc == '\n')
950 0 : pc++;
951 0 : nparam++;
952 0 : } while (*pc);
953 :
954 : /* help ---------- */
955 0 : if ((param[0][0] == 'h' && param[0][1] == 'e') || param[0][0] == '?')
956 0 : print_help();
957 :
958 : /* version ---------- */
959 0 : else if (match(param[0], "version")) {
960 0 : mscb_get_version(lib, prot);
961 0 : printf("MSCB library version : %s\n", lib);
962 0 : printf("MSCB protocol version : %s\n", prot);
963 : }
964 :
965 : /* debug ---------- */
966 0 : if (match(param[0], "debug")) {
967 0 : mscb_debug(atoi(param[1]));
968 0 : printf("Debugging level changed successfully.\n");
969 : }
970 :
971 : /* scan ---------- */
972 0 : else if (match(param[0], "scan")) {
973 : do {
974 0 : n_found = 0;
975 0 : int quick = 0;
976 0 : if (param[1][0] == 'q' || param[2][0] == 'q')
977 0 : quick = 1;
978 0 : for (i = -1; i < 0x10000; i++) {
979 0 : if (i != -1 && param[1][0] != 'a' && param[2][0] != 'a' && i > 0 && !ping_addr[i])
980 0 : continue;
981 0 : if (i == -1)
982 0 : printf("Test address 65535 (0xFFFF)\r");
983 : else
984 0 : printf("Test address %05d (0x%04X)\r", i, i);
985 0 : fflush(stdout);
986 :
987 0 : if (i == -1) {
988 : /* do the first time with retry, to send '0's */
989 0 : status = mscb_ping(fd, (unsigned short) 0xFFFF, 0, 0);
990 0 : Sleep(100);
991 : } else
992 0 : status = mscb_ping(fd, (unsigned short) i, quick, 0);
993 :
994 0 : if (status == MSCB_SUCCESS) {
995 :
996 0 : n_found++;
997 :
998 : /* node found, search next 100 as well */
999 0 : for (j = i; j < i + 100 && j < 0x10000; j++)
1000 0 : if (j >= 0)
1001 0 : ping_addr[j] = 1;
1002 :
1003 0 : status = mscb_info(fd, (unsigned short) i, &info);
1004 0 : strncpy(str, info.node_name, sizeof(str));
1005 0 : str[16] = 0;
1006 :
1007 0 : if (status == MSCB_SUCCESS) {
1008 0 : printf("Found node \"%s\", NA %d (0x%04X), GA %d (0x%04X), Rev. 0x%04X \n",
1009 0 : str, (unsigned short) i, (unsigned short) i, info.group_address,
1010 0 : info.group_address, info.revision);
1011 :
1012 0 : mscb_get_version(lib, prot);
1013 0 : if (info.protocol_version != atoi(prot)) {
1014 : printf
1015 0 : ("WARNING: Protocol version on node (%d) differs from local version (%s).\n",
1016 0 : info.protocol_version, prot);
1017 : }
1018 :
1019 : }
1020 0 : } else if (status == MSCB_SUBM_ERROR) {
1021 0 : printf("Error: Submaster not responding\n");
1022 0 : break;
1023 : }
1024 :
1025 0 : if (kbhit())
1026 0 : break;
1027 : }
1028 :
1029 0 : } while ((param[1][0] == 'r' || param[2][0] == 'r') && !kbhit());
1030 :
1031 0 : while (kbhit())
1032 0 : getch();
1033 :
1034 0 : printf(" \n");
1035 0 : if (n_found == 0)
1036 0 : printf("No nodes found \n");
1037 0 : else if (n_found == 1)
1038 0 : printf("One node found \n");
1039 0 : else if (n_found > 0)
1040 0 : printf("%d nodes found \n", n_found);
1041 : }
1042 :
1043 : /* info ---------- */
1044 0 : else if (match(param[0], "info")) {
1045 0 : if (current_addr < 0)
1046 0 : printf("You must first address an individual node\n");
1047 : else {
1048 0 : status = mscb_info(fd, (unsigned short) current_addr, &info);
1049 0 : if (status == MSCB_CRC_ERROR)
1050 0 : puts("CRC Error");
1051 0 : else if (status != MSCB_SUCCESS)
1052 0 : puts("No response from node");
1053 : else {
1054 0 : strncpy(str, info.node_name, sizeof(str));
1055 0 : str[16] = 0;
1056 0 : printf("Node name : %s\n", str);
1057 0 : printf("Node address : %d (0x%X)\n", info.node_address,
1058 0 : info.node_address);
1059 0 : printf("Group address : %d (0x%X)\n", info.group_address,
1060 0 : info.group_address);
1061 0 : printf("Protocol version : %d\n", info.protocol_version);
1062 :
1063 : // check if it's an SCS3000 or not
1064 0 : if (info.pinExt_resets == 0) {
1065 0 : printf("Revision : 0x%04X\n", info.revision);
1066 : } else {
1067 0 : printf("Revision : V %d.%d.%d\n", info.revision >> 8, (info.revision >> 4) & 0xF,
1068 0 : info.revision & 0xF);
1069 : }
1070 :
1071 :
1072 0 : if (info.rtc[0] && info.rtc[0] != 0xFF) {
1073 0 : for (i = 0; i < 6; i++)
1074 0 : info.rtc[i] = (info.rtc[i] / 0x10) * 10 + info.rtc[i] % 0x10;
1075 0 : printf("Real Time Clock : %02d-%02d-%02d %02d:%02d:%02d\n",
1076 0 : info.rtc[0], info.rtc[1], info.rtc[2],
1077 0 : info.rtc[3], info.rtc[4], info.rtc[5]);
1078 : }
1079 :
1080 0 : status = mscb_uptime(fd, (unsigned short) current_addr, &uptime);
1081 0 : if (status == MSCB_SUCCESS)
1082 0 : printf("Uptime : %dd %02dh %02dm %02ds\n",
1083 : uptime / (3600 * 24),
1084 0 : (uptime % (3600 * 24)) / 3600, (uptime % 3600) / 60,
1085 : (uptime % 60));
1086 0 : if (info.buf_size != 0)
1087 0 : printf("Buffer size : %d\n", info.buf_size);
1088 :
1089 : // print variables for SCS3000
1090 0 : if (info.bootBank != 0) {
1091 0 : printf("Pin/Ext WD Resets : %d\n", info.pinExt_resets);
1092 0 : printf("SW-resets : %d\n", info.SW_resets);
1093 0 : printf("Int. WD resets : %d\n", info.int_WD_resets);
1094 0 : printf("Boot-Bank : %d\n", info.bootBank);
1095 0 : printf("Silicon Revision : %c\n", info.siliconRevison);
1096 0 : printf("System load : %4.2f%%\n", info.systemLoad);
1097 0 : printf("Peak system load : %4.2f%%\n", info.peakSystemLoad);
1098 0 : printf("PCB Temp : %4.2f%cC\n", info.pcbTemp, 167); // 167 is � symbol
1099 0 : printf("Supply 1.8V : %4.2fV\n", info.Supply1V8);
1100 0 : printf("Supply 3.3V : %4.2fV\n", info.Supply3V3);
1101 0 : printf("Supply 5.0V : %4.2fV\n", info.Supply5V0);
1102 0 : printf("Supply 24.0V : %4.2fV\n", info.Supply24V0);
1103 0 : printf("Supply 5V Ext. : %4.2fV\n", info.Supply5V0Ext);
1104 0 : printf("Supply 24V Ext. : %4.2fV\n", info.Supply24V0Ext);
1105 0 : printf("Supply current : %4.3fA\n", info.Supply24V0Current);
1106 0 : printf("Battery voltage : %4.2fV\n", info.Vbat);
1107 : }
1108 :
1109 0 : mscb_get_version(lib, prot);
1110 0 : if (info.protocol_version != atoi(prot)) {
1111 : printf
1112 0 : ("\nWARNING: Protocol version on node (%d) differs from local version (%s).\n",
1113 0 : info.protocol_version, prot);
1114 : printf
1115 0 : ("Problems may arise communicating with this node. Please upgrade.\n\n");
1116 : }
1117 : }
1118 : }
1119 : }
1120 :
1121 : /* ping ---------- */
1122 0 : else if (match(param[0], "ping")) {
1123 0 : if (!param[1][0])
1124 0 : puts("Please specify node address");
1125 : else {
1126 0 : if (param[1][1] == 'x') {
1127 0 : sscanf(param[1] + 2, "%x", &i);
1128 0 : addr = (unsigned short) i;
1129 : } else
1130 0 : addr = (unsigned short) atoi(param[1]);
1131 :
1132 : do {
1133 0 : status = mscb_ping(fd, addr, 0, 1);
1134 :
1135 0 : if (status != MSCB_SUCCESS) {
1136 0 : if (status == MSCB_MUTEX)
1137 0 : printf("MSCB used by other thread\n");
1138 0 : else if (status == MSCB_SUBM_ERROR)
1139 0 : printf("Error: Submaster not responding\n");
1140 : else
1141 0 : printf("Node %d does not respond\n", addr);
1142 0 : current_addr = -1;
1143 0 : current_group = -1;
1144 0 : broadcast = 0;
1145 : } else {
1146 0 : printf("Node %d addressed\n", addr);
1147 0 : current_addr = addr;
1148 0 : current_group = -1;
1149 0 : broadcast = 0;
1150 : }
1151 :
1152 0 : if (param[2][0] == 'r' && !kbhit())
1153 0 : Sleep(1000);
1154 :
1155 0 : } while (param[2][0] == 'r' && !kbhit());
1156 : }
1157 : }
1158 :
1159 : /* address ---------- */
1160 0 : else if (match(param[0], "addr")) {
1161 0 : if (!param[1][0])
1162 0 : puts("Please specify node address");
1163 : else {
1164 0 : if (param[1][1] == 'x') {
1165 0 : sscanf(param[1] + 2, "%x", &i);
1166 0 : addr = (unsigned short) i;
1167 : } else
1168 0 : addr = (unsigned short) atoi(param[1]);
1169 :
1170 0 : mscb_addr(fd, MCMD_ADDR_NODE16, addr, 0, 10);
1171 0 : current_addr = addr;
1172 0 : current_group = -1;
1173 0 : broadcast = 0;
1174 : }
1175 : }
1176 :
1177 : /* ba, broadcast address ---------- */
1178 0 : else if (match(param[0], "baddr")) {
1179 0 : current_addr = -1;
1180 0 : current_group = -1;
1181 0 : broadcast = 1;
1182 : }
1183 :
1184 : /* ga, group address ---------- */
1185 0 : else if (match(param[0], "gaddr")) {
1186 0 : if (!param[1][0])
1187 0 : puts("Please specify group address");
1188 : else {
1189 0 : if (param[1][1] == 'x') {
1190 0 : sscanf(param[1] + 2, "%x", &i);
1191 0 : addr = (unsigned short) i;
1192 : } else
1193 0 : addr = (unsigned short) atoi(param[1]);
1194 :
1195 0 : printf("Enter address of first node in group %d: ", addr);
1196 0 : fgets(str, sizeof(str), stdin);
1197 0 : reference_addr = atoi(str);
1198 0 : current_addr = -1;
1199 0 : current_group = addr;
1200 0 : broadcast = 0;
1201 : }
1202 : }
1203 :
1204 : /* sa, set node address ---------- */
1205 0 : else if (match(param[0], "sa")) {
1206 0 : if (current_addr < 0 && current_group < 0 && !broadcast)
1207 0 : printf("You must first address node(s)\n");
1208 : else {
1209 0 : if (!param[1][0])
1210 0 : puts("Please specify node address");
1211 : else {
1212 0 : if (param[1][1] == 'x') {
1213 0 : sscanf(param[1] + 2, "%x", &i);
1214 0 : addr = (unsigned short) i;
1215 : } else
1216 0 : addr = (unsigned short) atoi(param[1]);
1217 :
1218 0 : status =
1219 0 : mscb_set_node_addr(fd, current_addr, current_group, broadcast, addr);
1220 0 : if (current_addr >= 0) {
1221 0 : if (status == MSCB_ADDR_EXISTS)
1222 0 : printf("Error: Address %d exists already on this network\n", addr);
1223 : else
1224 0 : current_addr = addr;
1225 : }
1226 : }
1227 : }
1228 : }
1229 :
1230 : /* sg, set group address ---------- */
1231 0 : else if (match(param[0], "sg")) {
1232 0 : if (current_addr < 0 && current_group < 0 && !broadcast)
1233 0 : printf("You must first address node(s)\n");
1234 : else {
1235 0 : if (!param[1][0])
1236 0 : puts("Please specify group address");
1237 : else {
1238 0 : if (param[1][1] == 'x') {
1239 0 : sscanf(param[1] + 2, "%x", &i);
1240 0 : addr = (unsigned short) i;
1241 : } else
1242 0 : addr = (unsigned short) atoi(param[1]);
1243 :
1244 0 : mscb_set_group_addr(fd, current_addr, current_group, broadcast, addr);
1245 : }
1246 : }
1247 : }
1248 :
1249 : /* sn, set node name ---------- */
1250 0 : else if (match(param[0], "sn")) {
1251 0 : if (current_addr < 0)
1252 0 : printf("You must first address an individual node\n");
1253 : else {
1254 0 : if (!param[1][0])
1255 0 : puts("Please specify node name");
1256 : else {
1257 0 : str[0] = '\0';
1258 0 : for (j = 1; j < 10; j++) {
1259 0 : strcat(str, param[j]);
1260 0 : if (j < 9 && param[j + 1][0] != '\0') {
1261 0 : strcat(str, " ");
1262 : }
1263 : }
1264 0 : while (strlen(str) > 0
1265 0 : && (str[strlen(str) - 1] == '\r' || str[strlen(str) - 1] == '\n'))
1266 0 : str[strlen(str) - 1] = 0;
1267 :
1268 0 : if (strlen(str) > 15)
1269 0 : printf("Maximum length is 15 characters, please choose shorter name\n");
1270 : else
1271 0 : mscb_set_name(fd, (unsigned short) current_addr, str);
1272 : }
1273 : }
1274 : }
1275 :
1276 : /* sm, set MAC address etc. ---------- */
1277 0 : else if (match(param[0], "sm")) {
1278 0 : if (set_mac_address(fd))
1279 0 : break; // exit program
1280 : }
1281 :
1282 : /* baud, set baud rate ---------- */
1283 0 : else if (match(param[0], "baud")) {
1284 0 : puts("Possible baud rates:\n");
1285 0 : puts(" 1: 2400");
1286 0 : puts(" 2: 4800");
1287 0 : puts(" 3: 9600");
1288 0 : puts(" 4: 19200");
1289 0 : puts(" 5: 28800");
1290 0 : puts(" 6: 38400");
1291 0 : puts(" 7: 57600");
1292 0 : puts(" 8: 115200 <= default");
1293 0 : puts(" 9: 172800");
1294 0 : puts(" 10: 345600");
1295 :
1296 0 : printf("\nSelect rate: ");
1297 0 : fgets(str, sizeof(str), stdin);
1298 0 : i = atoi(str);
1299 0 : mscb_set_baud(fd, i);
1300 : }
1301 :
1302 :
1303 : /* write ---------- */
1304 0 : else if (match(param[0], "write")) {
1305 0 : if (current_addr < 0 && current_group < 0)
1306 0 : printf("You must first address a node or a group\n");
1307 : else {
1308 0 : if (!param[1][0])
1309 0 : puts("Please specify channel number");
1310 : else {
1311 0 : idx1 = atoi(param[1]);
1312 0 : if (strchr(param[1], '-'))
1313 0 : idx2 = atoi(strchr(param[1], '-') + 1);
1314 : else
1315 0 : idx2 = idx1;
1316 :
1317 0 : if (current_addr < 0) {
1318 0 : addr = reference_addr;
1319 : } else
1320 0 : addr = current_addr;
1321 :
1322 0 : idx1 = idx1 > 255 ? 255 : idx1;
1323 0 : idx2 = idx2 > 255 ? 255 : idx2;
1324 :
1325 0 : for (index = idx1; index <= idx2; index++) {
1326 0 : status = mscb_info_variable(fd, (unsigned short) addr, (unsigned char) index,
1327 : &info_var);
1328 :
1329 0 : if (status == MSCB_NO_VAR) {
1330 0 : printf("Node has no variable #%d\n", index);
1331 0 : break;
1332 : }
1333 :
1334 0 : if (info_var.unit == UNIT_STRING) {
1335 0 : memset(str, 0, sizeof(str));
1336 0 : strncpy(str, param[2], info_var.width);
1337 0 : if (strlen(str) > 0 && str[strlen(str) - 1] == '\n')
1338 0 : str[strlen(str) - 1] = 0;
1339 :
1340 : do {
1341 0 : if (current_addr >= 0)
1342 0 : status = mscb_write(fd, (unsigned short) current_addr,
1343 0 : (unsigned char) index, str, strlen(str) + 1);
1344 : else
1345 0 : status = mscb_write_group(fd, (unsigned short) current_group,
1346 : (unsigned char) index, str,
1347 0 : strlen(str) + 1);
1348 0 : if (param[3][0])
1349 0 : Sleep(1000);
1350 0 : } while (param[3][0] && !kbhit());
1351 :
1352 0 : } else if (info_var.unit == UNIT_ASCII) {
1353 0 : memset(str, 0, sizeof(str));
1354 0 : strncpy(str, param[2], sizeof(str));
1355 0 : if (strlen(str) > 0 && str[strlen(str) - 1] == '\n')
1356 0 : str[strlen(str) - 1] = 0;
1357 :
1358 : do {
1359 0 : if (current_addr >= 0)
1360 0 : status =
1361 0 : mscb_write(fd, (unsigned short) current_addr,
1362 0 : (unsigned char) index, str, strlen(str) + 1);
1363 0 : Sleep(100);
1364 0 : } while (param[3][0] && !kbhit());
1365 :
1366 : } else {
1367 0 : if (!param[2][0])
1368 0 : puts("Please specify data");
1369 : else {
1370 0 : if (info_var.unit == UNIT_BYTE && info_var.width == 8) {
1371 0 : if (param[2][1] == 'x')
1372 0 : sscanf(param[2] + 2, "%lx", &qdata);
1373 : else
1374 0 : qdata = atol(param[2]);
1375 : } else {
1376 0 : if (info_var.flags & MSCBF_FLOAT) {
1377 0 : value = (float) atof(param[2]);
1378 0 : memcpy(&data, &value, sizeof(float));
1379 : } else {
1380 0 : if (param[2][1] == 'x')
1381 0 : sscanf(param[2] + 2, "%x", &data);
1382 : else
1383 0 : data = atoi(param[2]);
1384 : }
1385 0 : qdata = data;
1386 : }
1387 :
1388 : do {
1389 0 : if (current_addr >= 0)
1390 0 : status = mscb_write(fd, (unsigned short) current_addr,
1391 0 : (unsigned char) index, &qdata, info_var.width);
1392 : else
1393 0 : status = mscb_write_group(fd, (unsigned short) current_group,
1394 : (unsigned char) index, &qdata,
1395 0 : info_var.width);
1396 :
1397 0 : if (param[3][0])
1398 0 : Sleep(100);
1399 :
1400 0 : } while (param[3][0] && !kbhit());
1401 : }
1402 : }
1403 : }
1404 :
1405 0 : if (status != MSCB_SUCCESS)
1406 0 : printf("Error: %d\n", status);
1407 : }
1408 : }
1409 : }
1410 :
1411 : /* mwrite ---------- */
1412 0 : else if (match(param[0], "mwrite")) {
1413 0 : if (!param[1][0] || !param[2][0] || !param[3][0] || !param[4][0])
1414 0 : puts("Please specify variable index, value, and node range");
1415 : else {
1416 0 : index = atoi(param[1]);
1417 0 : first = atoi(param[3]);
1418 0 : last = atoi(param[4]);
1419 :
1420 0 : mscb_info_variable(fd, (unsigned short) first, (unsigned char) index,
1421 : &info_var);
1422 :
1423 0 : for (addr = first; addr <= last; addr++) {
1424 :
1425 0 : printf("Node %d\n", addr);
1426 0 : if (info_var.unit == UNIT_STRING) {
1427 0 : memset(str, 0, sizeof(str));
1428 0 : strncpy(str, param[2], info_var.width);
1429 0 : if (strlen(str) > 0 && str[strlen(str) - 1] == '\n')
1430 0 : str[strlen(str) - 1] = 0;
1431 :
1432 0 : status = mscb_write(fd, (unsigned short) addr,
1433 0 : (unsigned char) index, str, strlen(str) + 1);
1434 :
1435 0 : } else if (info_var.unit == UNIT_ASCII) {
1436 0 : memset(str, 0, sizeof(str));
1437 0 : strncpy(str, param[2], sizeof(str));
1438 0 : if (strlen(str) > 0 && str[strlen(str) - 1] == '\n')
1439 0 : str[strlen(str) - 1] = 0;
1440 :
1441 0 : mscb_write(fd, (unsigned short) addr,
1442 0 : (unsigned char) index, str, strlen(str) + 1);
1443 : } else {
1444 0 : if (info_var.flags & MSCBF_FLOAT) {
1445 0 : value = (float) atof(param[2]);
1446 0 : memcpy(&data, &value, sizeof(float));
1447 : } else {
1448 0 : if (param[2][1] == 'x')
1449 0 : sscanf(param[2] + 2, "%x", &data);
1450 : else
1451 0 : data = atoi(param[2]);
1452 : }
1453 :
1454 0 : status = mscb_write(fd, (unsigned short) addr,
1455 0 : (unsigned char) index, &data, info_var.width);
1456 : }
1457 : }
1458 :
1459 0 : if (status != MSCB_SUCCESS)
1460 0 : printf("Error: %d\n", status);
1461 : }
1462 : }
1463 :
1464 : /* read ---------- */
1465 0 : else if (match(param[0], "read")) {
1466 0 : if (current_addr < 0)
1467 0 : printf("You must first address an individual node\n");
1468 : else {
1469 0 : if (!param[1][0] || param[1][0] == 'a' || param[1][0] == 'r') {
1470 0 : first = 0;
1471 0 : last = 255;
1472 0 : } else if (strchr(param[1], '-')) {
1473 0 : first = atoi(param[1]);
1474 0 : last = atoi(strchr(param[1], '-') + 1);
1475 : } else {
1476 0 : first = last = atoi(param[1]);
1477 : }
1478 :
1479 0 : first = first > 255 ? 255 : first;
1480 0 : last = last > 255 ? 255 : last;
1481 :
1482 0 : read_all = (param[1][0] == 'a' || param[2][0] == 'a' || param[3][0] == 'a');
1483 0 : repeat = (param[1][0] == 'r' || param[2][0] == 'r' || param[3][0] == 'r');
1484 0 : if (repeat) {
1485 0 : wait = 0;
1486 0 : for (i = 1; i < 4; i++)
1487 0 : if (param[i][0] == 'r')
1488 0 : break;
1489 0 : if (atoi(param[i + 1]) > 0)
1490 0 : wait = atoi(param[i + 1]);
1491 : }
1492 :
1493 0 : n_found = 0;
1494 0 : memset(info_var_array, 0, sizeof(info_var_array));
1495 0 : for (i = first; i <= last; i++) {
1496 0 : status = mscb_info_variable(fd, (unsigned short) current_addr, (unsigned char) i, &info_var_array[i]);
1497 0 : if (status == MSCB_NO_VAR) {
1498 0 : if (first == last)
1499 0 : printf("Node has no variable #%d\n", first);
1500 0 : break;
1501 0 : } else if (status == MSCB_CRC_ERROR)
1502 0 : puts("CRC Error\n");
1503 0 : else if (status != MSCB_SUCCESS)
1504 0 : puts("Timeout or invalid channel number\n");
1505 : else
1506 0 : n_found++;
1507 : }
1508 :
1509 0 : if (n_found) {
1510 : do {
1511 0 : if (first == last) { // read single variable
1512 0 : i = first;
1513 0 : size = info_var_array[i].width;
1514 0 : memset(dbuf, 0, sizeof(dbuf));
1515 0 : status = mscb_read(fd, (unsigned short) current_addr, (unsigned char) i, dbuf, &size);
1516 :
1517 0 : if (status == MSCB_SUCCESS)
1518 0 : print_channel(i, &info_var_array[i], dbuf, first != last);
1519 : } else { // read multiple variables
1520 0 : last = first + n_found - 1;
1521 0 : size = 1400;
1522 0 : status = mscb_read_range(fd, (unsigned short) current_addr, (unsigned char) first,
1523 : (unsigned char) last, dbuf, &size);
1524 :
1525 0 : if (status == MSCB_CRC_ERROR)
1526 0 : puts("CRC Error\n");
1527 0 : else if (status == MSCB_TIMEOUT)
1528 0 : puts("Timeout receivig acknowledge\n");
1529 0 : else if (status != MSCB_SUCCESS)
1530 0 : puts("Reading not successful!\n");
1531 : else {
1532 0 : pdata = dbuf;
1533 0 : for (i = first; i <= last; i++) {
1534 0 : size = info_var_array[i].width;
1535 0 : if (size == 2) {
1536 0 : WORD_SWAP(pdata);
1537 0 : } else if (size == 4) {
1538 0 : DWORD_SWAP(pdata);
1539 : }
1540 :
1541 0 : if ((info_var_array[i].flags & MSCBF_HIDDEN) == 0 || read_all || first > 0)
1542 0 : print_channel(i, &info_var_array[i], pdata, first != last);
1543 :
1544 0 : if (kbhit())
1545 0 : break;
1546 :
1547 0 : pdata += size;
1548 : }
1549 : }
1550 : }
1551 :
1552 0 : if (kbhit())
1553 0 : break;
1554 :
1555 0 : if (first != last && repeat)
1556 0 : printf("\n");
1557 :
1558 0 : if (repeat) {
1559 0 : if (wait) {
1560 0 : Sleep(wait);
1561 0 : printf("\n");
1562 : } else
1563 0 : Sleep(10);
1564 : }
1565 :
1566 0 : } while (!kbhit() && repeat);
1567 : }
1568 :
1569 0 : if (first == last)
1570 0 : printf("\n");
1571 0 : while (kbhit())
1572 0 : getch();
1573 : }
1574 : }
1575 :
1576 : /* save ---------- */
1577 0 : else if (match(param[0], "save")) {
1578 0 : if (current_addr < 0 && param[1][0] == 0 && param[2][0] == 0)
1579 0 : printf("You must first address an individual node or specify a range\n");
1580 : else {
1581 0 : if (param[1][0] == 0 || strchr(param[1], '.') == NULL) {
1582 0 : printf("Enter file name: ");
1583 0 : fgets(str, sizeof(str), stdin);
1584 : } else
1585 0 : strcpy(str, param[1]);
1586 :
1587 0 : if (str[strlen(str) - 1] == '\n')
1588 0 : str[strlen(str) - 1] = 0;
1589 :
1590 0 : if (param[2][0] == 0)
1591 0 : first = last = current_addr;
1592 : else {
1593 0 : if (param[3][0]) {
1594 0 : first = atoi(param[2]);
1595 0 : last = atoi(param[3]);
1596 : } else {
1597 0 : first = atoi(param[1]);
1598 0 : last = atoi(param[2]);
1599 : }
1600 : }
1601 :
1602 0 : writer = mxml_open_file(str);
1603 0 : if (writer == NULL)
1604 0 : printf("Cannot open xml file \"%s\"\n", str);
1605 : else {
1606 0 : mxml_start_element(writer, "MSCBDump");
1607 0 : for (i = first, j = 0; i <= last; i++) {
1608 0 : status = mscb_ping(fd, (unsigned short) i, 0, 1);
1609 0 : if (status == MSCB_SUCCESS) {
1610 0 : j++;
1611 0 : printf("Save node %d (0x%04X) \r", i, i);
1612 0 : fflush(stdout);
1613 0 : save_node_xml(writer, fd, i);
1614 : } else {
1615 0 : printf("Test address %d (0x%04X) \r", i, i);
1616 0 : fflush(stdout);
1617 : }
1618 : }
1619 0 : printf("\n");
1620 0 : if (j > 1)
1621 0 : printf("%d nodes saved \n", j);
1622 :
1623 0 : mxml_end_element(writer);
1624 0 : mxml_close_file(writer);
1625 : }
1626 : }
1627 : }
1628 :
1629 : /* load ---------- */
1630 0 : else if (match(param[0], "load")) {
1631 0 : if (param[1][0] == 0) {
1632 0 : printf("Enter file name: ");
1633 0 : fgets(str, sizeof(str), stdin);
1634 : } else
1635 0 : strcpy(str, param[1]);
1636 :
1637 0 : if (str[strlen(str) - 1] == '\n')
1638 0 : str[strlen(str) - 1] = 0;
1639 :
1640 0 : printf("Write parameters to flash? (y/[n]) ");
1641 0 : fgets(line, sizeof(line), stdin);
1642 :
1643 0 : load_nodes_xml(fd, str, line[0] == 'y');
1644 : }
1645 :
1646 : /* terminal ---------- */
1647 0 : else if (match(param[0], "terminal")) {
1648 : int status, chn;
1649 :
1650 : /* find first dataless variable */
1651 0 : memset(info_var_array, 0, sizeof(info_var_array));
1652 0 : for (chn = 0; chn < 255; chn++) {
1653 0 : status = mscb_info_variable(fd, (unsigned short) current_addr, (unsigned char) chn, &info_var_array[chn]);
1654 0 : if (status == MSCB_NO_VAR)
1655 0 : break;
1656 0 : if (info_var_array[chn].flags & MSCBF_DATALESS)
1657 0 : break;
1658 : }
1659 :
1660 0 : if (status == MSCB_NO_VAR) {
1661 :
1662 0 : puts("Node does not support terminal mode.\n");
1663 :
1664 : } else {
1665 :
1666 0 : puts("Exit with <ESC>\n");
1667 0 : c = 0;
1668 :
1669 : do {
1670 0 : if ((c = ss_getchar(0)) != 0) {
1671 0 : if (c == 27)
1672 0 : break;
1673 :
1674 0 : putchar(c);
1675 0 : fflush(stdout);
1676 0 : status = mscb_write(fd, (unsigned short) current_addr, chn, &c, 1);
1677 0 : if (status != MSCB_SUCCESS) {
1678 0 : printf("\nError: %d\n", status);
1679 0 : break;
1680 : }
1681 :
1682 0 : if (c == '\r') {
1683 0 : putchar('\n');
1684 0 : c = '\n';
1685 0 : mscb_write(fd, (unsigned short) current_addr, chn, &c, 1);
1686 : }
1687 :
1688 : }
1689 :
1690 0 : memset(line, 0, sizeof(line));
1691 0 : size = sizeof(line);
1692 0 : mscb_read(fd, (unsigned short) current_addr, chn, line, &size);
1693 0 : if (size > 0) {
1694 0 : fputs(line, stdout);
1695 0 : fflush(stdout);
1696 : }
1697 :
1698 0 : Sleep(10);
1699 : } while (TRUE);
1700 :
1701 0 : puts("\n");
1702 0 : while (kbhit())
1703 0 : getch();
1704 : }
1705 : }
1706 :
1707 : /* flash ---------- */
1708 0 : else if (match(param[0], "flash")) {
1709 0 : if (current_addr < 0 && current_group < 0 && !broadcast)
1710 0 : printf("You must first address node (s)\n");
1711 : else {
1712 0 : status = mscb_flash(fd, current_addr, current_group, broadcast);
1713 :
1714 0 : if (status != MSCB_SUCCESS)
1715 0 : printf("Error: %d\n", status);
1716 : }
1717 : }
1718 :
1719 : /* upload ---------- */
1720 0 : else if (match(param[0], "upload")) {
1721 0 : if (isdigit(param[1][0])) {
1722 : // address given: upload to WaveDAQ slot
1723 0 : if (param[2][0] == 0) {
1724 0 : printf("Enter name of file: ");
1725 0 : fgets(filename, sizeof(filename), stdin);
1726 : } else
1727 0 : strcpy(filename, param[2]);
1728 :
1729 0 : if (str[strlen(filename) - 1] == '\n')
1730 0 : str[strlen(filename) - 1] = 0;
1731 :
1732 0 : i = 0;
1733 0 : if (match(param[2], "debug") ||
1734 0 : match(param[3], "deubg"))
1735 0 : i = 1;
1736 :
1737 0 : status = mscb_upload(fd, (unsigned short) current_addr, (unsigned short) atoi(param[1]), filename,
1738 : i | MSCB_UPLOAD_SUBADDR);
1739 0 : if (status == MSCB_NOT_FOUND)
1740 0 : printf("File \"%s\" not found\n", filename);
1741 0 : else if (status == MSCB_FORMAT_ERROR)
1742 0 : printf("Syntax error in file \"%s\"\n", filename);
1743 0 : else if (status == MSCB_TIMEOUT)
1744 0 : printf("Node %d does not respond\n", current_addr);
1745 0 : else if (status == MSCB_SUBADDR)
1746 0 : printf("Cannot program subaddress\n");
1747 0 : else if (status == MSCB_NOTREADY)
1748 0 : printf("Note just rebooted and not ready for upgrade\n");
1749 :
1750 : } else {
1751 0 : if (current_addr < 0)
1752 0 : printf("You must first address an individual node\n");
1753 : else {
1754 0 : if (param[1][0] == 0) {
1755 0 : printf("Enter name of file: ");
1756 0 : fgets(filename, sizeof(filename), stdin);
1757 : } else
1758 0 : strcpy(filename, param[1]);
1759 :
1760 0 : if (str[strlen(filename) - 1] == '\n')
1761 0 : str[strlen(filename) - 1] = 0;
1762 :
1763 0 : status = mscb_upload(fd, (unsigned short) current_addr, 0, filename, param[2][0] == 'd');
1764 0 : if (status == MSCB_NOT_FOUND)
1765 0 : printf("File \"%s\" not found\n", filename);
1766 0 : else if (status == MSCB_FORMAT_ERROR)
1767 0 : printf("Syntax error in file \"%s\"\n", filename);
1768 0 : else if (status == MSCB_TIMEOUT)
1769 0 : printf("Node %d does not respond\n", current_addr);
1770 0 : else if (status == MSCB_SUBADDR)
1771 0 : printf("Cannot program subaddress\n");
1772 0 : else if (status == MSCB_NOTREADY)
1773 0 : printf("Note just rebooted and not ready for upgrade\n");
1774 :
1775 : }
1776 : }
1777 : }
1778 :
1779 : /* download ---------- */
1780 0 : else if (match(param[0], "download")) {
1781 0 : if (isdigit(param[1][0])) {
1782 : // address given: upload to WaveDAQ slot
1783 0 : if (param[2][0] == 0) {
1784 0 : printf("Enter name of file: ");
1785 0 : fgets(filename, sizeof(filename), stdin);
1786 : } else
1787 0 : strcpy(filename, param[2]);
1788 :
1789 0 : if (str[strlen(filename) - 1] == '\n')
1790 0 : str[strlen(filename) - 1] = 0;
1791 :
1792 0 : status = mscb_download(fd, (unsigned short) current_addr, (unsigned short) atoi(param[1]), filename);
1793 0 : if (status == MSCB_NOT_FOUND)
1794 0 : printf("File \"%s\" exists already\n", filename);
1795 0 : else if (status == MSCB_NO_MEM)
1796 0 : printf("Cannot write to file \"%s\"\n", filename);
1797 0 : else if (status == MSCB_TIMEOUT)
1798 0 : printf("Node %d does not respond\n", current_addr);
1799 0 : else if (status == MSCB_SUBADDR)
1800 0 : printf("Cannot read subaddress\n");
1801 :
1802 : } else {
1803 0 : if (current_addr < 0)
1804 0 : printf("You must first address an individual node\n");
1805 : else {
1806 0 : if (param[1][0] == 0) {
1807 0 : printf("Enter name of file: ");
1808 0 : fgets(filename, sizeof(filename), stdin);
1809 : } else
1810 0 : strcpy(filename, param[1]);
1811 :
1812 0 : if (str[strlen(filename) - 1] == '\n')
1813 0 : str[strlen(filename) - 1] = 0;
1814 :
1815 0 : status = mscb_download(fd, (unsigned short) current_addr, 0, filename);
1816 0 : if (status == MSCB_NOT_FOUND)
1817 0 : printf("File \"%s\" exists already\n", filename);
1818 0 : else if (status == MSCB_NO_MEM)
1819 0 : printf("Cannot write to file \"%s\"\n", filename);
1820 0 : else if (status == MSCB_TIMEOUT)
1821 0 : printf("Node %d does not respond\n", current_addr);
1822 0 : else if (status == MSCB_SUBADDR)
1823 0 : printf("Cannot read subaddress\n");
1824 : }
1825 : }
1826 : }
1827 :
1828 : /* mupload ---------- */
1829 0 : else if (match(param[0], "mupload")) {
1830 :
1831 0 : first = atoi(param[2]);
1832 0 : last = atoi(param[3]);
1833 :
1834 0 : if (last == 0)
1835 0 : printf("You must specify an address range\n");
1836 : else {
1837 0 : strcpy(filename, param[1]);
1838 :
1839 0 : for (i = first; i <= last; i++) {
1840 0 : printf("Node%d: ", i);
1841 0 : status = mscb_upload(fd, (unsigned short) i, 0, filename, 0);
1842 :
1843 0 : if (status == MSCB_NOT_FOUND) {
1844 0 : printf("File \"%s\" not found\n", filename);
1845 0 : break;
1846 0 : } else if (status == MSCB_FORMAT_ERROR) {
1847 0 : printf("Syntax error in file \"%s\"\n", filename);
1848 0 : break;
1849 0 : } else if (status == MSCB_TIMEOUT)
1850 0 : printf("Node %d does not respond\n", current_addr);
1851 0 : else if (status == MSCB_SUBADDR)
1852 0 : printf("Cannot program subaddress\n");
1853 0 : else if (status == MSCB_NOTREADY)
1854 0 : printf("Note just rebooted and not ready for upgrade\n");
1855 : }
1856 : }
1857 : }
1858 :
1859 : /* verify ---------- */
1860 0 : else if (match(param[0], "verify")) {
1861 0 : if (isdigit(param[1][0])) {
1862 : // address given: verify WaveDAQ slot
1863 0 : if (param[2][0] == 0) {
1864 0 : printf("Enter name of file: ");
1865 0 : fgets(filename, sizeof(filename), stdin);
1866 : } else
1867 0 : strcpy(filename, param[2]);
1868 :
1869 0 : if (str[strlen(filename) - 1] == '\n')
1870 0 : str[strlen(filename) - 1] = 0;
1871 :
1872 0 : status = mscb_verify(fd, (unsigned short) current_addr, (short) atoi(param[1]), filename,
1873 : MSCB_UPLOAD_SUBADDR);
1874 0 : if (status == MSCB_NOT_FOUND)
1875 0 : printf("File \"%s\" not found\n", filename);
1876 0 : else if (status == MSCB_FORMAT_ERROR)
1877 0 : printf("Syntax error in file \"%s\"\n", filename);
1878 0 : else if (status == MSCB_TIMEOUT)
1879 0 : printf("Node %d does not respond\n", current_addr);
1880 0 : else if (status == MSCB_SUBADDR)
1881 0 : printf("Cannot program subaddress\n");
1882 0 : else if (status == MSCB_NOTREADY)
1883 0 : printf("Note just rebooted and not ready for upgrade\n");
1884 :
1885 : } else {
1886 0 : if (current_addr < 0)
1887 0 : printf("You must first address an individual node\n");
1888 : else {
1889 0 : if (param[1][0] == 0) {
1890 0 : printf("Enter name of file: ");
1891 0 : fgets(filename, sizeof(filename), stdin);
1892 : } else
1893 0 : strcpy(filename, param[1]);
1894 :
1895 0 : if (str[strlen(filename) - 1] == '\n')
1896 0 : str[strlen(filename) - 1] = 0;
1897 :
1898 0 : status = mscb_verify(fd, (unsigned short) current_addr, 0, filename, 0);
1899 0 : if (status == MSCB_NOT_FOUND)
1900 0 : printf("File \"%s\" not found\n", filename);
1901 0 : else if (status == MSCB_FORMAT_ERROR)
1902 0 : printf("Syntax error in file \"%s\"\n", filename);
1903 0 : else if (status == MSCB_TIMEOUT)
1904 0 : printf("Node %d does not respond\n", current_addr);
1905 0 : else if (status == MSCB_SUBADDR)
1906 0 : printf("Cannot program subaddress\n");
1907 0 : else if (status == MSCB_NOTREADY)
1908 0 : printf("Note just rebooted and not ready for upgrade\n");
1909 : }
1910 : }
1911 : }
1912 :
1913 : /* memory write ---------- */
1914 0 : else if (match(param[0], "memwr")) {
1915 0 : if (current_addr < 0 && current_group < 0 && !broadcast)
1916 0 : printf("You must first address node (s)\n");
1917 : else {
1918 0 : slot = atoi(param[1]);
1919 :
1920 0 : if (param[2][1] == 'x')
1921 0 : sscanf(param[2] + 2, "%X", &mem_addr);
1922 : else
1923 0 : mem_addr = atoi(param[2]);
1924 :
1925 0 : mem_addr |= MSCB_BASE_RAM;
1926 :
1927 0 : if (param[3][1] == 'x') {
1928 0 : sscanf(param[3] + 2, "%X", &data);
1929 0 : if (strlen(param[3]) == 4)
1930 0 : size = 1;
1931 0 : else if (strlen(param[3]) == 6) {
1932 0 : size = 2;
1933 0 : WORD_SWAP(&data);
1934 : } else {
1935 0 : size = 4;
1936 0 : DWORD_SWAP(&data);
1937 : }
1938 0 : } else if (isdigit(param[3][0])) {
1939 0 : size = 4;
1940 0 : data = atoi(param[3]);
1941 0 : DWORD_SWAP(&data);
1942 : } else {
1943 : // TBD: String
1944 : }
1945 :
1946 0 : mscb_write_mem(fd, (unsigned short) current_addr, slot, mem_addr, &data, size);
1947 : }
1948 : }
1949 :
1950 : /* memory read ---------- */
1951 0 : else if (match(param[0], "memrd")) {
1952 0 : if (current_addr < 0 && current_group < 0 && !broadcast)
1953 0 : printf("You must first address node (s)\n");
1954 : else {
1955 0 : slot = atoi(param[1]);
1956 :
1957 0 : if (param[2][1] == 'x')
1958 0 : sscanf(param[2] + 2, "%X", &mem_addr);
1959 : else
1960 0 : mem_addr = atoi(param[2]);
1961 :
1962 0 : mem_addr |= MSCB_BASE_RAM;
1963 :
1964 0 : if (param[3][1] == 'x')
1965 0 : sscanf(param[3] + 2, "%X", &size);
1966 : else
1967 0 : size = atoi(param[3]);
1968 :
1969 0 : status = mscb_read_mem(fd, (unsigned short) current_addr, slot, mem_addr, &dbuf, size);
1970 :
1971 : /* print result */
1972 0 : if (status == MSCB_SUCCESS) {
1973 0 : printf("0x%02X: ", mem_addr);
1974 0 : for (i = 0; i < size; i++)
1975 0 : printf("%02X ", (unsigned char) dbuf[i]);
1976 0 : printf("\n");
1977 : }
1978 : }
1979 : }
1980 :
1981 : /* reboot ---------- */
1982 0 : else if (match(param[0], "reboot")) {
1983 0 : if (current_addr < 0 && current_group < 0 && !broadcast)
1984 0 : printf("You must first address node (s)\n");
1985 : else {
1986 0 : status = mscb_reboot(fd, current_addr, current_group, broadcast);
1987 :
1988 0 : if (status != MSCB_SUCCESS)
1989 0 : printf("Error: %d\n", status);
1990 : }
1991 : }
1992 :
1993 : /* sr ---------- */
1994 0 : else if (match(param[0], "sr")) {
1995 0 : mscb_subm_reset(fd);
1996 : }
1997 :
1998 : /* submaster ---------- */
1999 0 : else if (match(param[0], "submaster")) {
2000 0 : mscb_subm_info(fd);
2001 : }
2002 :
2003 : /* sync ---------- */
2004 0 : else if (match(param[0], "sync")) {
2005 0 : if (current_addr < 0 && current_group < 0 && !broadcast)
2006 0 : printf("You must first address node (s)\n");
2007 : else {
2008 0 : status = mscb_set_time(fd, current_addr, current_group, broadcast);
2009 :
2010 0 : if (status != MSCB_SUCCESS)
2011 0 : printf("Error: %d\n", status);
2012 : else {
2013 0 : now = time(NULL);
2014 0 : ptm = localtime(&now);
2015 0 : printf("Synchornized to %02d-%02d-%02d %02d:%02d:%02d\n",
2016 0 : ptm->tm_mday, ptm->tm_mon + 1, ptm->tm_year - 100,
2017 : ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
2018 : }
2019 : }
2020 : }
2021 :
2022 : /* echo test ---------- */
2023 0 : else if (match(param[0], "echo")) {
2024 : unsigned char d1, d2;
2025 : int i, status;
2026 :
2027 0 : if (current_addr < 0)
2028 0 : printf("You must first address an individual node\n");
2029 : else {
2030 0 : d1 = i = 0;
2031 0 : while (!kbhit()) {
2032 0 : d1 = (d1 + 1) % 256;
2033 :
2034 0 : status = mscb_echo(fd, (unsigned short) current_addr, d1, &d2);
2035 :
2036 0 : if (status == MSCB_TIMEOUT)
2037 0 : printf("Timeout in submaster communictation\n");
2038 0 : else if (status == MSCB_TIMEOUT_BUS)
2039 0 : printf("Timeout from RS485 bus\n");
2040 0 : else if (status == MSCB_CRC_ERROR)
2041 0 : printf("CRC Error on RS485 bus\n");
2042 0 : else if (status != MSCB_SUCCESS)
2043 0 : printf("Error: %d\n", status);
2044 :
2045 0 : if (d2 != d1) {
2046 0 : printf("%d\nReceived: %02X, should be %02X, status = %d\n", i, d2, d1,
2047 : status);
2048 :
2049 0 : if (param[1][0] != 'c' && param[1][1] != 'c')
2050 0 : break;
2051 : }
2052 :
2053 0 : i++;
2054 0 : if (i % 100 == 0) {
2055 0 : printf("%d\r", i);
2056 0 : fflush(stdout);
2057 : }
2058 :
2059 0 : if (param[1][0] != 'f' && param[1][1] != 'c')
2060 0 : Sleep(10);
2061 : }
2062 0 : printf("%d\n", i);
2063 0 : while (kbhit())
2064 0 : getch();
2065 : }
2066 : }
2067 :
2068 : /* call user function ----------- */
2069 0 : else if (match(param[0], "user")) {
2070 0 : if (current_addr < 0 && current_group < 0 && !broadcast)
2071 0 : printf("You must first address node (s)\n");
2072 : else {
2073 :
2074 0 : if (param[1][0]) {
2075 0 : data = atoi(param[1]);
2076 0 : size = sizeof(status);
2077 0 : status = mscb_user(fd, current_addr, &data, 1, &status, &size);
2078 : } else {
2079 0 : status = mscb_user(fd, current_addr, NULL, 0, &data, &size);
2080 : }
2081 :
2082 0 : if (status != MSCB_SUCCESS)
2083 0 : printf("Error: %d\n", status);
2084 : }
2085 0 : } else if (match(param[0], "log")) {
2086 0 : if (broadcast)
2087 0 : printf("Log command not allowed in broadcast mode!\n");
2088 0 : else if (current_group > 0)
2089 0 : printf("Log command not allowed in group address mode!\n");
2090 0 : if (current_addr < 0)
2091 0 : printf("You must first address a single node\n");
2092 : else {
2093 :
2094 : // check first if its an SCS3000
2095 0 : memset(&info, 0, sizeof(info));
2096 0 : status = mscb_info(fd, (unsigned short) current_addr, &info);
2097 0 : if (status == MSCB_CRC_ERROR)
2098 0 : puts("CRC Error");
2099 0 : else if (status != MSCB_SUCCESS)
2100 0 : puts("node does not respond.");
2101 0 : else if (info.bootBank == 0)
2102 0 : puts("Log command not supported!");
2103 : else {
2104 0 : if (param[1][0] == 'c')
2105 : // clear log
2106 0 : status = mscb_clear_log(fd, current_addr);
2107 : else {
2108 : // +3 becasue of ACK and datalength of answer
2109 0 : char *LogMsg = &dbuf[3];
2110 :
2111 : // read log
2112 : do {
2113 0 : status = mscb_read_log(fd, current_addr, dbuf, sizeof(dbuf));
2114 :
2115 0 : if (status == MSCB_SUCCESS)
2116 0 : printf("%s", LogMsg);
2117 :
2118 0 : } while (status == MSCB_SUCCESS && *LogMsg != '\0');
2119 : }
2120 :
2121 0 : if (status != MSCB_SUCCESS)
2122 0 : printf("Error: %d\n", status);
2123 : }
2124 : }
2125 : }
2126 :
2127 : /* test1 ---------- */
2128 0 : else if (match(param[0], "t1")) {
2129 0 : data = atoi(param[1]);
2130 :
2131 : do {
2132 0 : mscb_link(fd, (unsigned short) current_addr, 4, &data, 1);
2133 0 : printf("Data: %d\r", data);
2134 0 : } while (!kbhit());
2135 0 : while (kbhit())
2136 0 : getch();
2137 : }
2138 :
2139 : /* test2 -----------*/
2140 0 : else if (match(param[0], "t2")) {
2141 : float a[16];
2142 0 : unsigned int start = ss_millitime();
2143 :
2144 0 : for (i = 0; i < 16; i++) {
2145 0 : a[i] = i * 1.01f;
2146 0 : DWORD_SWAP(&a[i]);
2147 : }
2148 0 : for (i = 0; i < 900; i++) {
2149 0 : mscb_write_range(fd, (unsigned short) current_addr, 0, 16, a, sizeof(a));
2150 0 : printf("%d\r", i);
2151 0 : if (kbhit())
2152 0 : break;
2153 : }
2154 0 : printf("\n%3.2lf sec.\n", (ss_millitime() - start) / 1000.0);
2155 0 : while (kbhit())
2156 0 : getch();
2157 : }
2158 :
2159 : /* calib1 -----------*/
2160 0 : else if (match(param[0], "c1")) {
2161 0 : status = mscb_info(fd, (unsigned short) current_addr, &info);
2162 0 : if (std::string(info.node_name) == "MPDC") {
2163 0 : uint8_t state = 0;
2164 0 : size = sizeof(state);
2165 0 : status = mscb_read(fd, (unsigned short) current_addr, 68, &state, &size);
2166 0 : if (state == 0) {
2167 0 : printf("Power (var #68) must be on for the calibration to work correctly\n");
2168 : } else {
2169 :
2170 : float current[32];
2171 0 : size = sizeof(current);
2172 0 : status = mscb_read_range(fd, (unsigned short) current_addr, 32, 63, current, &size);
2173 :
2174 0 : for (i = 0; i < 32; i++) {
2175 0 : DWORD_SWAP(¤t[i]);
2176 : // printf("I%d: %1.2lf\n", i, current[i]);
2177 : }
2178 :
2179 : float current_offset[32];
2180 0 : size = sizeof(current_offset);
2181 0 : status = mscb_read_range(fd, (unsigned short) current_addr, 70, 101, current_offset, &size);
2182 :
2183 0 : for (i = 0; i < 32; i++) {
2184 0 : DWORD_SWAP(¤t_offset[i]);
2185 : // printf("IOfs%d: %1.2lf\n", i, current_offset[i]);
2186 : }
2187 :
2188 : // do correction
2189 0 : for (i = 0; i < 32; i++)
2190 0 : current_offset[i] += current[i];
2191 :
2192 : // write back offsets
2193 0 : size = sizeof(current_offset);
2194 0 : for (i = 0; i < 32; i++) {
2195 0 : printf("IOfs%d = %1.2lf\n", i, current_offset[i]);
2196 0 : status = mscb_write(fd, (unsigned short) current_addr, 70 + i, ¤t_offset[i], sizeof(float));
2197 : }
2198 :
2199 0 : if (status == MSCB_SUCCESS)
2200 0 : printf("\nCurrent offsets successfully updated, please flash values\n");
2201 : else
2202 0 : printf("Error %d\n", status);
2203 : }
2204 : } else
2205 0 : printf("MPDC device not present\n");
2206 : }
2207 :
2208 : /* exit/quit ---------- */
2209 0 : else if (match(param[0], "exit") || match(param[0], "quit"))
2210 0 : break;
2211 :
2212 0 : else if (param[0][0] == 0);
2213 :
2214 0 : else if (param[0][0] == '\n');
2215 :
2216 : else
2217 0 : printf("Unknown command %s %s %s\n", param[0], param[1], param[2]);
2218 :
2219 : /* exit after single command */
2220 0 : if (cmd[0] && cmd[0] != '@')
2221 0 : break;
2222 :
2223 0 : } while (1);
2224 : }
2225 :
2226 : /*------------------------------------------------------------------*/
2227 :
2228 0 : int main(int argc, char *argv[]) {
2229 : int i, fd, server, scan;
2230 : unsigned short adr;
2231 : char cmd[256], device[256], str[256], password[256], ip[256];
2232 : int debug;
2233 :
2234 0 : cmd[0] = 0;
2235 0 : adr = 0;
2236 :
2237 0 : debug = server = scan = 0;
2238 0 : device[0] = password[0] = 0;
2239 :
2240 : /* parse command line parameters */
2241 0 : for (i = 1; i < argc; i++) {
2242 0 : if (argv[i][0] == '-' && argv[i][1] == 'v')
2243 0 : debug = 2;
2244 0 : else if (argv[i][0] == '-' && argv[i][1] == 'w')
2245 0 : debug = 1;
2246 0 : else if (argv[i][0] == '-' && argv[i][1] == 'r')
2247 0 : server = 1;
2248 0 : else if (argv[i][0] == '-' && argv[i][1] == 's')
2249 0 : scan = 1;
2250 0 : else if (argv[i][0] == '-') {
2251 0 : if (i + 1 >= argc || argv[i + 1][0] == '-')
2252 0 : goto usage;
2253 0 : else if (argv[i][1] == 'd')
2254 0 : strcpy(device, argv[++i]);
2255 0 : else if (argv[i][1] == 'p')
2256 0 : strcpy(password, argv[++i]);
2257 0 : else if (argv[i][1] == 'a')
2258 0 : adr = atoi(argv[++i]);
2259 0 : else if (argv[i][1] == 'c') {
2260 0 : if (strlen(argv[i]) >= 256) {
2261 0 : printf("error: command line too long (>256).\n");
2262 0 : return 0;
2263 : }
2264 0 : strcpy(cmd, argv[++i]);
2265 : } else {
2266 0 : usage:
2267 : printf
2268 0 : ("usage: msc [-d host:device] [-p password] [-a addr] [-c Command] [-c @CommandFile] [-v] [-s]\n\n");
2269 0 : printf(" -d device, \"<host>:usb0\" for RPC connection\n");
2270 : printf
2271 0 : (" or \"mscb<xxx>\" for Ethernet connection to SUBM_260\n");
2272 0 : printf(" -p optional password for SUBM_260\n");
2273 0 : printf(" -r Start RPC server\n");
2274 0 : printf(" -s Scan for Ethernet submasters on local net\n");
2275 0 : printf(" -a Address node before executing command\n");
2276 0 : printf(" -c Execute command immediately\n");
2277 0 : printf(" -v Produce verbose debugging output into mscb_debug.log\n");
2278 0 : printf(" -w Log all write commands to mscb_write.log\n\n");
2279 0 : printf("For a list of valid commands start msc interactively\n");
2280 0 : printf("and type \"help\".\n");
2281 0 : return 0;
2282 : }
2283 : }
2284 : }
2285 :
2286 0 : if (server) {
2287 : #ifdef HAVE_MRPC
2288 : mrpc_server_loop();
2289 : #endif
2290 0 : return 0;
2291 : }
2292 :
2293 0 : if (scan) {
2294 0 : mscb_scan_udp();
2295 0 : return 0;
2296 : }
2297 :
2298 0 : if (device[0])
2299 0 : host2ip(device, ip, sizeof(ip));
2300 : else
2301 0 : ip[0] = 0;
2302 :
2303 0 : if (device[0] == 0) {
2304 0 : printf("Please specify MSCB submaster via -d flag\n");
2305 0 : return 0;
2306 : }
2307 :
2308 : /* open port */
2309 0 : fd = mscb_init(device, sizeof(device), password, debug);
2310 :
2311 0 : if (fd == EMSCB_WRONG_PASSWORD) {
2312 0 : printf("Enter password to access %s: ", device);
2313 0 : fgets(str, sizeof(str), stdin);
2314 0 : while (strlen(str) > 0
2315 0 : && (str[strlen(str) - 1] == '\r' || str[strlen(str) - 1] == '\n'))
2316 0 : str[strlen(str) - 1] = 0;
2317 0 : fd = mscb_init(device, sizeof(device), str, debug);
2318 : }
2319 :
2320 0 : if (fd < 0) {
2321 0 : if (fd == EMSCB_COMM_ERROR) {
2322 0 : printf("\nCannot communicate with MSCB submaster %s (%s)\n", device, ip);
2323 0 : puts("Please disconnect and reconnect submaster\n");
2324 0 : } else if (fd == EMSCB_PROTOCOL_VERSION) {
2325 0 : printf("\nSubmaster %s (%s) runs old protocol version\n", device, ip);
2326 0 : puts("Please upgrade submaster software\n");
2327 0 : } else if (fd == EMSCB_NOT_FOUND) {
2328 : #ifdef HAVE_USB
2329 : printf("\nCannot find USB submaster\n");
2330 : #else
2331 0 : printf("\nNo USB support available in this verson of msc\n");
2332 0 : printf("An ethernet node address must explicitly be supplied via the '-d [host]' flag\n");
2333 : #endif
2334 0 : } else if (fd == EMSCB_WRONG_PASSWORD) {
2335 0 : printf("\nWrong password\n");
2336 0 : } else if (fd == EMSCB_NO_WRITE_ACCESS) {
2337 0 : printf("\nNo write access to MSCB submaster %s (%s)\n", device, ip);
2338 0 : puts("Please install hotplug script \"drivers/linux/usb.usermap_scs_250\" to \"/etc/hotplug/\".\n");
2339 0 : } else if (fd == EMSCB_LOCKED) {
2340 0 : puts("\nMSCB system is locked by other process");
2341 0 : puts("Please stop all running MSCB clients\n");
2342 0 : } else if (device[0])
2343 0 : printf("Cannot connect to device \"%s\" (%s)\n", device, ip);
2344 : else
2345 0 : printf("Please specify MSCB submaster via -d flag\n");
2346 :
2347 : #ifdef _MSC_VER
2348 : puts("\n-- hit any key to exit --");
2349 :
2350 : while (!kbhit())
2351 : Sleep(100);
2352 : while (kbhit())
2353 : getch();
2354 : #endif
2355 :
2356 0 : return 0;
2357 : }
2358 :
2359 0 : printf("Connected to submaster %s (%s)\n", device, ip);
2360 :
2361 0 : cmd_loop(fd, cmd, adr);
2362 :
2363 0 : mscb_exit(fd);
2364 :
2365 0 : return 0;
2366 : }
|