fp@922: /***************************************************************************** fp@922: * fp@922: * $Id$ fp@922: * fp@922: ****************************************************************************/ fp@922: fp@922: #include fp@1118: #include // basename() fp@922: fp@922: #include fp@1126: #include fp@922: #include fp@956: #include fp@1126: #include fp@922: using namespace std; fp@922: fp@1122: #include "globals.h" fp@1122: fp@1122: /*****************************************************************************/ fp@1122: fp@1122: string binaryBaseName; fp@1122: unsigned int masterIndex = 0; fp@1122: int slavePosition = -1; fp@1122: int domainIndex = -1; fp@1125: string commandName; fp@956: vector commandArgs; fp@1122: Verbosity verbosity = Normal; fp@968: string dataTypeStr; fp@980: bool force = false; fp@1122: fp@1121: bool helpRequested = false; fp@922: fp@1122: MasterDevice masterDev; fp@1122: fp@1122: /*****************************************************************************/ fp@1122: fp@1122: struct Command { fp@1125: const char *name; fp@1122: void (*func)(void); fp@1122: const char *helpString; fp@1126: const char *briefDesc; fp@1122: fp@1122: int execute(void) const; fp@1122: void displayHelp(void) const; fp@1122: }; fp@1122: fp@1122: /*****************************************************************************/ fp@1122: fp@1126: #define DEFINE_EXTERN_COMMAND(name) \ fp@1122: void command_##name(void); \ fp@1125: extern const char *help_##name fp@1125: fp@1126: #define INIT_COMMAND(name, desc) \ fp@1126: {#name, command_##name, help_##name, desc} fp@1126: fp@1126: DEFINE_EXTERN_COMMAND(alias); fp@1126: DEFINE_EXTERN_COMMAND(config); fp@1126: DEFINE_EXTERN_COMMAND(data); fp@1126: DEFINE_EXTERN_COMMAND(debug); fp@1126: DEFINE_EXTERN_COMMAND(domains); fp@1126: DEFINE_EXTERN_COMMAND(master); fp@1126: DEFINE_EXTERN_COMMAND(pdos); fp@1126: DEFINE_EXTERN_COMMAND(sdos); fp@1126: DEFINE_EXTERN_COMMAND(sdo_download); fp@1126: DEFINE_EXTERN_COMMAND(sdo_upload); fp@1126: DEFINE_EXTERN_COMMAND(slaves); fp@1126: DEFINE_EXTERN_COMMAND(sii_read); fp@1126: DEFINE_EXTERN_COMMAND(sii_write); fp@1126: DEFINE_EXTERN_COMMAND(states); fp@1126: DEFINE_EXTERN_COMMAND(xml); fp@1122: fp@1125: static const Command commands[] = { fp@1126: INIT_COMMAND(alias, "Write alias addresses."), fp@1126: INIT_COMMAND(config, "Show bus configuration."), fp@1126: INIT_COMMAND(data, "Output binary domain process data."), fp@1126: INIT_COMMAND(debug, "Set the master's debug level."), fp@1126: INIT_COMMAND(domains, "Show domain information."), fp@1126: INIT_COMMAND(master, "Show master information."), fp@1126: INIT_COMMAND(pdos, "List Pdo assignment/mapping."), fp@1126: INIT_COMMAND(sdos, "List Sdo dictionaries."), fp@1126: INIT_COMMAND(sdo_download, "Write an Sdo entry."), fp@1126: INIT_COMMAND(sdo_upload, "Read an Sdo entry."), fp@1126: INIT_COMMAND(slaves, "Show slaves."), fp@1126: INIT_COMMAND(sii_read, "Output a slave's SII contents."), fp@1126: INIT_COMMAND(sii_write, "Write slave's SII contents."), fp@1126: INIT_COMMAND(states, "Request slave states."), fp@1126: INIT_COMMAND(xml, "Generate slave information xmls."), fp@1122: }; fp@1122: fp@1126: static const Command *cmdEnd = commands + sizeof(commands) / sizeof(Command); fp@1122: fp@1122: /*****************************************************************************/ fp@1122: fp@1122: void printUsage() fp@1122: { fp@1126: const Command *cmd; fp@1126: size_t maxWidth = 0; fp@1126: fp@1126: for (cmd = commands; cmd < cmdEnd; cmd++) { fp@1126: if (strlen(cmd->name) > maxWidth) { fp@1126: maxWidth = strlen(cmd->name); fp@1126: } fp@1126: } fp@1126: fp@1122: cerr fp@1122: << "Usage: " << binaryBaseName << " [OPTIONS]" << endl fp@1126: << "Commands:" << endl; fp@1126: fp@1126: cerr << left; fp@1126: for (cmd = commands; cmd < cmdEnd; cmd++) { fp@1126: cerr << " " << setw(maxWidth) << cmd->name fp@1126: << " " << cmd->briefDesc << endl; fp@1126: } fp@1126: fp@1126: cerr fp@1125: << "Commands can be generously abbreviated." << endl fp@1122: << "Global options:" << endl fp@1122: << " --master -m Index of the master to use. Default: 0" fp@1122: << endl fp@1122: << " --slave -s Positive numerical ring position," fp@1122: << endl fp@1122: << " or 'all' for all slaves (default)." fp@1122: << endl fp@1122: << " or 'all' for all domains (default)." fp@1122: << endl fp@1122: << " --type -t Forced Sdo data type." << endl fp@1122: << " --force -f Force action." << endl fp@1122: << " --quiet -q Output less information." << endl fp@1122: << " --verbose -v Output more information." << endl fp@1122: << " --help -h Show this help." << endl fp@1122: << "Call '" << binaryBaseName fp@1122: << " --help' for command-specific help." << endl fp@1122: << "Send bug reports to " << PACKAGE_BUGREPORT << "." << endl; fp@1122: } fp@1122: fp@1122: /*****************************************************************************/ fp@1122: fp@1122: void getOptions(int argc, char **argv) fp@1122: { fp@1122: int c, argCount, optionIndex, number; fp@1122: char *remainder; fp@1122: fp@1122: static struct option longOptions[] = { fp@1122: //name, has_arg, flag, val fp@1122: {"master", required_argument, NULL, 'm'}, fp@1122: {"slave", required_argument, NULL, 's'}, fp@1122: {"domain", required_argument, NULL, 'd'}, fp@1122: {"type", required_argument, NULL, 't'}, fp@1122: {"force", no_argument, NULL, 'f'}, fp@1122: {"quiet", no_argument, NULL, 'q'}, fp@1122: {"verbose", no_argument, NULL, 'v'}, fp@1122: {"help", no_argument, NULL, 'h'}, fp@1122: {} fp@1122: }; fp@1122: fp@1122: do { fp@1122: c = getopt_long(argc, argv, "m:s:d:t:fqvh", longOptions, &optionIndex); fp@1122: fp@1122: switch (c) { fp@1122: case 'm': fp@1122: number = strtoul(optarg, &remainder, 0); fp@1122: if (remainder == optarg || *remainder || number < 0) { fp@1122: cerr << "Invalid master number " << optarg << "!" << endl; fp@1122: printUsage(); fp@1122: exit(1); fp@1122: } fp@1122: masterIndex = number; fp@1122: break; fp@1122: fp@1122: case 's': fp@1122: if (!strcmp(optarg, "all")) { fp@1122: slavePosition = -1; fp@1122: } else { fp@1122: number = strtoul(optarg, &remainder, 0); fp@1122: if (remainder == optarg || *remainder fp@1122: || number < 0 || number > 0xFFFF) { fp@1122: cerr << "Invalid slave position " fp@1122: << optarg << "!" << endl; fp@1122: printUsage(); fp@1122: exit(1); fp@1122: } fp@1122: slavePosition = number; fp@1122: } fp@1122: break; fp@1122: fp@1122: case 'd': fp@1122: if (!strcmp(optarg, "all")) { fp@1122: domainIndex = -1; fp@1122: } else { fp@1122: number = strtoul(optarg, &remainder, 0); fp@1122: if (remainder == optarg || *remainder || number < 0) { fp@1122: cerr << "Invalid domain index " fp@1122: << optarg << "!" << endl; fp@1122: printUsage(); fp@1122: exit(1); fp@1122: } fp@1122: domainIndex = number; fp@1122: } fp@1122: break; fp@1122: fp@1122: case 't': fp@1122: dataTypeStr = optarg; fp@1122: break; fp@1122: fp@1122: case 'f': fp@1122: force = true; fp@1122: break; fp@1122: fp@1122: case 'q': fp@1122: verbosity = Quiet; fp@1122: break; fp@1122: fp@1122: case 'v': fp@1122: verbosity = Verbose; fp@1122: break; fp@1122: fp@1122: case 'h': fp@1122: helpRequested = true; fp@1122: break; fp@1122: fp@1122: case '?': fp@1122: printUsage(); fp@1122: exit(1); fp@1122: fp@1122: default: fp@1122: break; fp@1122: } fp@1122: } fp@1122: while (c != -1); fp@1122: fp@1122: argCount = argc - optind; fp@1122: fp@1122: if (!argCount) { fp@1122: if (!helpRequested) { fp@1122: cerr << "Please specify a command!" << endl; fp@1122: } fp@1122: printUsage(); fp@1122: exit(!helpRequested); fp@1122: } fp@1122: fp@1125: commandName = argv[optind]; fp@1122: while (++optind < argc) fp@1122: commandArgs.push_back(string(argv[optind])); fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: int Command::execute() const fp@1122: { fp@1122: try { fp@1122: func(); fp@1122: } catch (InvalidUsageException &e) { fp@1122: cerr << e.what() << endl << endl; fp@1122: displayHelp(); fp@1122: return 1; fp@1122: } catch (ExecutionFailureException &e) { fp@1122: cerr << e.what() << endl; fp@1122: return 1; fp@1122: } catch (MasterDeviceException &e) { fp@1122: cerr << e.what() << endl; fp@1122: return 1; fp@1122: } fp@1122: fp@1122: return 0; fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void Command::displayHelp() const fp@1122: { fp@1125: cerr << binaryBaseName << " " << commandName << " " << helpString; fp@1125: } fp@1125: fp@1125: /****************************************************************************/ fp@1125: fp@1125: bool abbrevMatch(const string &abb, const string &full) fp@1125: { fp@1125: unsigned int abbIndex; fp@1125: size_t fullPos = 0; fp@1125: fp@1125: for (abbIndex = 0; abbIndex < abb.length(); abbIndex++) { fp@1125: fullPos = full.find(abb[abbIndex], fullPos); fp@1125: if (fullPos == string::npos) fp@1125: return false; fp@1125: } fp@1125: fp@1125: return true; fp@1125: } fp@1125: fp@1125: /****************************************************************************/ fp@1125: fp@1125: list getMatchingCommands(const string &cmdStr) fp@1125: { fp@1126: const Command *cmd; fp@1125: list res; fp@1125: fp@1125: // find matching commands fp@1126: for (cmd = commands; cmd < cmdEnd; cmd++) { fp@1125: if (abbrevMatch(cmdStr, cmd->name)) { fp@1125: res.push_back(cmd); fp@1125: } fp@1125: } fp@1125: fp@1125: return res; fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: int main(int argc, char **argv) fp@1122: { fp@1122: int retval = 0; fp@1125: list commands; fp@1125: list::const_iterator ci; fp@1125: const Command *cmd; fp@1122: fp@1122: binaryBaseName = basename(argv[0]); fp@1122: getOptions(argc, argv); fp@1122: fp@1125: commands = getMatchingCommands(commandName); fp@1125: fp@1125: if (commands.size()) { fp@1125: if (commands.size() == 1) { fp@1125: cmd = commands.front(); fp@1125: if (!helpRequested) { fp@1125: masterDev.setIndex(masterIndex); fp@1125: retval = cmd->execute(); fp@1125: } else { fp@1125: cmd->displayHelp(); fp@1125: } fp@935: } else { fp@1125: cerr << "Ambigous command abbreviation! Matching:" << endl; fp@1125: for (ci = commands.begin(); ci != commands.end(); ci++) { fp@1125: cerr << (*ci)->name << endl; fp@1125: } fp@1125: cerr << endl; fp@1125: printUsage(); fp@1125: retval = 1; fp@935: } fp@1125: } else { fp@1125: cerr << "Unknown command " << commandName << "!" << endl << endl; fp@1122: printUsage(); fp@1122: retval = 1; fp@922: } fp@922: fp@1122: return retval; fp@922: } fp@922: fp@922: /****************************************************************************/ fp@1126: fp@1126: void printRawData( fp@1126: const uint8_t *data, fp@1126: unsigned int size fp@1126: ) fp@1126: { fp@1126: cout << hex << setfill('0'); fp@1126: while (size--) { fp@1126: cout << "0x" << setw(2) << (unsigned int) *data++; fp@1126: if (size) fp@1126: cout << " "; fp@1126: } fp@1126: cout << endl; fp@1126: } fp@1126: fp@1126: /****************************************************************************/