/********************************************************************\ Name: msc.c Created by: Stefan Ritt Contents: Command-line interface for the Midas Slow Control Bus $Id$ \********************************************************************/ #ifdef _MSC_VER #define OS_WINNT #endif #if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__) #define OS_LINUX #endif #ifdef OS_WINNT #include #include #include #include #include #elif defined(OS_LINUX) #define O_BINARY 0 #include #include #include #include #include #include #endif #include "mscb.h" #include "mscbxx.h" #include #include #include #include #include #include #include #include "mscbrpc.h" #include "mxml.h" #include "mstrlcpy.h" extern int cmd_edit(const char *prompt, char *cmd, int(*dir)(char *, int *), int(*idle)(void)); int cmd_dir(char *line, int *cursor) { return FALSE; } /*------------------------------------------------------------------*/ typedef struct { char id; char name[32]; } NAME_TABLE; NAME_TABLE prefix_table[] = { {(char) PRFX_PICO, "pico",}, {(char) PRFX_NANO, "nano",}, {(char) PRFX_MICRO, "micro",}, {(char) PRFX_MILLI, "milli",}, {(char) PRFX_NONE, "",}, {(char) PRFX_KILO, "kilo",}, {(char) PRFX_MEGA, "mega",}, {(char) PRFX_GIGA, "giga",}, {(char) PRFX_TERA, "tera",}, {(char) 99} }; NAME_TABLE unit_table[] = { {UNIT_METER, "meter",}, {UNIT_GRAM, "gram",}, {UNIT_SECOND, "second",}, {UNIT_MINUTE, "minute",}, {UNIT_HOUR, "hour",}, {UNIT_AMPERE, "ampere",}, {UNIT_KELVIN, "kelvin",}, {UNIT_CELSIUS, "deg. celsius",}, {UNIT_FARENHEIT, "deg. farenheit",}, {UNIT_HERTZ, "hertz",}, {UNIT_PASCAL, "pascal",}, {UNIT_BAR, "bar",}, {UNIT_WATT, "watt",}, {UNIT_VOLT, "volt",}, {UNIT_OHM, "ohm",}, {UNIT_TESLA, "tesls",}, {UNIT_LITERPERSEC, "liter/sec",}, {UNIT_RPM, "RPM",}, {UNIT_FARAD, "farad",}, {UNIT_BOOLEAN, "boolean",}, {UNIT_BYTE, "byte",}, {UNIT_WORD, "word",}, {UNIT_DWORD, "dword",}, {UNIT_ASCII, "ascii",}, {UNIT_STRING, "string",}, {UNIT_BAUD, "baud",}, {UNIT_PERCENT, "percent",}, {UNIT_PPM, "RPM",}, {UNIT_COUNT, "counts",}, {UNIT_FACTOR, "factor",}, {0} }; /*------------------------------------------------------------------*/ /* special characters */ #define CH_BS 8 #define CH_TAB 9 #define CH_CR 13 #define CH_EXT 0x100 #define CH_HOME (CH_EXT+0) #define CH_INSERT (CH_EXT+1) #define CH_DELETE (CH_EXT+2) #define CH_END (CH_EXT+3) #define CH_PUP (CH_EXT+4) #define CH_PDOWN (CH_EXT+5) #define CH_UP (CH_EXT+6) #define CH_DOWN (CH_EXT+7) #define CH_RIGHT (CH_EXT+8) #define CH_LEFT (CH_EXT+9) int ss_getchar(int reset) { #ifdef OS_LINUX static int init = FALSE; static struct termios save_termios; struct termios buf; int i, fd; char c[3]; fd = fileno(stdin); if (reset) { if (init) tcsetattr(fd, TCSAFLUSH, &save_termios); init = FALSE; return 0; } if (!init) { tcgetattr(fd, &save_termios); memcpy(&buf, &save_termios, sizeof(buf)); buf.c_lflag &= ~(ECHO | ICANON | IEXTEN); buf.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON); buf.c_cflag &= ~(CSIZE | PARENB); buf.c_cflag |= CS8; /* buf.c_oflag &= ~(OPOST); */ buf.c_cc[VMIN] = 0; buf.c_cc[VTIME] = 0; tcsetattr(fd, TCSAFLUSH, &buf); init = TRUE; } memset(c, 0, 3); i = read(fd, c, 1); if (i == 0) { Sleep(10); return 0; } /* check if ESC */ if (c[0] == 27) { i = read(fd, c, 2); if (i == 0) /* return if only ESC */ return 27; /* cursor keys return 2 chars, others 3 chars */ if (c[1] < 65) read(fd, c, 1); /* convert ESC sequence to CH_xxx */ switch (c[1]) { case 49: return CH_HOME; case 50: return CH_INSERT; case 51: return CH_DELETE; case 52: return CH_END; case 53: return CH_PUP; case 54: return CH_PDOWN; case 65: return CH_UP; case 66: return CH_DOWN; case 67: return CH_RIGHT; case 68: return CH_LEFT; } } /* BS/DEL -> BS */ if (c[0] == 127) return CH_BS; return c[0]; #elif defined(OS_WINNT) static BOOL init = FALSE; static INT repeat_count = 0; static INT repeat_char; HANDLE hConsole; DWORD nCharsRead; INPUT_RECORD ir; hConsole = GetStdHandle(STD_INPUT_HANDLE); if (reset) { SetConsoleMode(hConsole, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); init = FALSE; return 0; } if (!init) { SetConsoleMode(hConsole, ENABLE_PROCESSED_INPUT); init = TRUE; } if (repeat_count) { repeat_count--; return repeat_char; } PeekConsoleInput(hConsole, &ir, 1, &nCharsRead); if (nCharsRead == 0) return 0; ReadConsoleInput(hConsole, &ir, 1, &nCharsRead); if (ir.EventType != KEY_EVENT) return ss_getchar(0); if (!ir.Event.KeyEvent.bKeyDown) return ss_getchar(0); if (ir.Event.KeyEvent.wRepeatCount > 1) { repeat_count = ir.Event.KeyEvent.wRepeatCount - 1; repeat_char = ir.Event.KeyEvent.uChar.AsciiChar; return repeat_char; } if (ir.Event.KeyEvent.uChar.AsciiChar) return ir.Event.KeyEvent.uChar.AsciiChar; if (ir.Event.KeyEvent.dwControlKeyState & (ENHANCED_KEY)) { switch (ir.Event.KeyEvent.wVirtualKeyCode) { case 33: return CH_PUP; case 34: return CH_PDOWN; case 35: return CH_END; case 36: return CH_HOME; case 37: return CH_LEFT; case 38: return CH_UP; case 39: return CH_RIGHT; case 40: return CH_DOWN; case 45: return CH_INSERT; case 46: return CH_DELETE; } return ir.Event.KeyEvent.wVirtualKeyCode; } return ss_getchar(0); #endif return -1; } /*------------------------------------------------------------------*/ unsigned int ss_millitime() { #ifdef OS_WINNT return (int) GetTickCount(); #endif /* OS_WINNT */ #ifdef OS_LINUX { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000 + tv.tv_usec / 1000; } #endif /* OS_LINUX */ return 0; } /*------------------------------------------------------------------*/ char *ss_gets(char *string, int size) { char *p; do { p = fgets(string, size, stdin); } while (p == NULL); if (strlen(p) > 0 && p[strlen(p) - 1] == '\n') p[strlen(p) - 1] = 0; return p; } /*------------------------------------------------------------------*/ void print_help() { puts("Available commands:\n"); puts("addr Address individual node"); puts("baddr Address all nodes (broadcast)"); puts("baud Set baud rate of MSCB bus"); puts("debug 0/1/2 Turn debuggin off/on, 2=show on screen"); puts("echo [fc] Perform echo test [fast,continuous]"); puts("flash Flash parameters into EEPROM"); puts("gaddr Address group of nodes"); puts("info Retrive node info"); puts("load Load node variables"); puts("ping [r] Ping node and set address [repeat mode]"); puts("read [r] [a] Read node variable [repeat mode] [all variables]"); puts("read - [r] [a] Read range of node variables [repeat] [all]"); puts("reboot Reboot addressed node"); puts("sa Set node address of addressed node"); puts("save [first last] Save current node variables [save range]"); puts("scan [r] [a] [q] Scan bus for nodes [repeat mode] [all] [quick]"); puts("sg Set group address of addressed node(s)"); puts("sn Set node name (up to 16 characters)"); puts("sr Reset current submaster"); puts("submaster Show info for current submaster"); puts("sync Synchronize local time with node(s)"); puts("terminal Enter teminal mode for SCS-210"); puts("upload [slot] [debug] Upload new firmware to node in [slot] [with debug info]"); puts("download [slot] Download firmware from node in [slot] to file"); puts("memrd Read from memory in "); puts("memwr Write to memory in "); puts("mup Upload new firmware to nodes a1-a2"); puts("mwr Write a variable to nodes from to "); puts("verify [adr] Compare current firmware in [adr] with file"); puts("version Display version number"); puts("write [r] Write node variable"); puts("write - Write range of node variables"); puts("log [c] Read log / clear Log [c]"); puts(""); } /*------------------------------------------------------------------*/ void print_channel_str(int index, MSCB_INFO_VAR *info_chn, void *pdata, int verbose, char *line) { char str[80]; int i, data; line[0] = 0; if (verbose) { memset(str, 0, sizeof(str)); strncpy(str, info_chn->name, sizeof(str)); for (i = strlen(str); i < (int) sizeof(info_chn->name) + 1; i++) str[i] = ' '; snprintf(line + strlen(line), 256 - strlen(line), "%3d: %s ", index, str); } else { memset(str, 0, sizeof(str)); strncpy(str, info_chn->name, sizeof(str)); snprintf(line, 256, "%s: ", str); } if (info_chn->unit == UNIT_STRING) { memset(str, 0, sizeof(str)); strncpy(str, (const char *) pdata, info_chn->width); if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "STR%02d \"", info_chn->width); for (i = 0; i < (int) strlen(str); i++) switch (str[i]) { case 1: strcat(line, "\\001"); break; case 2: strcat(line, "\\002"); break; case 9: strcat(line, "\\t"); break; case 10: strcat(line, "\\n"); break; case 13: strcat(line, "\\r"); break; default: line[strlen(line) + 1] = 0; line[strlen(line)] = str[i]; break; } strcat(line, "\""); } else { data = *((int *) pdata); switch (info_chn->width) { case 0: printf(" 0bit"); break; case 1: data &= 0xFF; if (info_chn->flags & MSCBF_SIGNED) { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), " 8bit S %15d (0x%02X/", (char) data, data); else snprintf(line + strlen(line), 256 - strlen(line), "%15d (0x%02X/", (char) data, data); } else { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), " 8bit U %15u (0x%02X/", data, data); else snprintf(line + strlen(line), 256 - strlen(line), "%15u (0x%02X/", data, data); } for (i = 0; i < 8; i++) if (data & (0x80 >> i)) snprintf(line + strlen(line), 256 - strlen(line), "1"); else snprintf(line + strlen(line), 256 - strlen(line), "0"); snprintf(line + strlen(line), 256 - strlen(line), ")"); break; case 2: data &= 0xFFFF; if (info_chn->flags & MSCBF_SIGNED) { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "16bit S %15d (0x%04X)", (short) data, data); else snprintf(line + strlen(line), 256 - strlen(line), "%15d (0x%04X)", (short) data, data); } else { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "16bit U %15u (0x%04X)", data, data); else snprintf(line + strlen(line), 256 - strlen(line), "%15u (0x%04X)", data, data); } break; case 3: data &= 0xFFFFFF; if (info_chn->flags & MSCBF_SIGNED) { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "24bit S %15ld (0x%06X)", (long) data, data); else snprintf(line + strlen(line), 256 - strlen(line), "%15ld (0x%06X)", (long) data, data); } else { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "24bit U %15u (0x%06X)", data, data); else snprintf(line + strlen(line), 256 - strlen(line), "%15ld (0x%06X)", (long) data, data); } break; case 4: data &= 0xFFFFFFFF; if (info_chn->flags & MSCBF_FLOAT) { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "32bit F %15.6lg", *((float *) (void *) &data)); else snprintf(line + strlen(line), 256 - strlen(line), "%15.6lg", *((float *) (void *) &data)); } else { if (info_chn->flags & MSCBF_SIGNED) { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "32bit S %15d (0x%08X)", data, data); else snprintf(line + strlen(line), 256 - strlen(line), "%15d (0x%08X)", data, data); } else { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "32bit U %15u (0x%08X)", data, data); else snprintf(line + strlen(line), 256 - strlen(line), "%15u (0x%08X)", data, data); } } break; case 8: unsigned long int qdata = *((unsigned long int *) pdata); if (info_chn->flags & MSCBF_SIGNED) { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "64bit S (0x%016lX) %ld", qdata, qdata); else snprintf(line + strlen(line), 256 - strlen(line), "(0x%016lX) %ld", qdata, qdata); } else { if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "64bit U (0x%016lX) %lu", qdata, qdata); else snprintf(line + strlen(line), 256 - strlen(line), "(0x%016lX) %lu", qdata, qdata); } break; } } snprintf(line + strlen(line), 256 - strlen(line), " "); /* evaluate prefix */ if (info_chn->prefix) { for (i = 0; prefix_table[i].id != 99; i++) if ((unsigned char) prefix_table[i].id == info_chn->prefix) break; if (prefix_table[i].id) strcpy(line + strlen(line), prefix_table[i].name); } /* evaluate unit */ if (info_chn->unit && info_chn->unit != UNIT_STRING) { for (i = 0; unit_table[i].id; i++) if ((unsigned char) unit_table[i].id == info_chn->unit) break; if (unit_table[i].id) strcpy(line + strlen(line), unit_table[i].name); } if (verbose) snprintf(line + strlen(line), 256 - strlen(line), "\n"); else snprintf(line + strlen(line), 256 - strlen(line), " \r"); } void print_channel(int index, MSCB_INFO_VAR *info_chn, void *pdata, int verbose) { char str[256]; print_channel_str(index, info_chn, pdata, verbose, str); fputs(str, stdout); } /*------------------------------------------------------------------*/ void save_node_xml(MXML_WRITER *writer, int fd, int addr) { int i, j, status, size; char str[256], line[256], data[256]; MSCB_INFO info; MSCB_INFO_VAR info_var; status = mscb_info(fd, (unsigned short) addr, &info); if (status == MSCB_CRC_ERROR) { puts("CRC Error"); return; } else if (status != MSCB_SUCCESS) { puts("No response from node"); return; } mxml_start_element(writer, "Node"); mxml_start_element(writer, "Name"); mxml_write_value(writer, info.node_name); mxml_end_element(writer); mxml_start_element(writer, "NodeAddress"); snprintf(str, sizeof(str), "%d (0x%X)", addr, addr); mxml_write_value(writer, str); mxml_end_element(writer); mxml_start_element(writer, "GroupAddress"); snprintf(str, sizeof(str), "%d (0x%X)", info.group_address, info.group_address); mxml_write_value(writer, str); mxml_end_element(writer); mxml_start_element(writer, "ProtocolVersion"); snprintf(str, sizeof(str), "%d.%d", info.protocol_version / 16, info.protocol_version % 16); mxml_write_value(writer, str); mxml_end_element(writer); mxml_start_element(writer, "Variables"); for (i = 0; i < info.n_variables; i++) { mxml_start_element(writer, "Variable"); mscb_info_variable(fd, (unsigned short) addr, (unsigned char) i, &info_var); size = sizeof(data); mscb_read(fd, (unsigned short) addr, (unsigned char) i, data, &size); mxml_start_element(writer, "Index"); snprintf(str, sizeof(str), "%d", i); mxml_write_value(writer, str); mxml_end_element(writer); mxml_start_element(writer, "Name"); strncpy(str, info_var.name, sizeof(str)); str[8] = 0; mxml_write_value(writer, str); mxml_end_element(writer); mxml_start_element(writer, "Width"); snprintf(str, sizeof(str), "%dbit", info_var.width * 8); mxml_write_value(writer, str); mxml_end_element(writer); print_channel_str(i, &info_var, data, 1, line); mstrlcpy(str, line + 21, sizeof(str)); for (j = 0; j < (int) strlen(str); j++) if (str[j] == ' ') break; str[j] = 0; mxml_start_element(writer, "Flags"); mxml_write_value(writer, str); mxml_end_element(writer); mstrlcpy(str, line + 21 + j, sizeof(str)); for (j += 21; j < (int) strlen(line); j++) if (line[j] != ' ') break; mstrlcpy(str, line + j, sizeof(str)); for (j = 0; j < (int) strlen(str); j++) if (str[j] == ' ') break; str[j] = 0; mxml_start_element(writer, "Value"); mxml_write_value(writer, str); mxml_end_element(writer); if (line[39] == '(') { mstrlcpy(str, line + 40, sizeof(str)); for (j = 0; j < (int) strlen(str); j++) if (str[j] == ')') break; str[j] = 0; mxml_start_element(writer, "HexBinValue"); mxml_write_value(writer, str); mxml_end_element(writer); j += 42; } else j = 39; mstrlcpy(str, line + j, sizeof(str)); for (j = 0; j < (int) strlen(str); j++) if (!isalnum(str[j])) break; str[j] = 0; mxml_start_element(writer, "Unit"); mxml_write_value(writer, str); mxml_end_element(writer); mxml_end_element(writer); // "Variable" } mxml_end_element(writer); // "Variables" mxml_end_element(writer); // "Node" } /*------------------------------------------------------------------*/ void load_nodes_xml(int fd, char *file_name, int flash) { int i, j, index, status, ivar, addr; char str[256], error[256], chn_name[256][17], name[256], value[256]; unsigned int data; float fvalue; PMXML_NODE root, node, nvarroot, nvar, nsub; MSCB_INFO info; MSCB_INFO_VAR info_var; root = mxml_parse_file(file_name, error, sizeof(error), NULL); if (root == NULL) { printf("Error loading \"%s\": %s\n", file_name, error); return; } root = mxml_find_node(root, "/MSCBDump"); if (root == NULL) { printf("Error loading \"%s\": No MSCBDump structure in file\n", file_name); return; } /* loop over all nodes in file */ for (index = 0; index < mxml_get_number_of_children(root); index++) { node = mxml_subnode(root, index); nsub = mxml_find_node(node, "NodeAddress"); if (nsub == NULL) { printf("Error loading \"%s\": Node #%d does not contain NodeAddress\n", file_name, index); return; } printf("\nLoading node #%s\n", mxml_get_value(nsub)); addr = atoi(mxml_get_value(nsub)); nvarroot = mxml_find_node(node, "Variables"); if (nvarroot == NULL) { printf("Error loading \"%s\": Node #%d does not contain Variables\n", file_name, index); return; } /* get list of channel names from node */ if (mscb_info(fd, (unsigned short) addr, &info) != MSCB_SUCCESS) { printf("No response from node %d, skip node.\n", addr); continue; } memset(chn_name, 0, sizeof(chn_name)); for (i = 0; i < info.n_variables; i++) { mscb_info_variable(fd, (unsigned short) addr, (unsigned char) i, &info_var); strncpy(chn_name[i], info_var.name, sizeof(chn_name[i])); } /* loop over variables */ for (ivar = 0; ivar < mxml_get_number_of_children(nvarroot); ivar++) { nvar = mxml_subnode(nvarroot, ivar); nsub = mxml_find_node(nvar, "Index"); if (nsub == NULL) { printf("Found variable without index\n"); continue; } nsub = mxml_find_node(nvar, "Name"); if (nsub == NULL) { printf("Found variable without name\n"); continue; } strcpy(name, mxml_get_value(nsub)); nsub = mxml_find_node(nvar, "Value"); if (nsub == NULL) { printf("Found variable without value\n"); continue; } strcpy(value, mxml_get_value(nsub)); /* search for channel with same name */ for (i = 0; chn_name[i][0]; i++) if (strcmp(chn_name[i], name) == 0) { mscb_info_variable(fd, (unsigned short) addr, (unsigned char) i, &info_var); if (info_var.unit == UNIT_STRING) { memset(str, 0, sizeof(str)); mstrlcpy(str, value, sizeof(str)); str[info_var.width] = 0; if (strlen(str) > 0 && str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = 0; status = mscb_write(fd, (unsigned short) addr, (unsigned char) i, str, info_var.width); if (status != MSCB_SUCCESS) printf("Error writing to node %d, variable %d\n", addr, i); } else { if (info_var.flags & MSCBF_FLOAT) { fvalue = (float) atof(value); memcpy(&data, &fvalue, sizeof(float)); } else { data = atoi(value); } status = mscb_write(fd, (unsigned short) addr, (unsigned char) i, &data, info_var.width); if (status != MSCB_SUCCESS) printf("Error writing to node %d, variable %d\n", addr, i); /* blank padding */ for (j = strlen(name); j < 8; j++) name[j] = ' '; name[j] = 0; printf("%3d: %s %s\n", i, name, value); } break; } if (chn_name[i][0] == 0) printf("Variable \"%s\" from file not in node, variable skipped\n", name); } if (flash) mscb_flash(fd, addr, -1, 0); } } /*------------------------------------------------------------------*/ int match(const char *str, const char *cmd) { int i; if (str[0] == '\r' || str[0] == '\n' || str[0] == 0) return 0; for (i = 0; i < (int) strlen(str); i++) { if (toupper(str[i]) != toupper(cmd[i]) && str[i] != '\r' && str[i] != '\n') return 0; } return 1; } /*------------------------------------------------------------------*/ void cmd_loop(int fd, char *cmd, unsigned short adr) { int i, j, status, size, nparam, current_addr, current_group, reference_addr, first, last, broadcast, read_all, repeat, index, idx1, idx2, wait = 0, n_found, slot; int ping_addr[0x10000]; unsigned short addr; unsigned int data, uptime, mem_addr; unsigned long int qdata; unsigned char c; float value; char str[256], line[256], dbuf[100 * 1024], param[10][100], *pc, lib[32], prot[32], *pdata, prompt[256], filename[256]; FILE *cmd_file = NULL; MSCB_INFO info; MSCB_INFO_VAR info_var_array[256]; MSCB_INFO_VAR info_var; time_t now; MXML_WRITER *writer; struct tm *ptm; /* open command file */ if (cmd[0] == '@') { cmd_file = fopen(cmd + 1, "r"); if (cmd_file == NULL) { printf("Command file %s not found.\n", cmd + 1); return; } } if (cmd[0]) /* assumed some node correctly addressed in command mode */ current_addr = 0; else current_addr = -1; current_group = -1; if (adr) current_addr = adr; broadcast = 0; reference_addr = 0; status = 0; /* fill table of possible addresses */ for (i = 0; i < 0x10000; i++) ping_addr[i] = 0; for (i = 0; i < 1000; i++) // 0..999 ping_addr[i] = 1; for (i = 0; i < 0x10000; i += 100) // 100, 200, ... ping_addr[i] = 1; for (i = 0; i < 0x10000; i += 0x100) ping_addr[i] = 1; // 256, 512, ... for (i = 0xFF00; i < 0xFFFF; i++) ping_addr[i] = 1; // 0xFF00-0xFFFF do { /* print prompt */ if (!cmd[0]) { if (current_addr >= 0) snprintf(prompt, sizeof(prompt), "node%d(0x%X)> ", current_addr, current_addr); else if (current_group >= 0) snprintf(prompt, sizeof(prompt), "group%d> ", current_group); else if (broadcast) snprintf(prompt, sizeof(prompt), "all> "); else snprintf(prompt, sizeof(prompt), "> "); memset(line, 0, sizeof(line)); cmd_edit(prompt, line, cmd_dir, NULL); } else if (cmd[0] != '@') strcpy(line, cmd); else { memset(line, 0, sizeof(line)); fgets(line, sizeof(line), cmd_file); if (line[0] == 0) break; /* cut off CR */ while (strlen(line) > 0 && line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = 0; if (line[0] == 0) continue; } /* analyze line */ nparam = 0; pc = line; while (*pc == ' ') pc++; memset(param, 0, sizeof(param)); do { if (*pc == '"') { pc++; for (i = 0; *pc && *pc != '"'; i++) param[nparam][i] = *pc++; if (*pc) pc++; } else if (*pc == '\'') { pc++; for (i = 0; *pc && *pc != '\''; i++) param[nparam][i] = *pc++; if (*pc) pc++; } else if (*pc == '`') { pc++; for (i = 0; *pc && *pc != '`'; i++) param[nparam][i] = *pc++; if (*pc) pc++; } else for (i = 0; *pc && *pc != ' '; i++) param[nparam][i] = *pc++; param[nparam][i] = 0; while (*pc == ' ' || *pc == '\r' || *pc == '\n') pc++; nparam++; } while (*pc); /* help ---------- */ if ((param[0][0] == 'h' && param[0][1] == 'e') || param[0][0] == '?') print_help(); /* version ---------- */ else if (match(param[0], "version")) { mscb_get_version(lib, prot); printf("MSCB library version : %s\n", lib); printf("MSCB protocol version : %s\n", prot); } /* debug ---------- */ if (match(param[0], "debug")) { mscb_debug(atoi(param[1])); printf("Debugging level changed successfully.\n"); } /* scan ---------- */ else if (match(param[0], "scan")) { do { n_found = 0; int quick = 0; if (param[1][0] == 'q' || param[2][0] == 'q') quick = 1; for (i = 0; i < 0x10000; i++) { if (i != -1 && param[1][0] != 'a' && param[2][0] != 'a' && i > 0 && !ping_addr[i]) continue; if (i == -1) printf("Test address 65535 (0xFFFF)\r"); else printf("Test address %05d (0x%04X)\r", i, i); fflush(stdout); if (i == -1) { /* do the first time with retry, to send '0's */ status = mscb_ping(fd, (unsigned short) 0xFFFF, 0, 0); Sleep(100); } else status = mscb_ping(fd, (unsigned short) i, quick, 0); if (status == MSCB_SUCCESS) { n_found++; /* node found, search next 100 as well */ for (j = i; j < i + 100 && j < 0x10000; j++) if (j >= 0) ping_addr[j] = 1; status = mscb_info(fd, (unsigned short) i, &info); strncpy(str, info.node_name, sizeof(str)); str[16] = 0; if (status == MSCB_SUCCESS) { printf ("Found node \"%s\", NA %d (0x%04X), GA %d (0x%04X), Rev. 0x%04X \n", str, (unsigned short) i, (unsigned short) i, info.group_address, info.group_address, info.revision); mscb_get_version(lib, prot); if (info.protocol_version != atoi(prot)) { printf ("WARNING: Protocol version on node (%d) differs from local version (%s).\n", info.protocol_version, prot); } } } else if (status == MSCB_SUBM_ERROR) { printf("Error: Submaster not responding\n"); break; } if (kbhit()) break; } } while ((param[1][0] == 'r' || param[2][0] == 'r') && !kbhit()); while (kbhit()) getch(); printf(" \n"); if (n_found == 0) printf("No nodes found \n"); else if (n_found == 1) printf("One node found \n"); else if (n_found > 0) printf("%d nodes found \n", n_found); } /* info ---------- */ else if (match(param[0], "info")) { if (current_addr < 0) printf("You must first address an individual node\n"); else { status = mscb_info(fd, (unsigned short) current_addr, &info); if (status == MSCB_CRC_ERROR) puts("CRC Error"); else if (status != MSCB_SUCCESS) puts("No response from node"); else { strncpy(str, info.node_name, sizeof(str)); str[16] = 0; printf("Node name : %s\n", str); printf("Node address : %d (0x%X)\n", info.node_address, info.node_address); printf("Group address : %d (0x%X)\n", info.group_address, info.group_address); printf("Protocol version : %d\n", info.protocol_version); // check if it's an SCS3000 or not if (info.pinExt_resets == 0) { printf("Revision : 0x%04X\n", info.revision); } else { printf("Revision : V %d.%d.%d\n", info.revision >> 8, (info.revision >> 4) & 0xF, info.revision & 0xF); } if (info.rtc[0] && info.rtc[0] != 0xFF) { for (i = 0; i < 6; i++) info.rtc[i] = (info.rtc[i] / 0x10) * 10 + info.rtc[i] % 0x10; printf("Real Time Clock : %02d-%02d-%02d %02d:%02d:%02d\n", info.rtc[0], info.rtc[1], info.rtc[2], info.rtc[3], info.rtc[4], info.rtc[5]); } status = mscb_uptime(fd, (unsigned short) current_addr, &uptime); if (status == MSCB_SUCCESS) printf("Uptime : %dd %02dh %02dm %02ds\n", uptime / (3600 * 24), (uptime % (3600 * 24)) / 3600, (uptime % 3600) / 60, (uptime % 60)); if (info.buf_size != 0) printf("Buffer size : %d\n", info.buf_size); // print variables for SCS3000 if (info.bootBank != 0) { printf("Pin/Ext WD Resets : %d\n", info.pinExt_resets); printf("SW-resets : %d\n", info.SW_resets); printf("Int. WD resets : %d\n", info.int_WD_resets); printf("Boot-Bank : %d\n", info.bootBank); printf("Silicon Revision : %c\n", info.siliconRevison); printf("System load : %4.2f%%\n", info.systemLoad); printf("Peak system load : %4.2f%%\n", info.peakSystemLoad); printf("PCB Temp : %4.2f%cC\n", info.pcbTemp, 167); // 167 is � symbol printf("Supply 1.8V : %4.2fV\n", info.Supply1V8); printf("Supply 3.3V : %4.2fV\n", info.Supply3V3); printf("Supply 5.0V : %4.2fV\n", info.Supply5V0); printf("Supply 24.0V : %4.2fV\n", info.Supply24V0); printf("Supply 5V Ext. : %4.2fV\n", info.Supply5V0Ext); printf("Supply 24V Ext. : %4.2fV\n", info.Supply24V0Ext); printf("Supply current : %4.3fA\n", info.Supply24V0Current); printf("Battery voltage : %4.2fV\n", info.Vbat); } mscb_get_version(lib, prot); if (info.protocol_version != atoi(prot)) { printf ("\nWARNING: Protocol version on node (%d) differs from local version (%s).\n", info.protocol_version, prot); printf ("Problems may arise communicating with this node. Please upgrade.\n\n"); } } } } /* ping ---------- */ else if (match(param[0], "ping")) { if (!param[1][0]) puts("Please specify node address"); else { if (param[1][1] == 'x') { sscanf(param[1] + 2, "%x", &i); addr = (unsigned short) i; } else addr = (unsigned short) atoi(param[1]); do { status = mscb_ping(fd, addr, 0, 1); if (status != MSCB_SUCCESS) { if (status == MSCB_MUTEX) printf("MSCB used by other thread\n"); else if (status == MSCB_SUBM_ERROR) printf("Error: Submaster not responding\n"); else printf("Node %d does not respond\n", addr); current_addr = -1; current_group = -1; broadcast = 0; } else { printf("Node %d addressed\n", addr); current_addr = addr; current_group = -1; broadcast = 0; } if (param[2][0] == 'r' && !kbhit()) Sleep(1000); } while (param[2][0] == 'r' && !kbhit()); } } /* address ---------- */ else if (match(param[0], "addr")) { if (!param[1][0]) puts("Please specify node address"); else { if (param[1][1] == 'x') { sscanf(param[1] + 2, "%x", &i); addr = (unsigned short) i; } else addr = (unsigned short) atoi(param[1]); mscb_addr(fd, MCMD_ADDR_NODE16, addr, 0, 10); current_addr = addr; current_group = -1; broadcast = 0; } } /* ba, broadcast address ---------- */ else if (match(param[0], "baddr")) { current_addr = -1; current_group = -1; broadcast = 1; } /* ga, group address ---------- */ else if (match(param[0], "gaddr")) { if (!param[1][0]) puts("Please specify group address"); else { if (param[1][1] == 'x') { sscanf(param[1] + 2, "%x", &i); addr = (unsigned short) i; } else addr = (unsigned short) atoi(param[1]); printf("Enter address of first node in group %d: ", addr); fgets(str, sizeof(str), stdin); reference_addr = atoi(str); current_addr = -1; current_group = addr; broadcast = 0; } } /* sa, set node address ---------- */ else if (match(param[0], "sa")) { if (current_addr < 0 && current_group < 0 && !broadcast) printf("You must first address node(s)\n"); else { if (!param[1][0]) puts("Please specify node address"); else { if (param[1][1] == 'x') { sscanf(param[1] + 2, "%x", &i); addr = (unsigned short) i; } else addr = (unsigned short) atoi(param[1]); status = mscb_set_node_addr(fd, current_addr, current_group, broadcast, addr); if (current_addr >= 0) { if (status == MSCB_ADDR_EXISTS) printf("Error: Address %d exists already on this network\n", addr); else current_addr = addr; } } } } /* sg, set group address ---------- */ else if (match(param[0], "sg")) { if (current_addr < 0 && current_group < 0 && !broadcast) printf("You must first address node(s)\n"); else { if (!param[1][0]) puts("Please specify group address"); else { if (param[1][1] == 'x') { sscanf(param[1] + 2, "%x", &i); addr = (unsigned short) i; } else addr = (unsigned short) atoi(param[1]); mscb_set_group_addr(fd, current_addr, current_group, broadcast, addr); } } } /* sn, set node name ---------- */ else if (match(param[0], "sn")) { if (current_addr < 0) printf("You must first address an individual node\n"); else { if (!param[1][0]) puts("Please specify node name"); else { str[0] = '\0'; for (j = 1; j < 10; j++) { strcat(str, param[j]); if (j < 9 && param[j + 1][0] != '\0') { strcat(str, " "); } } while (strlen(str) > 0 && (str[strlen(str) - 1] == '\r' || str[strlen(str) - 1] == '\n')) str[strlen(str) - 1] = 0; if (strlen(str) > 15) printf("Maximum length is 15 characters, please choose shorter name\n"); else mscb_set_name(fd, (unsigned short) current_addr, str); } } } /* sm, set MAC address etc. ---------- */ else if (match(param[0], "sm")) { if (set_mac_address(fd)) break; // exit program } /* baud, set baud rate ---------- */ else if (match(param[0], "baud")) { puts("Possible baud rates:\n"); puts(" 1: 2400"); puts(" 2: 4800"); puts(" 3: 9600"); puts(" 4: 19200"); puts(" 5: 28800"); puts(" 6: 38400"); puts(" 7: 57600"); puts(" 8: 115200 <= default"); puts(" 9: 172800"); puts(" 10: 345600"); printf("\nSelect rate: "); fgets(str, sizeof(str), stdin); i = atoi(str); mscb_set_baud(fd, i); } /* write ---------- */ else if (match(param[0], "write")) { if (current_addr < 0 && current_group < 0) printf("You must first address a node or a group\n"); else { if (!param[1][0] || !param[2][0]) puts("Please specify channel number and data"); else { idx1 = atoi(param[1]); if (strchr(param[1], '-')) idx2 = atoi(strchr(param[1], '-') + 1); else idx2 = idx1; if (current_addr < 0) { addr = reference_addr; } else addr = current_addr; idx1 = idx1 > 255 ? 255 : idx1; idx2 = idx2 > 255 ? 255 : idx2; for (index = idx1; index <= idx2; index++) { status = mscb_info_variable(fd, (unsigned short) addr, (unsigned char) index, &info_var); if (status == MSCB_NO_VAR) { printf("Node has no variable #%d\n", index); break; } if (info_var.unit == UNIT_STRING) { memset(str, 0, sizeof(str)); strncpy(str, param[2], info_var.width); if (strlen(str) > 0 && str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = 0; do { if (current_addr >= 0) status = mscb_write(fd, (unsigned short) current_addr, (unsigned char) index, str, strlen(str) + 1); else status = mscb_write_group(fd, (unsigned short) current_group, (unsigned char) index, str, strlen(str) + 1); if (param[3][0]) Sleep(1000); } while (param[3][0] && !kbhit()); } else if (info_var.unit == UNIT_ASCII) { memset(str, 0, sizeof(str)); strncpy(str, param[2], sizeof(str)); if (strlen(str) > 0 && str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = 0; do { if (current_addr >= 0) status = mscb_write(fd, (unsigned short) current_addr, (unsigned char) index, str, strlen(str) + 1); Sleep(100); } while (param[3][0] && !kbhit()); } else { if (info_var.unit == UNIT_BYTE && info_var.width == 8) { if (param[2][1] == 'x') sscanf(param[2] + 2, "%lx", &qdata); else qdata = atol(param[2]); } else { if (info_var.flags & MSCBF_FLOAT) { value = (float) atof(param[2]); memcpy(&data, &value, sizeof(float)); } else { if (param[2][1] == 'x') sscanf(param[2] + 2, "%x", &data); else data = atoi(param[2]); } qdata = data; } do { if (current_addr >= 0) status = mscb_write(fd, (unsigned short) current_addr, (unsigned char) index, &qdata, info_var.width); else status = mscb_write_group(fd, (unsigned short) current_group, (unsigned char) index, &qdata, info_var.width); if (param[3][0]) Sleep(100); } while (param[3][0] && !kbhit()); } } if (status != MSCB_SUCCESS) printf("Error: %d\n", status); } } } /* mwrite ---------- */ else if (match(param[0], "mwrite")) { if (!param[1][0] || !param[2][0] || !param[3][0] || !param[4][0]) puts("Please specify variable index, value, and node range"); else { index = atoi(param[1]); first = atoi(param[3]); last = atoi(param[4]); mscb_info_variable(fd, (unsigned short) first, (unsigned char) index, &info_var); for (addr = first; addr <= last; addr++) { printf("Node %d\n", addr); if (info_var.unit == UNIT_STRING) { memset(str, 0, sizeof(str)); strncpy(str, param[2], info_var.width); if (strlen(str) > 0 && str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = 0; status = mscb_write(fd, (unsigned short) addr, (unsigned char) index, str, strlen(str) + 1); } else if (info_var.unit == UNIT_ASCII) { memset(str, 0, sizeof(str)); strncpy(str, param[2], sizeof(str)); if (strlen(str) > 0 && str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = 0; mscb_write(fd, (unsigned short) addr, (unsigned char) index, str, strlen(str) + 1); } else { if (info_var.flags & MSCBF_FLOAT) { value = (float) atof(param[2]); memcpy(&data, &value, sizeof(float)); } else { if (param[2][1] == 'x') sscanf(param[2] + 2, "%x", &data); else data = atoi(param[2]); } status = mscb_write(fd, (unsigned short) addr, (unsigned char) index, &data, info_var.width); } } if (status != MSCB_SUCCESS) printf("Error: %d\n", status); } } /* read ---------- */ else if (match(param[0], "read")) { if (current_addr < 0) printf("You must first address an individual node\n"); else { if (!param[1][0] || param[1][0] == 'a' || param[1][0] == 'r') { first = 0; last = 255; } else if (strchr(param[1], '-')) { first = atoi(param[1]); last = atoi(strchr(param[1], '-') + 1); } else { first = last = atoi(param[1]); } first = first > 255 ? 255 : first; last = last > 255 ? 255 : last; read_all = (param[1][0] == 'a' || param[2][0] == 'a' || param[3][0] == 'a'); repeat = (param[1][0] == 'r' || param[2][0] == 'r' || param[3][0] == 'r'); if (repeat) { wait = 0; for (i = 1; i < 4; i++) if (param[i][0] == 'r') break; if (atoi(param[i + 1]) > 0) wait = atoi(param[i + 1]); } n_found = 0; memset(info_var_array, 0, sizeof(info_var_array)); for (i = first; i <= last; i++) { status = mscb_info_variable(fd, (unsigned short) current_addr, (unsigned char) i, &info_var_array[i]); if (status == MSCB_NO_VAR) { if (first == last) printf("Node has no variable #%d\n", first); break; } else if (status == MSCB_CRC_ERROR) puts("CRC Error\n"); else if (status != MSCB_SUCCESS) puts("Timeout or invalid channel number\n"); else n_found++; } if (n_found) { do { if (first == last) { // read single variable i = first; size = info_var_array[i].width; memset(dbuf, 0, sizeof(dbuf)); status = mscb_read(fd, (unsigned short) current_addr, (unsigned char) i, dbuf, &size); if (status == MSCB_SUCCESS) print_channel(i, &info_var_array[i], dbuf, first != last); } else { // read multiple variables last = first + n_found - 1; size = 1400; status = mscb_read_range(fd, (unsigned short) current_addr, (unsigned char) first, (unsigned char) last, dbuf, &size); if (status == MSCB_CRC_ERROR) puts("CRC Error\n"); else if (status == MSCB_TIMEOUT) puts("Timeout receivig acknowledge\n"); else if (status != MSCB_SUCCESS) puts("Reading not successful!\n"); else { pdata = dbuf; for (i = first; i <= last; i++) { size = info_var_array[i].width; if (size == 2) { WORD_SWAP(pdata); } else if (size == 4) { DWORD_SWAP(pdata); } if ((info_var_array[i].flags & MSCBF_HIDDEN) == 0 || read_all || first > 0) print_channel(i, &info_var_array[i], pdata, first != last); if (kbhit()) break; pdata += size; } } } if (kbhit()) break; if (first != last && repeat) printf("\n"); if (repeat) { if (wait) { Sleep(wait); printf("\n"); } else Sleep(10); } } while (!kbhit() && repeat); } if (first == last) printf("\n"); while (kbhit()) getch(); } } /* save ---------- */ else if (match(param[0], "save")) { if (current_addr < 0 && param[1][0] == 0 && param[2][0] == 0) printf("You must first address an individual node or specify a range\n"); else { if (param[1][0] == 0 || strchr(param[1], '.') == NULL) { printf("Enter file name: "); fgets(str, sizeof(str), stdin); } else strcpy(str, param[1]); if (str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = 0; if (param[2][0] == 0) first = last = current_addr; else { if (param[3][0]) { first = atoi(param[2]); last = atoi(param[3]); } else { first = atoi(param[1]); last = atoi(param[2]); } } writer = mxml_open_file(str); if (writer == NULL) printf("Cannot open xml file \"%s\"\n", str); else { mxml_start_element(writer, "MSCBDump"); for (i = first, j = 0; i <= last; i++) { status = mscb_ping(fd, (unsigned short) i, 0, 1); if (status == MSCB_SUCCESS) { j++; printf("Save node %d (0x%04X) \r", i, i); fflush(stdout); save_node_xml(writer, fd, i); } else { printf("Test address %d (0x%04X) \r", i, i); fflush(stdout); } } printf("\n"); if (j > 1) printf("%d nodes saved \n", j); mxml_end_element(writer); mxml_close_file(writer); } } } /* load ---------- */ else if (match(param[0], "load")) { if (param[1][0] == 0) { printf("Enter file name: "); fgets(str, sizeof(str), stdin); } else strcpy(str, param[1]); if (str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = 0; printf("Write parameters to flash? (y/[n]) "); fgets(line, sizeof(line), stdin); load_nodes_xml(fd, str, line[0] == 'y'); } /* terminal ---------- */ else if (match(param[0], "terminal")) { int status, chn; /* find first dataless variable */ memset(info_var_array, 0, sizeof(info_var_array)); for (chn = 0; chn < 255; chn++) { status = mscb_info_variable(fd, (unsigned short) current_addr, (unsigned char) chn, &info_var_array[chn]); if (status == MSCB_NO_VAR) break; if (info_var_array[chn].flags & MSCBF_DATALESS) break; } if (status == MSCB_NO_VAR) { puts("Node does not support terminal mode.\n"); } else { puts("Exit with \n"); c = 0; do { if ((c = ss_getchar(0)) != 0) { if (c == 27) break; putchar(c); fflush(stdout); status = mscb_write(fd, (unsigned short) current_addr, chn, &c, 1); if (status != MSCB_SUCCESS) { printf("\nError: %d\n", status); break; } if (c == '\r') { putchar('\n'); c = '\n'; mscb_write(fd, (unsigned short) current_addr, chn, &c, 1); } } memset(line, 0, sizeof(line)); size = sizeof(line); mscb_read(fd, (unsigned short) current_addr, chn, line, &size); if (size > 0) { fputs(line, stdout); fflush(stdout); } Sleep(10); } while (TRUE); puts("\n"); while (kbhit()) getch(); } } /* flash ---------- */ else if (match(param[0], "flash")) { if (current_addr < 0 && current_group < 0 && !broadcast) printf("You must first address node (s)\n"); else { status = mscb_flash(fd, current_addr, current_group, broadcast); if (status != MSCB_SUCCESS) printf("Error: %d\n", status); } } /* upload ---------- */ else if (match(param[0], "upload")) { if (isdigit(param[1][0])) { // address given: upload to WaveDAQ slot if (param[2][0] == 0) { printf("Enter name of file: "); fgets(filename, sizeof(filename), stdin); } else strcpy(filename, param[2]); if (str[strlen(filename) - 1] == '\n') str[strlen(filename) - 1] = 0; i = 0; if (match(param[2], "debug") || match(param[3], "deubg")) i = 1; status = mscb_upload(fd, (unsigned short) current_addr, (unsigned short) atoi(param[1]), filename, i | MSCB_UPLOAD_SUBADDR); if (status == MSCB_NOT_FOUND) printf("File \"%s\" not found\n", filename); else if (status == MSCB_FORMAT_ERROR) printf("Syntax error in file \"%s\"\n", filename); else if (status == MSCB_TIMEOUT) printf("Node %d does not respond\n", current_addr); else if (status == MSCB_SUBADDR) printf("Cannot program subaddress\n"); else if (status == MSCB_NOTREADY) printf("Note just rebooted and not ready for upgrade\n"); } else { if (current_addr < 0) printf("You must first address an individual node\n"); else { if (param[1][0] == 0) { printf("Enter name of file: "); fgets(filename, sizeof(filename), stdin); } else strcpy(filename, param[1]); if (str[strlen(filename) - 1] == '\n') str[strlen(filename) - 1] = 0; status = mscb_upload(fd, (unsigned short) current_addr, 0, filename, param[2][0] == 'd'); if (status == MSCB_NOT_FOUND) printf("File \"%s\" not found\n", filename); else if (status == MSCB_FORMAT_ERROR) printf("Syntax error in file \"%s\"\n", filename); else if (status == MSCB_TIMEOUT) printf("Node %d does not respond\n", current_addr); else if (status == MSCB_SUBADDR) printf("Cannot program subaddress\n"); else if (status == MSCB_NOTREADY) printf("Note just rebooted and not ready for upgrade\n"); } } } /* download ---------- */ else if (match(param[0], "download")) { if (isdigit(param[1][0])) { // address given: upload to WaveDAQ slot if (param[2][0] == 0) { printf("Enter name of file: "); fgets(filename, sizeof(filename), stdin); } else strcpy(filename, param[2]); if (str[strlen(filename) - 1] == '\n') str[strlen(filename) - 1] = 0; status = mscb_download(fd, (unsigned short) current_addr, (unsigned short) atoi(param[1]), filename); if (status == MSCB_NOT_FOUND) printf("File \"%s\" exists already\n", filename); else if (status == MSCB_NO_MEM) printf("Cannot write to file \"%s\"\n", filename); else if (status == MSCB_TIMEOUT) printf("Node %d does not respond\n", current_addr); else if (status == MSCB_SUBADDR) printf("Cannot read subaddress\n"); } else { if (current_addr < 0) printf("You must first address an individual node\n"); else { if (param[1][0] == 0) { printf("Enter name of file: "); fgets(filename, sizeof(filename), stdin); } else strcpy(filename, param[1]); if (str[strlen(filename) - 1] == '\n') str[strlen(filename) - 1] = 0; status = mscb_download(fd, (unsigned short) current_addr, 0, filename); if (status == MSCB_NOT_FOUND) printf("File \"%s\" exists already\n", filename); else if (status == MSCB_NO_MEM) printf("Cannot write to file \"%s\"\n", filename); else if (status == MSCB_TIMEOUT) printf("Node %d does not respond\n", current_addr); else if (status == MSCB_SUBADDR) printf("Cannot read subaddress\n"); } } } /* mupload ---------- */ else if (match(param[0], "mupload")) { first = atoi(param[2]); last = atoi(param[3]); if (last == 0) printf("You must specify an address range\n"); else { strcpy(filename, param[1]); for (i = first; i <= last; i++) { printf("Node%d: ", i); status = mscb_upload(fd, (unsigned short) i, 0, filename, 0); if (status == MSCB_NOT_FOUND) { printf("File \"%s\" not found\n", filename); break; } else if (status == MSCB_FORMAT_ERROR) { printf("Syntax error in file \"%s\"\n", filename); break; } else if (status == MSCB_TIMEOUT) printf("Node %d does not respond\n", current_addr); else if (status == MSCB_SUBADDR) printf("Cannot program subaddress\n"); else if (status == MSCB_NOTREADY) printf("Note just rebooted and not ready for upgrade\n"); } } } /* verify ---------- */ else if (match(param[0], "verify")) { if (isdigit(param[1][0])) { // address given: verify WaveDAQ slot if (param[2][0] == 0) { printf("Enter name of file: "); fgets(filename, sizeof(filename), stdin); } else strcpy(filename, param[2]); if (str[strlen(filename) - 1] == '\n') str[strlen(filename) - 1] = 0; status = mscb_verify(fd, (unsigned short) current_addr, (short) atoi(param[1]), filename, MSCB_UPLOAD_SUBADDR); if (status == MSCB_NOT_FOUND) printf("File \"%s\" not found\n", filename); else if (status == MSCB_FORMAT_ERROR) printf("Syntax error in file \"%s\"\n", filename); else if (status == MSCB_TIMEOUT) printf("Node %d does not respond\n", current_addr); else if (status == MSCB_SUBADDR) printf("Cannot program subaddress\n"); else if (status == MSCB_NOTREADY) printf("Note just rebooted and not ready for upgrade\n"); } else { if (current_addr < 0) printf("You must first address an individual node\n"); else { if (param[1][0] == 0) { printf("Enter name of file: "); fgets(filename, sizeof(filename), stdin); } else strcpy(filename, param[1]); if (str[strlen(filename) - 1] == '\n') str[strlen(filename) - 1] = 0; status = mscb_verify(fd, (unsigned short) current_addr, 0, filename, 0); if (status == MSCB_NOT_FOUND) printf("File \"%s\" not found\n", filename); else if (status == MSCB_FORMAT_ERROR) printf("Syntax error in file \"%s\"\n", filename); else if (status == MSCB_TIMEOUT) printf("Node %d does not respond\n", current_addr); else if (status == MSCB_SUBADDR) printf("Cannot program subaddress\n"); else if (status == MSCB_NOTREADY) printf("Note just rebooted and not ready for upgrade\n"); } } } /* memory write ---------- */ else if (match(param[0], "memwr")) { if (current_addr < 0 && current_group < 0 && !broadcast) printf("You must first address node (s)\n"); else { slot = atoi(param[1]); if (param[2][1] == 'x') sscanf(param[2] + 2, "%X", &mem_addr); else mem_addr = atoi(param[2]); mem_addr |= MSCB_BASE_RAM; if (param[3][1] == 'x') { sscanf(param[3] + 2, "%X", &data); if (strlen(param[3]) == 4) size = 1; else if (strlen(param[3]) == 6) { size = 2; WORD_SWAP(&data); } else { size = 4; DWORD_SWAP(&data); } } else if (isdigit(param[3][0])) { size = 4; data = atoi(param[3]); DWORD_SWAP(&data); } else { // TBD: String } mscb_write_mem(fd, (unsigned short) current_addr, slot, mem_addr, &data, size); } } /* memory read ---------- */ else if (match(param[0], "memrd")) { if (current_addr < 0 && current_group < 0 && !broadcast) printf("You must first address node (s)\n"); else { slot = atoi(param[1]); if (param[2][1] == 'x') sscanf(param[2] + 2, "%X", &mem_addr); else mem_addr = atoi(param[2]); mem_addr |= MSCB_BASE_RAM; if (param[3][1] == 'x') sscanf(param[3] + 2, "%X", &size); else size = atoi(param[3]); status = mscb_read_mem(fd, (unsigned short) current_addr, slot, mem_addr, &dbuf, size); /* print result */ if (status == MSCB_SUCCESS) { printf("0x%02X: ", mem_addr); for (i = 0; i < size; i++) printf("%02X ", (unsigned char) dbuf[i]); printf("\n"); } } } /* reboot ---------- */ else if (match(param[0], "reboot")) { if (current_addr < 0 && current_group < 0 && !broadcast) printf("You must first address node (s)\n"); else { status = mscb_reboot(fd, current_addr, current_group, broadcast); if (status != MSCB_SUCCESS) printf("Error: %d\n", status); } } /* sr ---------- */ else if (match(param[0], "sr")) { mscb_subm_reset(fd); } /* submaster ---------- */ else if (match(param[0], "submaster")) { mscb_subm_info(fd); } /* sync ---------- */ else if (match(param[0], "sync")) { if (current_addr < 0 && current_group < 0 && !broadcast) printf("You must first address node (s)\n"); else { status = mscb_set_time(fd, current_addr, current_group, broadcast); if (status != MSCB_SUCCESS) printf("Error: %d\n", status); else { now = time(NULL); ptm = localtime(&now); printf("Synchornized to %02d-%02d-%02d %02d:%02d:%02d\n", ptm->tm_mday, ptm->tm_mon + 1, ptm->tm_year - 100, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); } } } /* echo test ---------- */ else if (match(param[0], "echo")) { unsigned char d1, d2; int i, status; if (current_addr < 0) printf("You must first address an individual node\n"); else { d1 = i = 0; while (!kbhit()) { d1 = (d1 + 1) % 256; status = mscb_echo(fd, (unsigned short) current_addr, d1, &d2); if (status == MSCB_TIMEOUT) printf("Timeout in submaster communictation\n"); else if (status == MSCB_TIMEOUT_BUS) printf("Timeout from RS485 bus\n"); else if (status == MSCB_CRC_ERROR) printf("CRC Error on RS485 bus\n"); else if (status != MSCB_SUCCESS) printf("Error: %d\n", status); if (d2 != d1) { printf("%d\nReceived: %02X, should be %02X, status = %d\n", i, d2, d1, status); if (param[1][0] != 'c' && param[1][1] != 'c') break; } i++; if (i % 100 == 0) { printf("%d\r", i); fflush(stdout); } if (param[1][0] != 'f' && param[1][1] != 'c') Sleep(10); } printf("%d\n", i); while (kbhit()) getch(); } } /* call user fundtion ----------- */ else if (match(param[0], "user")) { if (current_addr < 0 && current_group < 0 && !broadcast) printf("You must first address node (s)\n"); else { if (param[1][0]) { data = atoi(param[1]); size = sizeof(status); status = mscb_user(fd, current_addr, &data, 1, &status, &size); } else { status = mscb_user(fd, current_addr, NULL, 0, &data, &size); } if (status != MSCB_SUCCESS) printf("Error: %d\n", status); } } else if (match(param[0], "log")) { if (broadcast) printf("Log command not allowed in broadcast mode!\n"); else if (current_group > 0) printf("Log command not allowed in group address mode!\n"); if (current_addr < 0) printf("You must first address a single node\n"); else { // check first if its an SCS3000 memset(&info, 0, sizeof(info)); status = mscb_info(fd, (unsigned short) current_addr, &info); if (status == MSCB_CRC_ERROR) puts("CRC Error"); else if (status != MSCB_SUCCESS) puts("node does not respond."); else if (info.bootBank == 0) puts("Log command not supported!"); else { if (param[1][0] == 'c') // clear log status = mscb_clear_log(fd, current_addr); else { // +3 becasue of ACK and datalength of answer char *LogMsg = &dbuf[3]; // read log do { status = mscb_read_log(fd, current_addr, dbuf, sizeof(dbuf)); if (status == MSCB_SUCCESS) printf("%s", LogMsg); } while (status == MSCB_SUCCESS && *LogMsg != '\0'); } if (status != MSCB_SUCCESS) printf("Error: %d\n", status); } } } /* test1 ---------- */ else if (match(param[0], "t1")) { data = atoi(param[1]); do { mscb_link(fd, (unsigned short) current_addr, 4, &data, 1); printf("Data: %d\r", data); } while (!kbhit()); while (kbhit()) getch(); } /* test 2 -----------*/ else if (match(param[0], "t2")) { float a[16]; unsigned int start = ss_millitime(); for (i = 0; i < 16; i++) { a[i] = i * 1.01f; DWORD_SWAP(&a[i]); } for (i = 0; i < 900; i++) { mscb_write_range(fd, (unsigned short) current_addr, 0, 16, a, sizeof(a)); printf("%d\r", i); if (kbhit()) break; } printf("\n%3.2lf sec.\n", (ss_millitime() - start) / 1000.0); while (kbhit()) getch(); } /* exit/quit ---------- */ else if (match(param[0], "exit") || match(param[0], "quit")) break; else if (param[0][0] == 0); else if (param[0][0] == '\n'); else printf("Unknown command %s %s %s\n", param[0], param[1], param[2]); /* exit after single command */ if (cmd[0] && cmd[0] != '@') break; } while (1); } /*------------------------------------------------------------------*/ int main(int argc, char *argv[]) { int i, fd, server, scan; unsigned short adr; char cmd[256], device[256], str[256], password[256], ip[256]; int debug; cmd[0] = 0; adr = 0; debug = server = scan = 0; device[0] = password[0] = 0; /* parse command line parameters */ for (i = 1; i < argc; i++) { if (argv[i][0] == '-' && argv[i][1] == 'v') debug = 2; else if (argv[i][0] == '-' && argv[i][1] == 'w') debug = 1; else if (argv[i][0] == '-' && argv[i][1] == 'r') server = 1; else if (argv[i][0] == '-' && argv[i][1] == 's') scan = 1; else if (argv[i][0] == '-') { if (i + 1 >= argc || argv[i + 1][0] == '-') goto usage; else if (argv[i][1] == 'd') strcpy(device, argv[++i]); else if (argv[i][1] == 'p') strcpy(password, argv[++i]); else if (argv[i][1] == 'a') adr = atoi(argv[++i]); else if (argv[i][1] == 'c') { if (strlen(argv[i]) >= 256) { printf("error: command line too long (>256).\n"); return 0; } strcpy(cmd, argv[++i]); } else { usage: printf ("usage: msc [-d host:device] [-p password] [-a addr] [-c Command] [-c @CommandFile] [-v] [-s]\n\n"); printf(" -d device, \":usb0\" for RPC connection\n"); printf (" or \"mscb\" for Ethernet connection to SUBM_260\n"); printf(" -p optional password for SUBM_260\n"); printf(" -r Start RPC server\n"); printf(" -s Scan for Ethernet submasters on local net\n"); printf(" -a Address node before executing command\n"); printf(" -c Execute command immediately\n"); printf(" -v Produce verbose debugging output into mscb_debug.log\n"); printf(" -w Log all write commands to mscb_write.log\n\n"); printf("For a list of valid commands start msc interactively\n"); printf("and type \"help\".\n"); return 0; } } } if (server) { #ifdef HAVE_MRPC mrpc_server_loop(); #endif return 0; } if (scan) { mscb_scan_udp(); return 0; } if (device[0]) host2ip(device, ip, sizeof(ip)); else ip[0] = 0; if (device[0] == 0) { printf("Please specify MSCB submaster via -d flag\n"); return 0; } /* open port */ fd = mscb_init(device, sizeof(device), password, debug); if (fd == EMSCB_WRONG_PASSWORD) { printf("Enter password to access %s: ", device); fgets(str, sizeof(str), stdin); while (strlen(str) > 0 && (str[strlen(str) - 1] == '\r' || str[strlen(str) - 1] == '\n')) str[strlen(str) - 1] = 0; fd = mscb_init(device, sizeof(device), str, debug); } if (fd < 0) { if (fd == EMSCB_COMM_ERROR) { printf("\nCannot communicate with MSCB submaster %s (%s)\n", device, ip); puts("Please disconnect and reconnect submaster\n"); } else if (fd == EMSCB_PROTOCOL_VERSION) { printf("\nSubmaster %s (%s) runs old protocol version\n", device, ip); puts("Please upgrade submaster software\n"); } else if (fd == EMSCB_NOT_FOUND) { #ifdef HAVE_USB printf("\nCannot find USB submaster\n"); #else printf("\nNo USB support available in this verson of msc\n"); printf("An ethernet node address must explicitly be supplied via the '-d [host]' flag\n"); #endif } else if (fd == EMSCB_WRONG_PASSWORD) { printf("\nWrong password\n"); } else if (fd == EMSCB_NO_WRITE_ACCESS) { printf("\nNo write access to MSCB submaster %s (%s)\n", device, ip); puts("Please install hotplug script \"drivers/linux/usb.usermap_scs_250\" to \"/etc/hotplug/\".\n"); } else if (fd == EMSCB_LOCKED) { puts("\nMSCB system is locked by other process"); puts("Please stop all running MSCB clients\n"); } else if (device[0]) printf("Cannot connect to device \"%s\" (%s)\n", device, ip); else printf("Please specify MSCB submaster via -d flag\n"); #ifdef _MSC_VER puts("\n-- hit any key to exit --"); while (!kbhit()) Sleep(100); while (kbhit()) getch(); #endif return 0; } printf("Connected to submaster %s (%s)\n", device, ip); cmd_loop(fd, cmd, adr); mscb_exit(fd); return 0; }