# HG changeset patch # User Florian Pose # Date 1216906026 0 # Node ID 59be91dfcbe119fca61f31911d8ad9f37439f334 # Parent 7ffbca63fc722d791c5bf9830d831b5c6e3f0929 Redesigned command interface. diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/Command.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/Command.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,81 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include "Command.h" + +/*****************************************************************************/ + +Command::Command(const string &name, const string &briefDesc): + name(name), + briefDesc(briefDesc), + verbosity(Normal) +{ +} + +/*****************************************************************************/ + +Command::~Command() +{ +} + +/*****************************************************************************/ + +void Command::setVerbosity(Verbosity v) +{ + verbosity = v; +}; + +/****************************************************************************/ + +bool Command::matchesSubstr(const string &cmd) const +{ + return name.substr(0, cmd.length()) == cmd; +} + +/****************************************************************************/ + +bool Command::matchesAbbrev(const string &abb) const +{ + unsigned int i; + size_t pos = 0; + + for (i = 0; i < abb.length(); i++) { + pos = name.find(abb[i], pos); + if (pos == string::npos) + return false; + } + + return true; +} + +/*****************************************************************************/ + +void Command::throwInvalidUsageException(const stringstream &s) +{ + throw InvalidUsageException(s); +} + +/*****************************************************************************/ + +void Command::throwCommandException(const stringstream &s) +{ + throw CommandException(s); +} + +/*****************************************************************************/ + +string Command::numericInfo() +{ + stringstream str; + + str << "Numerical values can be specified either with decimal (no" << endl + << "prefix), octal (prefix '0') or hexadecimal (prefix '0x') base." + << endl; + + return str.str(); +} + +/****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/Command.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/Command.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,117 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMAND_H__ +#define __COMMAND_H__ + +#include +#include +using namespace std; + +#include "MasterDevice.h" + +/*****************************************************************************/ + +extern unsigned int masterIndex; +extern int slavePosition; +extern int domainIndex; +extern string dataTypeStr; +extern bool force; + +/****************************************************************************/ + +class InvalidUsageException: + public runtime_error +{ + friend class Command; + + protected: + /** Constructor with stringstream parameter. */ + InvalidUsageException( + const stringstream &s /**< Message. */ + ): runtime_error(s.str()) {} +}; + +/****************************************************************************/ + +class CommandException: + public runtime_error +{ + friend class Command; + + protected: + /** Constructor with stringstream parameter. */ + CommandException( + const stringstream &s /**< Message. */ + ): runtime_error(s.str()) {} +}; + +/****************************************************************************/ + +class Command +{ + public: + Command(const string &, const string &); + virtual ~Command(); + + enum Verbosity { + Quiet, + Normal, + Verbose + }; + void setVerbosity(Verbosity); + + const string &getName() const; + const string &getBriefDescription() const; + Verbosity getVerbosity() const; + + bool matchesSubstr(const string &) const; + bool matchesAbbrev(const string &) const; + + virtual string helpString() const = 0; + + typedef vector StringVector; + virtual void execute(MasterDevice &, const StringVector &) = 0; + + protected: + void throwInvalidUsageException(const stringstream &); + void throwCommandException(const stringstream &); + + enum {BreakAfterBytes = 16}; + static string numericInfo(); + + private: + string name; + string briefDesc; + Verbosity verbosity; + + Command(); +}; + +/****************************************************************************/ + +inline const string &Command::getName() const +{ + return name; +} + +/****************************************************************************/ + +inline const string &Command::getBriefDescription() const +{ + return briefDesc; +} + +/****************************************************************************/ + +inline Command::Verbosity Command::getVerbosity() const +{ + return verbosity; +} + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandAlias.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandAlias.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,153 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +#include +using namespace std; + +#include "CommandAlias.h" +#include "sii_crc.h" +#include "byteorder.h" + +/*****************************************************************************/ + +CommandAlias::CommandAlias(): + Command("alias", "Write alias addresses.") +{ +} + +/*****************************************************************************/ + +string CommandAlias::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS] " << endl + << endl + << getBriefDescription() << endl + << endl + << "Arguments:" << endl + << " ALIAS must be an unsigned 16 bit number. Zero means no alias." + << endl << endl + << "Command-specific options:" << endl + << " --slave -s Positive numerical ring position, or 'all'" + << endl + << " for all slaves (default). The --force" + << endl + << " option is required in this case." << endl + << " --force -f Acknowledge writing aliases of all" << endl + << " slaves." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/*****************************************************************************/ + +/** Writes the Secondary slave address (alias) to the slave's SII. + */ +void CommandAlias::execute(MasterDevice &m, const StringVector &args) +{ + uint16_t alias; + stringstream err, strAlias; + int number; + unsigned int numSlaves, i; + + if (args.size() != 1) { + err << "'" << getName() << "' takes exactly one argument!"; + throwInvalidUsageException(err); + } + + strAlias << args[0]; + strAlias + >> resetiosflags(ios::basefield) // guess base from prefix + >> number; + if (strAlias.fail() || number < 0x0000 || number > 0xffff) { + err << "Invalid alias '" << args[0] << "'!"; + throwInvalidUsageException(err); + } + alias = number; + + if (slavePosition == -1) { + if (!force) { + err << "This will write the alias addresses of all slaves to " + << alias << "! Please specify --force to proceed."; + throwCommandException(err); + } + + m.open(MasterDevice::ReadWrite); + numSlaves = m.slaveCount(); + + for (i = 0; i < numSlaves; i++) { + writeSlaveAlias(m, i, alias); + } + } else { + m.open(MasterDevice::ReadWrite); + writeSlaveAlias(m, slavePosition, alias); + } +} + +/*****************************************************************************/ + +/** Writes the Secondary slave address (alias) to the slave's SII. + */ +void CommandAlias::writeSlaveAlias( + MasterDevice &m, + uint16_t slavePosition, + uint16_t alias + ) +{ + ec_ioctl_slave_sii_t data; + ec_ioctl_slave_t slave; + stringstream err; + uint8_t crc; + + m.getSlave(&slave, slavePosition); + + if (slave.sii_nwords < 8) { + err << "Current SII contents are too small to set an alias " + << "(" << slave.sii_nwords << " words)!"; + throwCommandException(err); + } + + // read first 8 SII words + data.slave_position = slavePosition; + data.offset = 0; + data.nwords = 8; + data.words = new uint16_t[data.nwords]; + + try { + m.readSii(&data); + } catch (MasterDeviceException &e) { + delete [] data.words; + err << "Failed to read SII: " << e.what(); + throwCommandException(err); + } + + // write new alias address in word 4 + data.words[4] = cputole16(alias); + + // calculate checksum over words 0 to 6 + crc = calcSiiCrc((const uint8_t *) data.words, 14); + + // write new checksum into first byte of word 7 + *(uint8_t *) (data.words + 7) = crc; + + // write first 8 words with new alias and checksum + try { + m.writeSii(&data); + } catch (MasterDeviceException &e) { + delete [] data.words; + err << "Failed to read SII: " << e.what(); + throwCommandException(err); + } + + delete [] data.words; +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandAlias.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandAlias.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,29 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDALIAS_H__ +#define __COMMANDALIAS_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandAlias: + public Command +{ + public: + CommandAlias(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + void writeSlaveAlias(MasterDevice &, uint16_t, uint16_t); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandConfig.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandConfig.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,260 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +#include +#include +using namespace std; + +#include "CommandConfig.h" +#include "byteorder.h" + +/*****************************************************************************/ + +CommandConfig::CommandConfig(): + Command("config", "Show slave configurations.") +{ +} + +/*****************************************************************************/ + +string CommandConfig::helpString() const +{ + stringstream str; + + str << "[OPTIONS]" << endl + << endl + << "Output information about the slave configurations" << endl + << "supplied by the application." << endl + << endl + << "Without the --verbose option, slave configurations are" << endl + << "output one-per-line. Example:" << endl + << endl + << "1001:0 0x0000003b/0x02010000 - -" << endl + << "| | | |" << endl + << "| | | \\- Slave is operational." + << endl + << "| | \\- Slave has been found." << endl + << "| \\- Hexadecimal vendor ID and product code, separated" + << endl + << "| by a slash." << endl + << "\\- Decimal alias and position, separated by a colon." << endl + << endl + << "With the --verbose option given, the configured Pdos and" << endl + << "Sdos are additionally printed." << endl + << endl + << "Command-specific options:" << endl + << " --verbose -v Show detailed configurations." << endl; + + return str.str(); +} + +/*****************************************************************************/ + +/*****************************************************************************/ + +bool operator<(const ec_ioctl_config_t &a, const ec_ioctl_config_t &b) +{ + return a.alias < b.alias + || (a.alias == b.alias && a.position < b.position); +} + +/*****************************************************************************/ + +/** Lists the bus configuration. + */ +void CommandConfig::execute(MasterDevice &m, const StringVector &args) +{ + ec_ioctl_master_t master; + unsigned int i; + ec_ioctl_config_t config; + ConfigList configList; + + m.open(MasterDevice::Read); + m.getMaster(&master); + + for (i = 0; i < master.config_count; i++) { + m.getConfig(&config, i); + configList.push_back(config); + } + + configList.sort(); + + if (getVerbosity() == Verbose) { + showDetailedConfigs(m, configList); + } else { + listConfigs(configList); + } +} + +/*****************************************************************************/ + +/** Lists the complete bus configuration. + */ +void CommandConfig::showDetailedConfigs( + MasterDevice &m, + const ConfigList &configList + ) +{ + ConfigList::const_iterator configIter; + unsigned int j, k, l; + ec_ioctl_config_pdo_t pdo; + ec_ioctl_config_pdo_entry_t entry; + ec_ioctl_config_sdo_t sdo; + + for (configIter = configList.begin(); + configIter != configList.end(); + configIter++) { + + cout << "Alias: " + << dec << configIter->alias << endl + << "Position: " << configIter->position << endl + << "Vendor Id: 0x" + << hex << setfill('0') + << setw(8) << configIter->vendor_id << endl + << "Product code: 0x" + << setw(8) << configIter->product_code << endl + << "Attached: " << (configIter->attached ? "yes" : "no") << endl + << "Operational: " << (configIter->operational ? "yes" : "no") << endl; + + for (j = 0; j < EC_MAX_SYNC_MANAGERS; j++) { + if (configIter->syncs[j].pdo_count) { + cout << "SM" << dec << j << " (" + << (configIter->syncs[j].dir == EC_DIR_INPUT + ? "Input" : "Output") << ")" << endl; + for (k = 0; k < configIter->syncs[j].pdo_count; k++) { + m.getConfigPdo(&pdo, configIter->config_index, j, k); + + cout << " Pdo 0x" << hex + << setw(4) << pdo.index + << " \"" << pdo.name << "\"" << endl; + + for (l = 0; l < pdo.entry_count; l++) { + m.getConfigPdoEntry(&entry, + configIter->config_index, j, k, l); + + cout << " Pdo entry 0x" << hex + << setw(4) << entry.index << ":" + << setw(2) << (unsigned int) entry.subindex + << ", " << dec << (unsigned int) entry.bit_length + << " bit, \"" << entry.name << "\"" << endl; + } + } + } + } + + cout << "Sdo configuration:" << endl; + if (configIter->sdo_count) { + for (j = 0; j < configIter->sdo_count; j++) { + m.getConfigSdo(&sdo, configIter->config_index, j); + + cout << " 0x" + << hex << setfill('0') + << setw(4) << sdo.index << ":" + << setw(2) << (unsigned int) sdo.subindex + << ", " << dec << sdo.size << " byte: " << hex; + + switch (sdo.size) { + case 1: + cout << "0x" << setw(2) + << (unsigned int) *(uint8_t *) &sdo.data; + break; + case 2: + cout << "0x" << setw(4) + << le16tocpu(*(uint16_t *) &sdo.data); + break; + case 4: + cout << "0x" << setw(8) + << le32tocpu(*(uint32_t *) &sdo.data); + break; + default: + cout << "???"; + } + + cout << endl; + } + } else { + cout << " None." << endl; + } + + cout << endl; + } +} + +/*****************************************************************************/ + +/** Lists the bus configuration. + */ +void CommandConfig::listConfigs(const ConfigList &configList) +{ + ConfigList::const_iterator configIter; + stringstream str; + Info info; + typedef list InfoList; + InfoList list; + InfoList::const_iterator iter; + unsigned int maxAliasWidth = 0, maxPosWidth = 0, + maxAttWidth = 0, maxOpWidth = 0; + + for (configIter = configList.begin(); + configIter != configList.end(); + configIter++) { + + str << dec << configIter->alias; + info.alias = str.str(); + str.clear(); + str.str(""); + + str << configIter->position; + info.pos = str.str(); + str.clear(); + str.str(""); + + str << hex << setfill('0') + << "0x" << setw(8) << configIter->vendor_id + << "/0x" << setw(8) << configIter->product_code; + info.ident = str.str(); + str.clear(); + str.str(""); + + str << (configIter->attached ? "attached" : "-"); + info.att = str.str(); + str.clear(); + str.str(""); + + str << (configIter->operational ? "operational" : "-"); + info.op = str.str(); + str.clear(); + str.str(""); + + list.push_back(info); + + if (info.alias.length() > maxAliasWidth) + maxAliasWidth = info.alias.length(); + if (info.pos.length() > maxPosWidth) + maxPosWidth = info.pos.length(); + if (info.att.length() > maxAttWidth) + maxAttWidth = info.att.length(); + if (info.op.length() > maxOpWidth) + maxOpWidth = info.op.length(); + } + + for (iter = list.begin(); iter != list.end(); iter++) { + cout << setfill(' ') << right + << setw(maxAliasWidth) << iter->alias + << ":" << left + << setw(maxPosWidth) << iter->pos + << " " + << iter->ident + << " " + << setw(maxAttWidth) << iter->att << " " + << setw(maxOpWidth) << iter->op << " " + << endl; + } +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandConfig.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandConfig.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,43 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDCONFIG_H__ +#define __COMMANDCONFIG_H__ + +#include +using namespace std; + +#include "Command.h" + +/****************************************************************************/ + +class CommandConfig: + public Command +{ + public: + CommandConfig(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + struct Info { + string alias; + string pos; + string ident; + string att; + string op; + }; + + typedef list ConfigList; + + void showDetailedConfigs(MasterDevice &, const ConfigList &); + void listConfigs(const ConfigList &); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandData.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandData.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,90 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +using namespace std; + +#include "CommandData.h" + +/*****************************************************************************/ + +CommandData::CommandData(): + Command("data", "Output binary domain process data.") +{ +} + +/*****************************************************************************/ + +string CommandData::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS]" << endl + << endl + << getBriefDescription() << endl + << endl + << "Command-specific options:" << endl + << " --domain -d Positive numerical domain index, or" << endl + << " 'all' for all domains (default). In" << endl + << " this case, data of all domains are" << endl + << " concatenated." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandData::execute(MasterDevice &m, const StringVector &args) +{ + m.open(MasterDevice::Read); + + if (domainIndex == -1) { + unsigned int i; + ec_ioctl_master_t master; + + m.getMaster(&master); + + for (i = 0; i < master.domain_count; i++) { + outputDomainData(m, i); + } + } else { + outputDomainData(m, domainIndex); + } +} + +/****************************************************************************/ + +void CommandData::outputDomainData(MasterDevice &m, unsigned int domainIndex) +{ + ec_ioctl_domain_t domain; + ec_ioctl_domain_data_t data; + unsigned char *processData; + unsigned int i; + + m.getDomain(&domain, domainIndex); + + if (!domain.data_size) + return; + + processData = new unsigned char[domain.data_size]; + + try { + m.getData(&data, domainIndex, domain.data_size, processData); + } catch (MasterDeviceException &e) { + delete [] processData; + throw e; + } + + for (i = 0; i < data.data_size; i++) + cout << processData[i]; + cout.flush(); + + delete [] processData; +} + +/****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandData.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandData.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,29 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDDATA_H__ +#define __COMMANDDATA_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandData: + public Command +{ + public: + CommandData(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + void outputDomainData(MasterDevice &, unsigned int); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandDebug.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandDebug.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,70 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +using namespace std; + +#include "CommandDebug.h" + +/*****************************************************************************/ + +CommandDebug::CommandDebug(): + Command("debug", "Set the master's debug level.") +{ +} + +/*****************************************************************************/ + +string CommandDebug::helpString() const +{ + stringstream str; + + str << getName() << " " << endl + << endl + << getBriefDescription() << endl + << endl + << "Debug messages are printed to syslog." << endl + << endl + << "Arguments:" << endl + << " LEVEL can have one of the following values:" << endl + << " 0 for no debugging output," << endl + << " 1 for some debug messages, or" << endl + << " 2 for printing all frame contents (use with caution!)." + << endl << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandDebug::execute(MasterDevice &m, const StringVector &args) +{ + stringstream str; + int debugLevel; + + if (args.size() != 1) { + stringstream err; + err << "'" << getName() << "' takes exactly one argument!"; + throwInvalidUsageException(err); + } + + str << args[0]; + str >> resetiosflags(ios::basefield) // guess base from prefix + >> debugLevel; + + if (str.fail()) { + stringstream err; + err << "Invalid debug level '" << args[0] << "'!"; + throwInvalidUsageException(err); + } + + m.open(MasterDevice::ReadWrite); + m.setDebug(debugLevel); +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandDebug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandDebug.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,26 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDDEBUG_H__ +#define __COMMANDDEBUG_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandDebug: + public Command +{ + public: + CommandDebug(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandDomains.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandDomains.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,155 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +using namespace std; + +#include "CommandDomains.h" + +/*****************************************************************************/ + +CommandDomains::CommandDomains(): + Command("domains", "Show configured domains.") +{ +} + +/*****************************************************************************/ + +string CommandDomains::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS]" + << endl + << getBriefDescription() << endl + << endl + << "Without the --verbose option, the domains are displayed" << endl + << "one-per-line. Example:" << endl + << endl + << "Domain0: LogBaseAddr 0x00000000, Size 6, WorkingCounter 0/1" + << endl << endl + << "The domain's base address for the logical datagram" << endl + << "(LRD/LWR/LRW) is displayed followed by the domain's" << endl + << "process data size in byte. The last values are the current" << endl + << "datagram working counter sum and the expected working" << endl + << "counter sum. If the values are equal, all Pdos are exchanged." + << endl << endl + << "If the --verbose option is given, the participating slave" << endl + << "configurations/FMMUs and the current process data are" << endl + << "additionally displayed:" << endl + << endl + << "Domain1: LogBaseAddr 0x00000006, Size 6, WorkingCounter 0/1" + << endl + << " SlaveConfig 1001:0, SM3 ( Input), LogAddr 0x00000006, Size 6" + << endl + << " 00 00 00 00 00 00" << endl + << endl + << "The process data are displayed as hexadecimal bytes." << endl + << endl + << "Command-specific options:" << endl + << " --domain -d Positive numerical domain index," << endl + << " or 'all' for all domains (default)." + << endl + << " --verbose -v Show FMMUs and process data" << endl + << " additionally." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandDomains::execute(MasterDevice &m, const StringVector &args) +{ + m.open(MasterDevice::Read); + + if (domainIndex == -1) { + unsigned int i; + ec_ioctl_master_t master; + + m.getMaster(&master); + + for (i = 0; i < master.domain_count; i++) { + showDomain(m, i); + } + } else { + showDomain(m, domainIndex); + } +} + +/****************************************************************************/ + +void CommandDomains::showDomain(MasterDevice &m, unsigned int domainIndex) +{ + ec_ioctl_domain_t domain; + unsigned char *processData; + ec_ioctl_domain_data_t data; + unsigned int i, j; + ec_ioctl_domain_fmmu_t fmmu; + unsigned int dataOffset; + + m.getDomain(&domain, domainIndex); + + cout << "Domain" << dec << domainIndex << ":" + << " LogBaseAddr 0x" + << hex << setfill('0') + << setw(8) << domain.logical_base_address + << ", Size " << dec << setfill(' ') + << setw(3) << domain.data_size + << ", WorkingCounter " + << domain.working_counter << "/" + << domain.expected_working_counter << endl; + + if (!domain.data_size || getVerbosity() != Verbose) + return; + + processData = new unsigned char[domain.data_size]; + + try { + m.getData(&data, domainIndex, domain.data_size, processData); + } catch (MasterDeviceException &e) { + delete [] processData; + throw e; + } + + for (i = 0; i < domain.fmmu_count; i++) { + m.getFmmu(&fmmu, domainIndex, i); + + cout << " SlaveConfig " + << dec << fmmu.slave_config_alias + << ":" << fmmu.slave_config_position + << ", SM" << (unsigned int) fmmu.sync_index << " (" + << setfill(' ') << setw(6) + << (fmmu.dir == EC_DIR_INPUT ? "Input" : "Output") + << "), LogAddr 0x" + << hex << setfill('0') + << setw(8) << fmmu.logical_address + << ", Size " << dec << fmmu.data_size << endl; + + dataOffset = fmmu.logical_address - domain.logical_base_address; + if (dataOffset + fmmu.data_size > domain.data_size) { + stringstream err; + delete [] processData; + err << "Fmmu information corrupted!"; + throwCommandException(err); + } + + cout << " " << hex << setfill('0'); + for (j = 0; j < fmmu.data_size; j++) { + if (j && !(j % BreakAfterBytes)) + cout << endl << " "; + cout << setw(2) + << (unsigned int) *(processData + dataOffset + j) << " "; + } + cout << endl; + } + + delete [] processData; +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandDomains.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandDomains.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,29 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDDOMAINS_H__ +#define __COMMANDDOMAINS_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandDomains: + public Command +{ + public: + CommandDomains(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + void showDomain(MasterDevice &, unsigned int); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandDownload.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandDownload.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,219 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +using namespace std; + +#include "CommandDownload.h" +#include "coe_datatypes.h" +#include "byteorder.h" + +/*****************************************************************************/ + +CommandDownload::CommandDownload(): + Command("download", "Write an Sdo entry to a slave.") +{ +} + +/*****************************************************************************/ + +string CommandDownload::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS] " << endl + << endl + << getBriefDescription() << endl + << endl + << "The data type of the Sdo entry is taken from the Sdo" << endl + << "dictionary by default. It can be overridden with the" << endl + << "--type option. If the slave does not support the Sdo" << endl + << "information service or the Sdo is not in the dictionary," << endl + << "the --type option is mandatory." << endl + << endl + << "These are the valid Sdo entry data types:" << endl + << " int8, int16, int32, uint8, uint16, uint32, string." << endl + << endl + << "Arguments:" + << " INDEX is the Sdo index and must be an unsigned" << endl + << " 16 bit number." << endl + << " SUBINDEX is the Sdo entry subindex and must be an" << endl + << " unsigned 8 bit number." << endl + << " VALUE is the value to download and must correspond" << endl + << " to the Sdo entry datatype (see above)." << endl + << endl + << "Command-specific options:" << endl + << " --slave -s Positive numerical ring position" << endl + << " (mandatory)." << endl + << " --type -t Forced Sdo entry data type (see" << endl + << " above)." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandDownload::execute(MasterDevice &m, const StringVector &args) +{ + stringstream strIndex, strSubIndex, strValue, err; + ec_ioctl_slave_sdo_download_t data; + unsigned int number; + const CoEDataType *dataType = NULL; + + if (slavePosition < 0) { + err << "'" << getName() << "' requires a slave! " + << "Please specify --slave."; + throwInvalidUsageException(err); + } + data.slave_position = slavePosition; + + if (args.size() != 3) { + err << "'" << getName() << "' takes 3 arguments!"; + throwInvalidUsageException(err); + } + + strIndex << args[0]; + strIndex + >> resetiosflags(ios::basefield) // guess base from prefix + >> data.sdo_index; + if (strIndex.fail()) { + err << "Invalid Sdo index '" << args[0] << "'!"; + throwInvalidUsageException(err); + } + + strSubIndex << args[1]; + strSubIndex + >> resetiosflags(ios::basefield) // guess base from prefix + >> number; + if (strSubIndex.fail() || number > 0xff) { + err << "Invalid Sdo subindex '" << args[1] << "'!"; + throwInvalidUsageException(err); + } + data.sdo_entry_subindex = number; + + if (dataTypeStr != "") { // data type specified + if (!(dataType = findDataType(dataTypeStr))) { + err << "Invalid data type '" << dataTypeStr << "'!"; + throwInvalidUsageException(err); + } + } else { // no data type specified: fetch from dictionary + ec_ioctl_slave_sdo_entry_t entry; + + m.open(MasterDevice::ReadWrite); + + try { + m.getSdoEntry(&entry, slavePosition, + data.sdo_index, data.sdo_entry_subindex); + } catch (MasterDeviceException &e) { + err << "Failed to determine Sdo entry data type. " + << "Please specify --type."; + throwCommandException(err); + } + if (!(dataType = findDataType(entry.data_type))) { + err << "Pdo entry has unknown data type 0x" + << hex << setfill('0') << setw(4) << entry.data_type << "!" + << " Please specify --type."; + throwCommandException(err); + } + } + + if (dataType->byteSize) { + data.data_size = dataType->byteSize; + } else { + data.data_size = DefaultBufferSize; + } + + data.data = new uint8_t[data.data_size + 1]; + + strValue << args[2]; + strValue >> resetiosflags(ios::basefield); // guess base from prefix + strValue.exceptions(ios::failbit); + + try { + switch (dataType->coeCode) { + case 0x0002: // int8 + { + int16_t val; // uint8_t is interpreted as char + strValue >> val; + if (val > 127 || val < -128) + throw ios::failure("Value out of range"); + *data.data = val; + break; + } + case 0x0003: // int16 + { + int16_t val; + strValue >> val; + *(int16_t *) data.data = cputole16(val); + break; + } + case 0x0004: // int32 + { + int32_t val; + strValue >> val; + *(int32_t *) data.data = cputole32(val); + break; + } + case 0x0005: // uint8 + { + uint16_t val; // uint8_t is interpreted as char + strValue >> val; + if (val > 0xff) + throw ios::failure("Value out of range"); + *data.data = val; + break; + } + case 0x0006: // uint16 + { + uint16_t val; + strValue >> val; + *(uint16_t *) data.data = cputole16(val); + break; + } + case 0x0007: // uint32 + { + uint32_t val; + strValue >> val; + *(uint32_t *) data.data = cputole32(val); + break; + } + case 0x0009: // string + if (strValue.str().size() >= data.data_size) { + err << "String too large"; + throwCommandException(err); + } + data.data_size = strValue.str().size(); + strValue >> (char *) data.data; + break; + + default: + delete [] data.data; + err << "Unknown data type 0x" << hex << dataType->coeCode; + throwCommandException(err); + } + } catch (ios::failure &e) { + delete [] data.data; + err << "Invalid value argument '" << args[2] + << "' for type '" << dataType->name << "'!"; + throwInvalidUsageException(err); + } + + m.open(MasterDevice::ReadWrite); + + try { + m.sdoDownload(&data); + } catch(MasterDeviceException &e) { + delete [] data.data; + throw e; + } + + delete [] data.data; +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandDownload.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandDownload.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,29 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDDOWNLOAD_H__ +#define __COMMANDDOWNLOAD_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandDownload: + public Command +{ + public: + CommandDownload(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + enum {DefaultBufferSize = 1024}; +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandMaster.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandMaster.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,89 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +using namespace std; + +#include "CommandMaster.h" + +/*****************************************************************************/ + +CommandMaster::CommandMaster(): + Command("alias", "Show master and Ethernet device information.") +{ +} + +/****************************************************************************/ + +string CommandMaster::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS]" << endl + << endl + << getBriefDescription() << endl + << endl + << "Command-specific options:" << endl + << " --master -m Index of the master to use. Default: 0." + << endl << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandMaster::execute(MasterDevice &m, const StringVector &args) +{ + ec_ioctl_master_t data; + stringstream err; + unsigned int i; + + m.open(MasterDevice::Read); + m.getMaster(&data); + + cout + << "Master" << masterIndex << endl + << " Phase: "; + + switch (data.phase) { + case 0: cout << "Waiting for device..."; break; + case 1: cout << "Idle"; break; + case 2: cout << "Operation"; break; + default: cout << "???"; + } + + cout << endl + << " Slaves: " << data.slave_count << endl; + + for (i = 0; i < 2; i++) { + cout << " Device" << i << ": "; + if (data.devices[i].address[0] == 0x00 + && data.devices[i].address[1] == 0x00 + && data.devices[i].address[2] == 0x00 + && data.devices[i].address[3] == 0x00 + && data.devices[i].address[4] == 0x00 + && data.devices[i].address[5] == 0x00) { + cout << "None."; + } else { + cout << hex << setfill('0') + << setw(2) << (unsigned int) data.devices[i].address[0] << ":" + << setw(2) << (unsigned int) data.devices[i].address[1] << ":" + << setw(2) << (unsigned int) data.devices[i].address[2] << ":" + << setw(2) << (unsigned int) data.devices[i].address[3] << ":" + << setw(2) << (unsigned int) data.devices[i].address[4] << ":" + << setw(2) << (unsigned int) data.devices[i].address[5] << " (" + << (data.devices[i].attached ? "attached" : "waiting...") + << ")" << endl << dec + << " Tx count: " << data.devices[i].tx_count << endl + << " Rx count: " << data.devices[i].rx_count; + } + cout << endl; + } +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandMaster.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandMaster.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,26 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDMASTER_H__ +#define __COMMANDMASTER_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandMaster: + public Command +{ + public: + CommandMaster(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandPdos.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandPdos.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,142 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +using namespace std; + +#include "CommandPdos.h" + +/*****************************************************************************/ + +CommandPdos::CommandPdos(): + Command("pdos", "List Sync managers, Pdo assignment and mapping.") +{ +} + +/*****************************************************************************/ + +string CommandPdos::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS]" << endl + << endl + << getBriefDescription() << endl + << endl + << "The information is displayed in three layers, which are" << endl + << "indented accordingly:" << endl + << endl + << "1) Sync managers - Contains the sync manager information" << endl + << " from the SII: Index, physical start address, default" << endl + << " size (value from the SII), control register and enable" << endl + << " word. Example:" << endl + << endl + << " SM3: PhysAddr 0x1100, DefaultSize 0, ControlRegister 0x20," + << "Enable 1" << endl + << endl + << "2) Assigned Pdos - Pdo direction, hexadecimal index and" << endl + << " -if available- the Pdo name. Example:" << endl + << endl + << " TxPdo 0x1a00 \"Channel1\"" << endl + << endl + << "3) Mapped Pdo entries - Pdo entry index and subindex (both" << endl + << " hexadecimal), the length in bit and -if available- the" << endl + << " description. Example:" << endl + << endl + << " Pdo entry 0x3101:01, 8 bit, \"Status\"" << endl + << endl + << "Note, that the displayed Pdo assignment and Pdo mapping" << endl + << "information can either originate from the SII or from the" << endl + << "CoE communication area." << endl + << endl + << "Command-specific options:" << endl + << " --slave -s Positive numerical ring position," << endl + << " or 'all' forall slaves (default)." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandPdos::execute(MasterDevice &m, const StringVector &args) +{ + m.open(MasterDevice::Read); + + if (slavePosition == -1) { + unsigned int numSlaves = m.slaveCount(), i; + + for (i = 0; i < numSlaves; i++) { + listSlavePdos(m, i, true); + } + } else { + listSlavePdos(m, slavePosition, false); + } +} + +/****************************************************************************/ + +void CommandPdos::listSlavePdos( + MasterDevice &m, + uint16_t slavePosition, + bool withHeader + ) +{ + ec_ioctl_slave_t slave; + ec_ioctl_slave_sync_t sync; + ec_ioctl_slave_sync_pdo_t pdo; + ec_ioctl_slave_sync_pdo_entry_t entry; + unsigned int i, j, k; + + m.getSlave(&slave, slavePosition); + + if (withHeader) + cout << "=== Slave " << slavePosition << " ===" << endl; + + for (i = 0; i < slave.sync_count; i++) { + m.getSync(&sync, slavePosition, i); + + cout << "SM" << i << ":" + << " PhysAddr 0x" + << hex << setfill('0') + << setw(4) << sync.physical_start_address + << ", DefaultSize " + << dec << setfill(' ') << setw(4) << sync.default_size + << ", ControlRegister 0x" + << hex << setfill('0') << setw(2) + << (unsigned int) sync.control_register + << ", Enable " << dec << (unsigned int) sync.enable + << endl; + + for (j = 0; j < sync.pdo_count; j++) { + m.getPdo(&pdo, slavePosition, i, j); + + cout << " " << (sync.control_register & 0x04 ? "R" : "T") + << "xPdo 0x" + << hex << setfill('0') + << setw(4) << pdo.index + << " \"" << pdo.name << "\"" << endl; + + if (getVerbosity() == Quiet) + continue; + + for (k = 0; k < pdo.entry_count; k++) { + m.getPdoEntry(&entry, slavePosition, i, j, k); + + cout << " Pdo entry 0x" + << hex << setfill('0') + << setw(4) << entry.index + << ":" << setw(2) << (unsigned int) entry.subindex + << ", " << dec << (unsigned int) entry.bit_length + << " bit, \"" << entry.name << "\"" << endl; + } + } + } +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandPdos.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandPdos.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,29 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDPDOS_H__ +#define __COMMANDPDOS_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandPdos: + public Command +{ + public: + CommandPdos(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + void listSlavePdos(MasterDevice &, uint16_t, bool); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandSdos.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandSdos.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,124 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +using namespace std; + +#include "CommandSdos.h" +#include "coe_datatypes.h" + +/*****************************************************************************/ + +CommandSdos::CommandSdos(): + Command("sdos", "List Sdo dictionaries.") +{ +} + +/*****************************************************************************/ + +string CommandSdos::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS]" << endl + << endl + << getBriefDescription() << endl + << endl + << "Sdo dictionary information is displayed in two layers," << endl + << "which are indented accordingly:" << endl + << endl + << "1) Sdos - Hexadecimal Sdo index and the name. Example:" << endl + << endl + << " Sdo 0x1018, \"Identity object\"" << endl + << endl + << "2) Sdo entries - Sdo index and Sdo entry subindex (both" << endl + << " hexadecimal) followed by the data type, the length in" << endl + << " bit, and the description. Example:" << endl + << endl + << " 0x1018:01, uint32, 32 bit, \"Vendor id\"" << endl + << endl + << "If the --quiet option is given, only the Sdos are printed." + << endl << endl + << "Command-specific options:" << endl + << " --slave -s Positive numerical ring position," << endl + << " 'all' for all slaves (default)." << endl + << " --quiet -q Print only Sdos (without Sdo" << endl + << " entries)." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandSdos::execute(MasterDevice &m, const StringVector &args) +{ + m.open(MasterDevice::Read); + + if (slavePosition == -1) { + unsigned int numSlaves = m.slaveCount(), i; + + for (i = 0; i < numSlaves; i++) { + listSlaveSdos(m, i, true); + } + } else { + listSlaveSdos(m, slavePosition, false); + } +} + +/****************************************************************************/ + +void CommandSdos::listSlaveSdos( + MasterDevice &m, + uint16_t slavePosition, + bool withHeader + ) +{ + ec_ioctl_slave_t slave; + ec_ioctl_slave_sdo_t sdo; + ec_ioctl_slave_sdo_entry_t entry; + unsigned int i, j; + const CoEDataType *d; + + m.getSlave(&slave, slavePosition); + + if (withHeader) + cout << "=== Slave " << slavePosition << " ===" << endl; + + for (i = 0; i < slave.sdo_count; i++) { + m.getSdo(&sdo, slavePosition, i); + + cout << "Sdo 0x" + << hex << setfill('0') + << setw(4) << sdo.sdo_index + << ", \"" << sdo.name << "\"" << endl; + + if (getVerbosity() == Quiet) + continue; + + for (j = 0; j <= sdo.max_subindex; j++) { + m.getSdoEntry(&entry, slavePosition, -i, j); + + cout << " 0x" << hex << setfill('0') + << setw(4) << sdo.sdo_index << ":" + << setw(2) << (unsigned int) entry.sdo_entry_subindex + << ", "; + + if ((d = findDataType(entry.data_type))) { + cout << d->name; + } else { + cout << "type " << setw(4) << entry.data_type; + } + + cout << ", " << dec << entry.bit_length << " bit, \"" + << entry.description << "\"" << endl; + } + } +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandSdos.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandSdos.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,29 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDSDOS_H__ +#define __COMMANDSDOS_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandSdos: + public Command +{ + public: + CommandSdos(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + void listSlaveSdos(MasterDevice &, uint16_t, bool); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandSiiRead.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandSiiRead.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,180 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +using namespace std; + +#include "CommandSiiRead.h" +#include "byteorder.h" + +/*****************************************************************************/ + +CommandSiiRead::CommandSiiRead(): + Command("sii_read", "Output a slave's SII contents.") +{ +} + +/*****************************************************************************/ + +string CommandSiiRead::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS]" << endl + << endl + << getBriefDescription() << endl + << endl + << "Without the --verbose option, binary SII contents are" << endl + << "output." << endl + << endl + << "With the --verbose option given, a textual representation" << endl + << "of the data is output, that is separated by SII category" << endl + << "names." << endl + << endl + << "Command-specific options:" << endl + << " --slave -s Positive numerical ring position" << endl + << " (mandatory)." << endl + << " --verbose -v Output textual data with" << endl + << " category names." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandSiiRead::execute(MasterDevice &m, const StringVector &args) +{ + ec_ioctl_slave_sii_t data; + ec_ioctl_slave_t slave; + unsigned int i; + const uint16_t *categoryHeader; + uint16_t categoryType, categorySize; + stringstream err; + + if (slavePosition < 0) { + err << "'" << getName() << "' requires a slave! " + << "Please specify --slave."; + throwInvalidUsageException(err); + } + data.slave_position = slavePosition; + + m.open(MasterDevice::Read); + + m.getSlave(&slave, slavePosition); + + if (!slave.sii_nwords) + return; + + data.offset = 0; + data.nwords = slave.sii_nwords; + data.words = new uint16_t[data.nwords]; + + try { + m.readSii(&data); + } catch (MasterDeviceException &e) { + delete [] data.words; + throw e; + } + + if (getVerbosity() == Verbose) { + cout << "SII Area:" << hex << setfill('0'); + for (i = 0; i < min(data.nwords, 0x0040U) * 2; i++) { + if (i % BreakAfterBytes) { + cout << " "; + } else { + cout << endl << " "; + } + cout << setw(2) << (unsigned int) *((uint8_t *) data.words + i); + } + cout << endl; + + if (data.nwords > 0x0040U) { + // cycle through categories + categoryHeader = data.words + 0x0040U; + categoryType = le16tocpu(*categoryHeader); + while (categoryType != 0xffff) { + cout << "SII Category 0x" << hex + << setw(4) << categoryType + << " (" << getCategoryName(categoryType) << ")" << flush; + + if (categoryHeader + 1 > data.words + data.nwords) { + err << "SII data seem to be corrupted!"; + throwCommandException(err); + } + categorySize = le16tocpu(*(categoryHeader + 1)); + cout << ", " << dec << categorySize << " words" << flush; + + if (categoryHeader + 2 + categorySize + > data.words + data.nwords) { + err << "SII data seem to be corrupted!"; + throwCommandException(err); + } + + cout << hex; + for (i = 0; i < categorySize * 2U; i++) { + if (i % BreakAfterBytes) { + cout << " "; + } else { + cout << endl << " "; + } + cout << setw(2) << (unsigned int) + *((uint8_t *) (categoryHeader + 2) + i); + } + cout << endl; + + if (categoryHeader + 2 + categorySize + 1 + > data.words + data.nwords) { + err << "SII data seem to be corrupted!"; + throwCommandException(err); + } + categoryHeader += 2 + categorySize; + categoryType = le16tocpu(*categoryHeader); + } + } + } else { + for (i = 0; i < data.nwords; i++) { + uint16_t *w = data.words + i; + cout << *(uint8_t *) w << *((uint8_t *) w + 1); + } + } + + delete [] data.words; +} + +/****************************************************************************/ + +const CommandSiiRead::CategoryName CommandSiiRead::categoryNames[] = { + {0x000a, "STRINGS"}, + {0x0014, "DataTypes"}, + {0x001e, "General"}, + {0x0028, "FMMU"}, + {0x0029, "SyncM"}, + {0x0032, "TXPDO"}, + {0x0033, "RXPDO"}, + {0x003c, "DC"}, + {} +}; + +/****************************************************************************/ + +const char *CommandSiiRead::getCategoryName(uint16_t type) +{ + const CategoryName *cn = categoryNames; + + while (cn->type) { + if (cn->type == type) { + return cn->name; + } + cn++; + } + + return "unknown"; +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandSiiRead.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandSiiRead.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,34 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDSIIREAD_H__ +#define __COMMANDSIIREAD_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandSiiRead: + public Command +{ + public: + CommandSiiRead(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + struct CategoryName { + uint16_t type; + const char *name; + }; + static const CategoryName categoryNames[]; + static const char *getCategoryName(uint16_t); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandSiiWrite.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandSiiWrite.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,139 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +#include +using namespace std; + +#include "CommandSiiWrite.h" +#include "sii_crc.h" +#include "byteorder.h" + +/*****************************************************************************/ + +CommandSiiWrite::CommandSiiWrite(): + Command("sii_write", "Write SII contents to a slave.") +{ +} + +/*****************************************************************************/ + +string CommandSiiWrite::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS] " << endl + << endl + << getBriefDescription() << endl + << endl + << "The file contents are checked for validity and integrity." << endl + << "These checks can be overridden with the --force option." << endl + << endl + << "Arguments:" << endl + << " FILENAME must be a path to a file that contains a" << endl + << " positive number of words." << endl + << endl + << "Command-specific options:" << endl + << " --slave -s Positive numerical ring position" << endl + << " (mandatory)." << endl + << " --force -f Override validity checks." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandSiiWrite::execute(MasterDevice &m, const StringVector &args) +{ + stringstream err; + ec_ioctl_slave_sii_t data; + ifstream file; + unsigned int byte_size; + const uint16_t *categoryHeader; + uint16_t categoryType, categorySize; + uint8_t crc; + + if (slavePosition < 0) { + err << "'" << getName() << "' requires a slave! " + << "Please specify --slave."; + throwInvalidUsageException(err); + } + data.slave_position = slavePosition; + + if (args.size() != 1) { + err << "'" << getName() << "' takes exactly one argument!"; + throwInvalidUsageException(err); + } + + file.open(args[0].c_str(), ifstream::in | ifstream::binary); + if (file.fail()) { + err << "Failed to open '" << args[0] << "'!"; + throwCommandException(err); + } + + // get length of file + file.seekg(0, ios::end); + byte_size = file.tellg(); + file.seekg(0, ios::beg); + + if (!byte_size || byte_size % 2) { + err << "Invalid file size! Must be non-zero and even."; + throwCommandException(err); + } + + data.nwords = byte_size / 2; + if (data.nwords < 0x0041 && !force) { + err << "SII data too short (" << data.nwords << " words)! Mimimum is" + " 40 fixed words + 1 delimiter. Use --force to write anyway."; + throwCommandException(err); + } + + // allocate buffer and read file into buffer + data.words = new uint16_t[data.nwords]; + file.read((char *) data.words, byte_size); + file.close(); + + if (!force) { + // calculate checksum over words 0 to 6 + crc = calcSiiCrc((const uint8_t *) data.words, 14); + if (crc != ((const uint8_t *) data.words)[14]) { + err << "CRC incorrect. Must be 0x" + << hex << setfill('0') << setw(2) << (unsigned int) crc + << ". Use --force to write anyway."; + throwCommandException(err); + } + + // cycle through categories to detect corruption + categoryHeader = data.words + 0x0040U; + categoryType = le16tocpu(*categoryHeader); + while (categoryType != 0xffff) { + if (categoryHeader + 1 > data.words + data.nwords) { + err << "SII data seem to be corrupted! " + << "Use --force to write anyway."; + throwCommandException(err); + } + categorySize = le16tocpu(*(categoryHeader + 1)); + if (categoryHeader + 2 + categorySize + 1 + > data.words + data.nwords) { + err << "SII data seem to be corrupted! " + "Use --force to write anyway."; + throwCommandException(err); + } + categoryHeader += 2 + categorySize; + categoryType = le16tocpu(*categoryHeader); + } + } + + // send data to master + m.open(MasterDevice::ReadWrite); + data.offset = 0; + m.writeSii(&data); +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandSiiWrite.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandSiiWrite.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,26 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDSIIWRITE_H__ +#define __COMMANDSIIWRITE_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandSiiWrite: + public Command +{ + public: + CommandSiiWrite(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandSlaves.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandSlaves.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,290 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +#include +using namespace std; + +#include "CommandSlaves.h" + +/*****************************************************************************/ + +CommandSlaves::CommandSlaves(): + Command("slaves", "Display slaves on the bus.") +{ +} + +/*****************************************************************************/ + +string CommandSlaves::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS]" << endl + << endl + << getBriefDescription() << endl + << endl + << "If the --verbose option is not given, the slaves are" << endl + << "displayed one-per-line. Example:" << endl + << endl + << "1 5555:0 PREOP + EL3162 2C. Ana. Input 0-10V" << endl + << "| | | | | |" << endl + << "| | | | | \\- Name from SII if avaliable," << endl + << "| | | | | otherwise hexadecimal vendor ID" << endl + << "| | | | | and product code separated by a" << endl + << "| | | | | colon." << endl + << "| | | | \\- Error flag. '+' means no error," << endl + << "| | | | 'E' means that scanning or" << endl + << "| | | | configuration failed." << endl + << "| | | \\- Current slave state." << endl + << "| | \\- Relative position (decimal) after the last" << endl + << "| | slave with an alias address set." << endl + << "| \\- Alias address of the slave (if set to non-zero)," << endl + << "| or the alias of the last slave with an alias set," << endl + << "| or zero if there is none." << endl + << "\\- Ring position (use this with any --slave option)." << endl + << endl + << "If the --verbose option is given, a detailed (multi-line)" << endl + << "description is output for each slave." << endl + << endl + << "Command-specific options:" << endl + << " --slave -s Positive numerical ring position," << endl + << " or 'all' for all slaves (default)." << endl + << " --verbose -v Show detailed slave information." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandSlaves::execute(MasterDevice &m, const StringVector &args) +{ + m.open(MasterDevice::Read); + + if (getVerbosity() == Verbose) { + if (slavePosition == -1) { + unsigned int numSlaves = m.slaveCount(), i; + + for (i = 0; i < numSlaves; i++) { + showSlave(m, i); + } + } else { + showSlave(m, slavePosition); + } + } else { + listSlaves(m, slavePosition); + } +} + +/****************************************************************************/ + +void CommandSlaves::listSlaves( + MasterDevice &m, + int slavePosition + ) +{ + unsigned int numSlaves, i; + ec_ioctl_slave_t slave; + uint16_t lastAlias, aliasIndex; + Info info; + typedef list InfoList; + InfoList infoList; + InfoList::const_iterator iter; + stringstream str; + unsigned int maxPosWidth = 0, maxAliasWidth = 0, + maxRelPosWidth = 0, maxStateWidth = 0; + + numSlaves = m.slaveCount(); + + lastAlias = 0; + aliasIndex = 0; + for (i = 0; i < numSlaves; i++) { + m.getSlave(&slave, i); + + if (slave.alias) { + lastAlias = slave.alias; + aliasIndex = 0; + } + + if (slavePosition == -1 || i == (unsigned int) slavePosition) { + str << dec << i; + info.pos = str.str(); + str.clear(); + str.str(""); + + str << lastAlias; + info.alias = str.str(); + str.str(""); + + str << aliasIndex; + info.relPos = str.str(); + str.str(""); + + info.state = slaveState(slave.state); + info.flag = (slave.error_flag ? 'E' : '+'); + + if (strlen(slave.name)) { + info.name = slave.name; + } else { + str << "0x" << hex << setfill('0') + << setw(8) << slave.vendor_id << ":0x" + << setw(8) << slave.product_code; + info.name = str.str(); + str.str(""); + } + + + infoList.push_back(info); + + if (info.pos.length() > maxPosWidth) + maxPosWidth = info.pos.length(); + if (info.alias.length() > maxAliasWidth) + maxAliasWidth = info.alias.length(); + if (info.relPos.length() > maxRelPosWidth) + maxRelPosWidth = info.relPos.length(); + if (info.state.length() > maxStateWidth) + maxStateWidth = info.state.length(); + } + + aliasIndex++; + } + + for (iter = infoList.begin(); iter != infoList.end(); iter++) { + cout << setfill(' ') << right + << setw(maxPosWidth) << iter->pos << " " + << setw(maxAliasWidth) << iter->alias + << ":" << left + << setw(maxRelPosWidth) << iter->relPos << " " + << setw(maxStateWidth) << iter->state << " " + << iter->flag << " " + << iter->name << endl; + } +} + +/****************************************************************************/ + +void CommandSlaves::showSlave( + MasterDevice &m, + uint16_t slavePosition + ) +{ + ec_ioctl_slave_t slave; + list protoList; + list::const_iterator protoIter; + + m.getSlave(&slave, slavePosition); + + cout << "=== Slave " << dec << slavePosition << " ===" << endl; + + if (slave.alias) + cout << "Alias: " << slave.alias << endl; + + cout + << "State: " << slaveState(slave.state) << endl + << "Flag: " << (slave.error_flag ? 'E' : '+') << endl + << "Identity:" << endl + << " Vendor Id: 0x" + << hex << setfill('0') + << setw(8) << slave.vendor_id << endl + << " Product code: 0x" + << setw(8) << slave.product_code << endl + << " Revision number: 0x" + << setw(8) << slave.revision_number << endl + << " Serial number: 0x" + << setw(8) << slave.serial_number << endl; + + if (slave.mailbox_protocols) { + cout << "Mailboxes:" << endl + << " RX: 0x" + << hex << setw(4) << slave.rx_mailbox_offset << "/" + << dec << slave.rx_mailbox_size + << ", TX: 0x" + << hex << setw(4) << slave.tx_mailbox_offset << "/" + << dec << slave.tx_mailbox_size << endl + << " Supported protocols: "; + + if (slave.mailbox_protocols & EC_MBOX_AOE) { + protoList.push_back("AoE"); + } + if (slave.mailbox_protocols & EC_MBOX_EOE) { + protoList.push_back("EoE"); + } + if (slave.mailbox_protocols & EC_MBOX_COE) { + protoList.push_back("CoE"); + } + if (slave.mailbox_protocols & EC_MBOX_FOE) { + protoList.push_back("FoE"); + } + if (slave.mailbox_protocols & EC_MBOX_SOE) { + protoList.push_back("SoE"); + } + if (slave.mailbox_protocols & EC_MBOX_VOE) { + protoList.push_back("VoE"); + } + + for (protoIter = protoList.begin(); protoIter != protoList.end(); + protoIter++) { + if (protoIter != protoList.begin()) + cout << ", "; + cout << *protoIter; + } + cout << endl; + } + + if (slave.has_general_category) { + cout << "General:" << endl + << " Group: " << slave.group << endl + << " Image name: " << slave.image << endl + << " Order number: " << slave.order << endl + << " Device name: " << slave.name << endl; + + if (slave.mailbox_protocols & EC_MBOX_COE) { + cout << " CoE details:" << endl + << " Enable Sdo: " + << (slave.coe_details.enable_sdo ? "yes" : "no") << endl + << " Enable Sdo Info: " + << (slave.coe_details.enable_sdo_info ? "yes" : "no") << endl + << " Enable Pdo Assign: " + << (slave.coe_details.enable_pdo_assign + ? "yes" : "no") << endl + << " Enable Pdo Configuration: " + << (slave.coe_details.enable_pdo_configuration + ? "yes" : "no") << endl + << " Enable Upload at startup: " + << (slave.coe_details.enable_upload_at_startup + ? "yes" : "no") << endl + << " Enable Sdo complete access: " + << (slave.coe_details.enable_sdo_complete_access + ? "yes" : "no") << endl; + } + + cout << " Flags:" << endl + << " Enable SafeOp: " + << (slave.general_flags.enable_safeop ? "yes" : "no") << endl + << " Enable notLRW: " + << (slave.general_flags.enable_not_lrw ? "yes" : "no") << endl + << " Current consumption: " + << dec << slave.current_on_ebus << " mA" << endl; + } +} + +/****************************************************************************/ + +string CommandSlaves::slaveState(uint8_t state) +{ + switch (state) { + case 1: return "INIT"; + case 2: return "PREOP"; + case 4: return "SAFEOP"; + case 8: return "OP"; + default: return "???"; + } +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandSlaves.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandSlaves.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,41 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDSLAVES_H__ +#define __COMMANDSLAVES_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandSlaves: + public Command +{ + public: + CommandSlaves(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + struct Info { + string pos; + string alias; + string relPos; + string state; + string flag; + string name; + }; + + void listSlaves(MasterDevice &, int); + void showSlave(MasterDevice &, uint16_t); + + static string slaveState(uint8_t); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandStates.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandStates.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,82 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +using namespace std; + +#include "CommandStates.h" + +/*****************************************************************************/ + +CommandStates::CommandStates(): + Command("states", "Request application-layer states.") +{ +} + +/*****************************************************************************/ + +string CommandStates::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS] " << endl + << endl + << getBriefDescription() << endl + << endl + << "Arguments:" << endl + << " STATE can be 'INIT', 'PREOP', 'SAFEOP', or 'OP'" << endl + << endl + << "Command-specific options:" << endl + << " --slave -s Positive numerical ring position," << endl + << " or 'all' for all slaves (default)." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandStates::execute(MasterDevice &m, const StringVector &args) +{ + stringstream err; + string stateStr; + uint8_t state = 0x00; + + if (args.size() != 1) { + err << "'" << getName() << "' takes exactly one argument!"; + throwInvalidUsageException(err); + } + + stateStr = args[0]; + transform(stateStr.begin(), stateStr.end(), + stateStr.begin(), (int (*) (int)) std::toupper); + + if (stateStr == "INIT") { + state = 0x01; + } else if (stateStr == "PREOP") { + state = 0x02; + } else if (stateStr == "SAFEOP") { + state = 0x04; + } else if (stateStr == "OP") { + state = 0x08; + } else { + err << "Invalid state '" << args[0] << "'!"; + throwInvalidUsageException(err); + } + + m.open(MasterDevice::ReadWrite); + + if (slavePosition == -1) { + unsigned int i, numSlaves = m.slaveCount(); + for (i = 0; i < numSlaves; i++) + m.requestState(i, state); + } else { + m.requestState(slavePosition, state); + } +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandStates.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandStates.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,28 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDSTATES_H__ +#define __COMMANDSTATES_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandStates: + public Command +{ + public: + CommandStates(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandUpload.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandUpload.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,205 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +using namespace std; + +#include "CommandUpload.h" +#include "coe_datatypes.h" +#include "byteorder.h" + +/*****************************************************************************/ + +CommandUpload::CommandUpload(): + Command("upload", "Read an Sdo entry from a slave.") +{ +} + +/*****************************************************************************/ + +string CommandUpload::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS] " << endl + << endl + << getBriefDescription() << endl + << endl + << "The data type of the Sdo entry is taken from the Sdo" << endl + << "dictionary by default. It can be overridden with the" << endl + << "--type option. If the slave does not support the Sdo" << endl + << "information service or the Sdo is not in the dictionary," << endl + << "the --type option is mandatory." << endl + << endl + << "These are the valid Sdo entry data types:" << endl + << " int8, int16, int32, uint8, uint16, uint32, string." << endl + << endl + << "Arguments:" << endl + << " INDEX is the Sdo index and must be an unsigned" << endl + << " 16 bit number." << endl + << " SUBINDEX is the Sdo entry subindex and must be an" << endl + << " unsigned 8 bit number." << endl + << endl + << "Command-specific options:" << endl + << " --slave -s Positive numerical ring position" << endl + << " (mandatory)." << endl + << " --type -t Forced Sdo entry data type (see" << endl + << " above)." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandUpload::execute(MasterDevice &m, const StringVector &args) +{ + stringstream err, strIndex, strSubIndex; + int sval; + ec_ioctl_slave_sdo_upload_t data; + unsigned int uval; + const CoEDataType *dataType = NULL; + + if (slavePosition < 0) { + err << "'" << getName() << "' requires a slave! " + << "Please specify --slave."; + throwInvalidUsageException(err); + } + data.slave_position = slavePosition; + + if (args.size() != 2) { + err << "'" << getName() << "' takes two arguments!"; + throwInvalidUsageException(err); + } + + strIndex << args[0]; + strIndex + >> resetiosflags(ios::basefield) // guess base from prefix + >> data.sdo_index; + if (strIndex.fail()) { + err << "Invalid Sdo index '" << args[0] << "'!"; + throwInvalidUsageException(err); + } + + strSubIndex << args[1]; + strSubIndex + >> resetiosflags(ios::basefield) // guess base from prefix + >> uval; + if (strSubIndex.fail() || uval > 0xff) { + err << "Invalid Sdo subindex '" << args[1] << "'!"; + throwInvalidUsageException(err); + } + data.sdo_entry_subindex = uval; + + if (dataTypeStr != "") { // data type specified + if (!(dataType = findDataType(dataTypeStr))) { + err << "Invalid data type '" << dataTypeStr << "'!"; + throwInvalidUsageException(err); + } + } else { // no data type specified: fetch from dictionary + ec_ioctl_slave_sdo_entry_t entry; + + m.open(MasterDevice::Read); + + try { + m.getSdoEntry(&entry, slavePosition, + data.sdo_index, data.sdo_entry_subindex); + } catch (MasterDeviceException &e) { + err << "Failed to determine Sdo entry data type. " + << "Please specify --type."; + throwCommandException(err); + } + if (!(dataType = findDataType(entry.data_type))) { + err << "Pdo entry has unknown data type 0x" + << hex << setfill('0') << setw(4) << entry.data_type << "!" + << " Please specify --type."; + throwCommandException(err); + } + } + + if (dataType->byteSize) { + data.target_size = dataType->byteSize; + } else { + data.target_size = DefaultBufferSize; + } + + data.target = new uint8_t[data.target_size + 1]; + + m.open(MasterDevice::Read); + + try { + m.sdoUpload(&data); + } catch (MasterDeviceException &e) { + delete [] data.target; + throw e; + } + + m.close(); + + if (dataType->byteSize && data.data_size != dataType->byteSize) { + err << "Data type mismatch. Expected " << dataType->name + << " with " << dataType->byteSize << " byte, but got " + << data.data_size << " byte."; + throwCommandException(err); + } + + cout << setfill('0'); + switch (dataType->coeCode) { + case 0x0002: // int8 + sval = *(int8_t *) data.target; + cout << sval << " 0x" << hex << setw(2) << sval << endl; + break; + case 0x0003: // int16 + sval = le16tocpu(*(int16_t *) data.target); + cout << sval << " 0x" << hex << setw(4) << sval << endl; + break; + case 0x0004: // int32 + sval = le32tocpu(*(int32_t *) data.target); + cout << sval << " 0x" << hex << setw(8) << sval << endl; + break; + case 0x0005: // uint8 + uval = (unsigned int) *(uint8_t *) data.target; + cout << uval << " 0x" << hex << setw(2) << uval << endl; + break; + case 0x0006: // uint16 + uval = le16tocpu(*(uint16_t *) data.target); + cout << uval << " 0x" << hex << setw(4) << uval << endl; + break; + case 0x0007: // uint32 + uval = le32tocpu(*(uint32_t *) data.target); + cout << uval << " 0x" << hex << setw(8) << uval << endl; + break; + case 0x0009: // string + cout << string((const char *) data.target, data.data_size) + << endl; + break; + default: + printRawData(data.target, data.data_size); // FIXME + break; + } + + delete [] data.target; +} + +/****************************************************************************/ + +void CommandUpload::printRawData( + const uint8_t *data, + unsigned int size + ) +{ + cout << hex << setfill('0'); + while (size--) { + cout << "0x" << setw(2) << (unsigned int) *data++; + if (size) + cout << " "; + } + cout << endl; +} + +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandUpload.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandUpload.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,31 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDUPLOAD_H__ +#define __COMMANDUPLOAD_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandUpload: + public Command +{ + public: + CommandUpload(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + enum {DefaultBufferSize = 1024}; + + static void printRawData(const uint8_t *, unsigned int); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandXml.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandXml.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,180 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +using namespace std; + +#include "CommandXml.h" + +/*****************************************************************************/ + +CommandXml::CommandXml(): + Command("xml", "Generate slave information XML.") +{ +} + +/*****************************************************************************/ + +string CommandXml::helpString() const +{ + stringstream str; + + str << getName() << " [OPTIONS]" + << endl + << getBriefDescription() << endl + << endl + << "Note that the Pdo information can either originate" << endl + << "from the SII or from the CoE communication area. For" << endl + << "some slaves, this is dependant on the last slave" << endl + << "configuration." << endl + << endl + << "Command-specific options:" << endl + << " --slave -s Positive numerical ring position," << endl + << " or 'all' for all slaves (default)." << endl + << endl + << numericInfo(); + + return str.str(); +} + +/****************************************************************************/ + +void CommandXml::execute(MasterDevice &m, const StringVector &args) +{ + m.open(MasterDevice::Read); + + if (slavePosition == -1) { + unsigned int numSlaves = m.slaveCount(), i; + + for (i = 0; i < numSlaves; i++) { + generateSlaveXml(m, i); + } + } else { + generateSlaveXml(m, slavePosition); + } +} + +/****************************************************************************/ + +void CommandXml::generateSlaveXml(MasterDevice &m, uint16_t slavePosition) +{ + ec_ioctl_slave_t slave; + ec_ioctl_slave_sync_t sync; + ec_ioctl_slave_sync_pdo_t pdo; + string pdoType; + ec_ioctl_slave_sync_pdo_entry_t entry; + unsigned int i, j, k; + + m.getSlave(&slave, slavePosition); + + cout + << "" << endl + << " " << endl + << " " << endl + << " " << endl + << " " << slave.vendor_id << "" << endl + << " " << endl + << " " << endl + << " " << endl + << " " << endl + << " " << slave.order << "" << endl; + + if (strlen(slave.name)) { + cout + << " " << endl; + } + + for (i = 0; i < slave.sync_count; i++) { + m.getSync(&sync, slavePosition, i); + + cout + << " " << endl; + } + + for (i = 0; i < slave.sync_count; i++) { + m.getSync(&sync, slavePosition, i); + + for (j = 0; j < sync.pdo_count; j++) { + m.getPdo(&pdo, slavePosition, i, j); + pdoType = (sync.control_register & 0x04 ? "R" : "T"); + pdoType += "xPdo"; + + cout + << " <" << pdoType + << " Sm=\"" << i << "\" Fixed=\"1\" Mandatory=\"1\">" << endl + << " #x" + << hex << setfill('0') << setw(4) << pdo.index + << "" << endl + << " " << pdo.name << "" << endl; + + for (k = 0; k < pdo.entry_count; k++) { + m.getPdoEntry(&entry, slavePosition, i, j, k); + + cout + << " " << endl + << " #x" + << hex << setfill('0') << setw(4) << entry.index + << "" << endl; + if (entry.index) + cout + << " " + << dec << (unsigned int) entry.subindex + << "" << endl; + + cout + << " " + << dec << (unsigned int) entry.bit_length + << "" << endl; + + if (entry.index) { + cout + << " " << entry.name + << "" << endl + << " "; + + if (entry.bit_length == 1) { + cout << "BOOL"; + } else if (!(entry.bit_length % 8)) { + if (entry.bit_length <= 64) + cout << "UINT" << (unsigned int) entry.bit_length; + else + cout << "STRING(" + << (unsigned int) (entry.bit_length / 8) + << ")"; + } else { + cerr << "Invalid bit length " + << (unsigned int) entry.bit_length << endl; + } + + cout << "" << endl; + } + + cout << " " << endl; + } + + cout + << " " << endl; + } + } + + cout + << " " << endl + << " " << endl + << " " << endl + << "" << endl; +} +/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/CommandXml.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/CommandXml.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,29 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __COMMANDXML_H__ +#define __COMMANDXML_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandXml: + public Command +{ + public: + CommandXml(); + + string helpString() const; + void execute(MasterDevice &, const StringVector &); + + protected: + void generateSlaveXml(MasterDevice &, uint16_t); +}; + +/****************************************************************************/ + +#endif diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/Makefile.am --- a/tool/Makefile.am Thu Jul 24 08:15:44 2008 +0000 +++ b/tool/Makefile.am Thu Jul 24 13:27:06 2008 +0000 @@ -29,30 +29,33 @@ # standard) as the (only) precondition to have the right to use EtherCAT # Technology, IP and trade marks. # +# vim: syntax=make +# #------------------------------------------------------------------------------ bin_PROGRAMS = ethercat ethercat_SOURCES = \ - MasterDevice.cpp MasterDevice.h \ + MasterDevice.cpp MasterDevice.h \ + Command.cpp \ + CommandAlias.cpp \ + CommandConfig.cpp \ + CommandData.cpp \ + CommandDebug.cpp \ + CommandDomains.cpp \ + CommandDownload.cpp \ + CommandMaster.cpp \ + CommandPdos.cpp \ + CommandSdos.cpp \ + CommandSiiRead.cpp \ + CommandSiiWrite.cpp \ + CommandSlaves.cpp \ + CommandStates.cpp \ + CommandUpload.cpp \ + CommandXml.cpp \ coe_datatypes.cpp \ sii_crc.cpp \ - cmd_alias.cpp \ - cmd_config.cpp \ - cmd_data.cpp \ - cmd_debug.cpp \ - cmd_domain.cpp \ - cmd_master.cpp \ - cmd_pdos.cpp \ - cmd_sdos.cpp \ - cmd_download.cpp \ - cmd_upload.cpp \ - cmd_slaves.cpp \ - cmd_sii_read.cpp \ - cmd_sii_write.cpp \ - cmd_states.cpp \ - cmd_xml.cpp \ - main.cpp + main.cpp ethercat_CXXFLAGS = -I../master -Wall diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/byteorder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/byteorder.h Thu Jul 24 13:27:06 2008 +0000 @@ -0,0 +1,40 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include + +/*****************************************************************************/ + +#define swap16(x) \ + ((uint16_t)( \ + (((uint16_t)(x) & 0x00ffU) << 8) | \ + (((uint16_t)(x) & 0xff00U) >> 8) )) +#define swap32(x) \ + ((uint32_t)( \ + (((uint32_t)(x) & 0x000000ffUL) << 24) | \ + (((uint32_t)(x) & 0x0000ff00UL) << 8) | \ + (((uint32_t)(x) & 0x00ff0000UL) >> 8) | \ + (((uint32_t)(x) & 0xff000000UL) >> 24) )) + +#if __BYTE_ORDER == __LITTLE_ENDIAN + +#define le16tocpu(x) x +#define le32tocpu(x) x + +#define cputole16(x) x +#define cputole32(x) x + +#elif __BYTE_ORDER == __BIG_ENDIAN + +#define le16tocpu(x) swap16(x) +#define le32tocpu(x) swap32(x) + +#define cputole16(x) swap16(x) +#define cputole32(x) swap32(x) + +#endif + +/****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_alias.cpp --- a/tool/cmd_alias.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -#include -using namespace std; - -#include "globals.h" -#include "sii_crc.h" - -/*****************************************************************************/ - -const char *help_alias = - "[OPTIONS] \n" - "\n" - "Write the secondary slave address (alias) for either\n" - "one or for multiple slaves.\n" - "\n" - "Arguments:\n" - " ALIAS must be an unsigned 16 bit number. Zero means no alias.\n" - "\n" - "Command-specific options:\n" - " --slave -s Positive numerical ring position, or 'all' for\n" - " all slaves (default). The --force option is\n" - " required in this case.\n" - " --force Acknowledge writing aliases of all slaves.\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/*****************************************************************************/ - -void writeSlaveAlias(uint16_t, uint16_t); - -/*****************************************************************************/ - -/** Writes the Secondary slave address (alias) to the slave's SII. - */ -void command_alias(void) -{ - uint16_t alias; - stringstream err, strAlias; - int number; - unsigned int numSlaves, i; - - if (commandArgs.size() != 1) { - err << "'" << commandName << "' takes exactly one argument!"; - throw InvalidUsageException(err); - } - - strAlias << commandArgs[0]; - strAlias - >> resetiosflags(ios::basefield) // guess base from prefix - >> number; - if (strAlias.fail() || number < 0x0000 || number > 0xffff) { - err << "Invalid alias '" << commandArgs[0] << "'!"; - throw InvalidUsageException(err); - } - alias = number; - - if (slavePosition == -1) { - if (!force) { - err << "This will write the alias addresses of all slaves to " - << alias << "! Please specify --force to proceed."; - throw CommandException(err); - } - - masterDev.open(MasterDevice::ReadWrite); - numSlaves = masterDev.slaveCount(); - - for (i = 0; i < numSlaves; i++) { - writeSlaveAlias(i, alias); - } - } else { - masterDev.open(MasterDevice::ReadWrite); - writeSlaveAlias(slavePosition, alias); - } -} - -/*****************************************************************************/ - -/** Writes the Secondary slave address (alias) to the slave's SII. - */ -void writeSlaveAlias( - uint16_t slavePosition, - uint16_t alias - ) -{ - ec_ioctl_slave_sii_t data; - ec_ioctl_slave_t slave; - stringstream err; - uint8_t crc; - - masterDev.getSlave(&slave, slavePosition); - - if (slave.sii_nwords < 8) { - err << "Current SII contents are too small to set an alias " - << "(" << slave.sii_nwords << " words)!"; - throw CommandException(err); - } - - // read first 8 SII words - data.slave_position = slavePosition; - data.offset = 0; - data.nwords = 8; - data.words = new uint16_t[data.nwords]; - - try { - masterDev.readSii(&data); - } catch (MasterDeviceException &e) { - delete [] data.words; - err << "Failed to read SII: " << e.what(); - throw CommandException(err); - } - - // write new alias address in word 4 - data.words[4] = cputole16(alias); - - // calculate checksum over words 0 to 6 - crc = calcSiiCrc((const uint8_t *) data.words, 14); - - // write new checksum into first byte of word 7 - *(uint8_t *) (data.words + 7) = crc; - - // write first 8 words with new alias and checksum - try { - masterDev.writeSii(&data); - } catch (MasterDeviceException &e) { - delete [] data.words; - err << "Failed to read SII: " << e.what(); - throw CommandException(err); - } - - delete [] data.words; -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_config.cpp --- a/tool/cmd_config.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,254 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -#include -#include -using namespace std; - -#include "globals.h" - -/*****************************************************************************/ - -const char *help_config = - "[OPTIONS]\n" - "\n" - "Output information about the slave configurations supplied by the\n" - "application.\n" - "\n" - "Without the --verbose option, each line of output shows one slave\n" - "configuration. Example:\n" - "\n" - "1001:0 0x0000003b/0x02010000 - -\n" - "| | | |\n" - "| | | \\- Slave is operational.\n" - "| | \\- Slave has been found.\n" - "| \\- Hexadecimal vendor ID and product code, separated by a\n" - "| slash.\n" - "\\- Decimal alias and position, separated by a colon.\n" - "\n" - "With the --verbose option given, the configured Pdos and Sdos are\n" - "additionally printed.\n" - "\n" - "Command-specific options:\n" - " --verbose -v Show detailed configurations.\n"; - -/*****************************************************************************/ - -struct ConfigInfo { - string alias; - string pos; - string ident; - string att; - string op; -}; - -typedef list ConfigList; - -void showDetailedConfigs(const ConfigList &configList); -void listConfigs(const ConfigList &configList); - -/*****************************************************************************/ - -bool operator<(const ec_ioctl_config_t &a, const ec_ioctl_config_t &b) -{ - return a.alias < b.alias - || (a.alias == b.alias && a.position < b.position); -} - -/*****************************************************************************/ - -/** Lists the bus configuration. - */ -void command_config(void) -{ - ec_ioctl_master_t master; - unsigned int i; - ec_ioctl_config_t config; - ConfigList configList; - - masterDev.open(MasterDevice::Read); - masterDev.getMaster(&master); - - for (i = 0; i < master.config_count; i++) { - masterDev.getConfig(&config, i); - configList.push_back(config); - } - - configList.sort(); - - if (verbosity == Verbose) { - showDetailedConfigs(configList); - } else { - listConfigs(configList); - } -} - -/*****************************************************************************/ - -/** Lists the complete bus configuration. - */ -void showDetailedConfigs(const ConfigList &configList) -{ - ConfigList::const_iterator configIter; - unsigned int j, k, l; - ec_ioctl_config_pdo_t pdo; - ec_ioctl_config_pdo_entry_t entry; - ec_ioctl_config_sdo_t sdo; - - for (configIter = configList.begin(); - configIter != configList.end(); - configIter++) { - - cout << "Alias: " - << dec << configIter->alias << endl - << "Position: " << configIter->position << endl - << "Vendor Id: 0x" - << hex << setfill('0') - << setw(8) << configIter->vendor_id << endl - << "Product code: 0x" - << setw(8) << configIter->product_code << endl - << "Attached: " << (configIter->attached ? "yes" : "no") << endl - << "Operational: " << (configIter->operational ? "yes" : "no") << endl; - - for (j = 0; j < EC_MAX_SYNC_MANAGERS; j++) { - if (configIter->syncs[j].pdo_count) { - cout << "SM" << dec << j << " (" - << (configIter->syncs[j].dir == EC_DIR_INPUT - ? "Input" : "Output") << ")" << endl; - for (k = 0; k < configIter->syncs[j].pdo_count; k++) { - masterDev.getConfigPdo(&pdo, configIter->config_index, j, k); - - cout << " Pdo 0x" << hex - << setw(4) << pdo.index - << " \"" << pdo.name << "\"" << endl; - - for (l = 0; l < pdo.entry_count; l++) { - masterDev.getConfigPdoEntry(&entry, - configIter->config_index, j, k, l); - - cout << " Pdo entry 0x" << hex - << setw(4) << entry.index << ":" - << setw(2) << (unsigned int) entry.subindex - << ", " << dec << (unsigned int) entry.bit_length - << " bit, \"" << entry.name << "\"" << endl; - } - } - } - } - - cout << "Sdo configuration:" << endl; - if (configIter->sdo_count) { - for (j = 0; j < configIter->sdo_count; j++) { - masterDev.getConfigSdo(&sdo, configIter->config_index, j); - - cout << " 0x" - << hex << setfill('0') - << setw(4) << sdo.index << ":" - << setw(2) << (unsigned int) sdo.subindex - << ", " << dec << sdo.size << " byte: " << hex; - - switch (sdo.size) { - case 1: - cout << "0x" << setw(2) - << (unsigned int) *(uint8_t *) &sdo.data; - break; - case 2: - cout << "0x" << setw(4) - << le16tocpu(*(uint16_t *) &sdo.data); - break; - case 4: - cout << "0x" << setw(8) - << le32tocpu(*(uint32_t *) &sdo.data); - break; - default: - cout << "???"; - } - - cout << endl; - } - } else { - cout << " None." << endl; - } - - cout << endl; - } -} - -/*****************************************************************************/ - -/** Lists the bus configuration. - */ -void listConfigs(const ConfigList &configList) -{ - ConfigList::const_iterator configIter; - stringstream str; - ConfigInfo info; - typedef list ConfigInfoList; - ConfigInfoList list; - ConfigInfoList::const_iterator iter; - unsigned int maxAliasWidth = 0, maxPosWidth = 0, - maxAttWidth = 0, maxOpWidth = 0; - - for (configIter = configList.begin(); - configIter != configList.end(); - configIter++) { - - str << dec << configIter->alias; - info.alias = str.str(); - str.clear(); - str.str(""); - - str << configIter->position; - info.pos = str.str(); - str.clear(); - str.str(""); - - str << hex << setfill('0') - << "0x" << setw(8) << configIter->vendor_id - << "/0x" << setw(8) << configIter->product_code; - info.ident = str.str(); - str.clear(); - str.str(""); - - str << (configIter->attached ? "attached" : "-"); - info.att = str.str(); - str.clear(); - str.str(""); - - str << (configIter->operational ? "operational" : "-"); - info.op = str.str(); - str.clear(); - str.str(""); - - list.push_back(info); - - if (info.alias.length() > maxAliasWidth) - maxAliasWidth = info.alias.length(); - if (info.pos.length() > maxPosWidth) - maxPosWidth = info.pos.length(); - if (info.att.length() > maxAttWidth) - maxAttWidth = info.att.length(); - if (info.op.length() > maxOpWidth) - maxOpWidth = info.op.length(); - } - - for (iter = list.begin(); iter != list.end(); iter++) { - cout << setfill(' ') << right - << setw(maxAliasWidth) << iter->alias - << ":" << left - << setw(maxPosWidth) << iter->pos - << " " - << iter->ident - << " " - << setw(maxAttWidth) << iter->att << " " - << setw(maxOpWidth) << iter->op << " " - << endl; - } -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_data.cpp --- a/tool/cmd_data.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -using namespace std; - -#include "globals.h" - -/*****************************************************************************/ - -const char *help_data = - "[OPTIONS]\n" - "\n" - "Output binary domain data.\n" - "\n" - "Command-specific options:\n" - " --domain -d Positive numerical domain index, or 'all' for\n" - " all domains (default). In this case, data of all\n" - " domains are concatenated.\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void outputDomainData(unsigned int); - -/****************************************************************************/ - -void command_data() -{ - masterDev.open(MasterDevice::Read); - - if (domainIndex == -1) { - unsigned int i; - ec_ioctl_master_t master; - - masterDev.getMaster(&master); - - for (i = 0; i < master.domain_count; i++) { - outputDomainData(i); - } - } else { - outputDomainData(domainIndex); - } -} - -/****************************************************************************/ - -void outputDomainData(unsigned int domainIndex) -{ - ec_ioctl_domain_t domain; - ec_ioctl_domain_data_t data; - unsigned char *processData; - unsigned int i; - - masterDev.getDomain(&domain, domainIndex); - - if (!domain.data_size) - return; - - processData = new unsigned char[domain.data_size]; - - try { - masterDev.getData(&data, domainIndex, domain.data_size, processData); - } catch (MasterDeviceException &e) { - delete [] processData; - throw e; - } - - for (i = 0; i < data.data_size; i++) - cout << processData[i]; - cout.flush(); - - delete [] processData; -} - -/****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_debug.cpp --- a/tool/cmd_debug.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -using namespace std; - -#include "globals.h" - -/*****************************************************************************/ - -const char *help_debug = - "\n" - "\n" - "Set the master debug level.\n" - "\n" - "Debug messages are printed to syslog.\n" - "\n" - "Arguments:\n" - " LEVEL can have one of the following values:\n" - " 0 for no debugging output,\n" - " 1 for some debug messages, or\n" - " 2 for printing all frame contents (use with caution!).\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void command_debug(void) -{ - stringstream str; - int debugLevel; - - if (commandArgs.size() != 1) { - stringstream err; - err << "'" << commandName << "' takes exactly one argument!"; - throw InvalidUsageException(err); - } - - str << commandArgs[0]; - str >> resetiosflags(ios::basefield) // guess base from prefix - >> debugLevel; - - if (str.fail()) { - stringstream err; - err << "Invalid debug level '" << commandArgs[0] << "'!"; - throw InvalidUsageException(err); - } - - masterDev.open(MasterDevice::ReadWrite); - masterDev.setDebug(debugLevel); -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_domain.cpp --- a/tool/cmd_domain.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -using namespace std; - -#include "globals.h" - -/*****************************************************************************/ - -const char *help_domains = - "[OPTIONS]\n" - "\n" - "Show information about the application's configured domains.\n" - "\n" - "Without the --verbose option, the domains are displayed one-per-line.\n" - "Example:\n" - "\n" - "Domain0: LogBaseAddr 0x00000000, Size 6, WorkingCounter 0/1\n" - "\n" - "The domain's base address for the logical datagram (LRD/LWR/LRW)\n" - "is displayed followed by the domain's process data size in byte.\n" - "The last values are the current datagram working counter sum and\n" - "the expected working counter sum. If the values are equal, all\n" - "Pdos are exchanged.\n" - "\n" - "If the --verbose option is given, the participating slave\n" - "configurations/FMMUs and the current process data are additionally\n" - "displayed:\n" - "\n" - "Domain1: LogBaseAddr 0x00000006, Size 6, WorkingCounter 0/1\n" - " SlaveConfig 1001:0, SM3 ( Input), LogAddr 0x00000006, Size 6\n" - " 00 00 00 00 00 00\n" - "\n" - "The process data are displayed as hexadecimal bytes.\n" - "\n" - "Command-specific options:\n" - " --domain -d Positive numerical domain index, or 'all'\n" - " for all domains (default).\n" - " --verbose -v Show FMMUs and process data additionally.\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void showDomain(unsigned int); - -/****************************************************************************/ - -void command_domains(void) -{ - masterDev.open(MasterDevice::Read); - - if (domainIndex == -1) { - unsigned int i; - ec_ioctl_master_t master; - - masterDev.getMaster(&master); - - for (i = 0; i < master.domain_count; i++) { - showDomain(i); - } - } else { - showDomain(domainIndex); - } -} - -/****************************************************************************/ - -void showDomain(unsigned int domainIndex) -{ - ec_ioctl_domain_t domain; - unsigned char *processData; - ec_ioctl_domain_data_t data; - unsigned int i, j; - ec_ioctl_domain_fmmu_t fmmu; - unsigned int dataOffset; - - masterDev.getDomain(&domain, domainIndex); - - cout << "Domain" << dec << domainIndex << ":" - << " LogBaseAddr 0x" - << hex << setfill('0') - << setw(8) << domain.logical_base_address - << ", Size " << dec << setfill(' ') - << setw(3) << domain.data_size - << ", WorkingCounter " - << domain.working_counter << "/" - << domain.expected_working_counter << endl; - - if (!domain.data_size || verbosity != Verbose) - return; - - processData = new unsigned char[domain.data_size]; - - try { - masterDev.getData(&data, domainIndex, domain.data_size, processData); - } catch (MasterDeviceException &e) { - delete [] processData; - throw e; - } - - for (i = 0; i < domain.fmmu_count; i++) { - masterDev.getFmmu(&fmmu, domainIndex, i); - - cout << " SlaveConfig " - << dec << fmmu.slave_config_alias - << ":" << fmmu.slave_config_position - << ", SM" << (unsigned int) fmmu.sync_index << " (" - << setfill(' ') << setw(6) - << (fmmu.dir == EC_DIR_INPUT ? "Input" : "Output") - << "), LogAddr 0x" - << hex << setfill('0') - << setw(8) << fmmu.logical_address - << ", Size " << dec << fmmu.data_size << endl; - - dataOffset = fmmu.logical_address - domain.logical_base_address; - if (dataOffset + fmmu.data_size > domain.data_size) { - stringstream err; - delete [] processData; - err << "Fmmu information corrupted!"; - throw CommandException(err); - } - - cout << " " << hex << setfill('0'); - for (j = 0; j < fmmu.data_size; j++) { - if (j && !(j % BreakAfterBytes)) - cout << endl << " "; - cout << setw(2) - << (unsigned int) *(processData + dataOffset + j) << " "; - } - cout << endl; - } - - delete [] processData; -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_download.cpp --- a/tool/cmd_download.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,203 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -using namespace std; - -#include "globals.h" -#include "coe_datatypes.h" - -/****************************************************************************/ - -const char *help_download = - "[OPTIONS] \n" - "\n" - "Download an Sdo entry to a slave.\n" - "\n" - "The data type of the Sdo entry is taken from the Sdo dictionary by\n" - "default. It can be overridden with the --type option. If the slave\n" - "does not support the Sdo information service or the Sdo is not in the\n" - "dictionary, the --type option is mandatory.\n" - "\n" - "These are the valid Sdo entry data types:\n" - " int8, int16, int32, uint8, uint16, uint32, string.\n" - "\n" - "Arguments:\n" - " INDEX is the Sdo index and must be an unsigned 16 bit number.\n" - " SUBINDEX is the Sdo entry subindex and must be an unsigned 8 bit\n" - " number.\n" - " VALUE is the value to download and must correspond to the Sdo\n" - " entry datatype (see above).\n" - "\n" - "Command-specific options:\n" - " --slave -s Positive numerical ring position (mandatory).\n" - " --type -t Forced Sdo entry data type (see above).\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - - -/****************************************************************************/ - -void command_download(void) -{ - stringstream strIndex, strSubIndex, strValue, err; - ec_ioctl_slave_sdo_download_t data; - unsigned int number; - const CoEDataType *dataType = NULL; - - if (slavePosition < 0) { - err << "'" << commandName << "' requires a slave! " - << "Please specify --slave."; - throw InvalidUsageException(err); - } - data.slave_position = slavePosition; - - if (commandArgs.size() != 3) { - err << "'" << commandName << "' takes 3 arguments!"; - throw InvalidUsageException(err); - } - - strIndex << commandArgs[0]; - strIndex - >> resetiosflags(ios::basefield) // guess base from prefix - >> data.sdo_index; - if (strIndex.fail()) { - err << "Invalid Sdo index '" << commandArgs[0] << "'!"; - throw InvalidUsageException(err); - } - - strSubIndex << commandArgs[1]; - strSubIndex - >> resetiosflags(ios::basefield) // guess base from prefix - >> number; - if (strSubIndex.fail() || number > 0xff) { - err << "Invalid Sdo subindex '" << commandArgs[1] << "'!"; - throw InvalidUsageException(err); - } - data.sdo_entry_subindex = number; - - if (dataTypeStr != "") { // data type specified - if (!(dataType = findDataType(dataTypeStr))) { - err << "Invalid data type '" << dataTypeStr << "'!"; - throw InvalidUsageException(err); - } - } else { // no data type specified: fetch from dictionary - ec_ioctl_slave_sdo_entry_t entry; - - masterDev.open(MasterDevice::ReadWrite); - - try { - masterDev.getSdoEntry(&entry, slavePosition, - data.sdo_index, data.sdo_entry_subindex); - } catch (MasterDeviceException &e) { - err << "Failed to determine Sdo entry data type. " - << "Please specify --type."; - throw CommandException(err); - } - if (!(dataType = findDataType(entry.data_type))) { - err << "Pdo entry has unknown data type 0x" - << hex << setfill('0') << setw(4) << entry.data_type << "!" - << " Please specify --type."; - throw CommandException(err); - } - } - - if (dataType->byteSize) { - data.data_size = dataType->byteSize; - } else { - data.data_size = DefaultBufferSize; - } - - data.data = new uint8_t[data.data_size + 1]; - - strValue << commandArgs[2]; - strValue >> resetiosflags(ios::basefield); // guess base from prefix - strValue.exceptions(ios::failbit); - - try { - switch (dataType->coeCode) { - case 0x0002: // int8 - { - int16_t val; // uint8_t is interpreted as char - strValue >> val; - if (val > 127 || val < -128) - throw ios::failure("Value out of range"); - *data.data = val; - break; - } - case 0x0003: // int16 - { - int16_t val; - strValue >> val; - *(int16_t *) data.data = cputole16(val); - break; - } - case 0x0004: // int32 - { - int32_t val; - strValue >> val; - *(int32_t *) data.data = cputole32(val); - break; - } - case 0x0005: // uint8 - { - uint16_t val; // uint8_t is interpreted as char - strValue >> val; - if (val > 0xff) - throw ios::failure("Value out of range"); - *data.data = val; - break; - } - case 0x0006: // uint16 - { - uint16_t val; - strValue >> val; - *(uint16_t *) data.data = cputole16(val); - break; - } - case 0x0007: // uint32 - { - uint32_t val; - strValue >> val; - *(uint32_t *) data.data = cputole32(val); - break; - } - case 0x0009: // string - if (strValue.str().size() >= data.data_size) { - err << "String too large"; - throw CommandException(err); - } - data.data_size = strValue.str().size(); - strValue >> (char *) data.data; - break; - - default: - delete [] data.data; - err << "Unknown data type 0x" << hex << dataType->coeCode; - throw CommandException(err); - } - } catch (ios::failure &e) { - delete [] data.data; - err << "Invalid value argument '" << commandArgs[2] - << "' for type '" << dataType->name << "'!"; - throw InvalidUsageException(err); - } - - masterDev.open(MasterDevice::ReadWrite); - - try { - masterDev.sdoDownload(&data); - } catch(MasterDeviceException &e) { - delete [] data.data; - throw e; - } - - delete [] data.data; -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_master.cpp --- a/tool/cmd_master.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -using namespace std; - -#include "globals.h" - -/****************************************************************************/ - -const char *help_master = - "[OPTIONS]\n" - "\n" - "Show master and Ethernet device information.\n" - "\n" - "Command-specific options:\n" - " --master -m Index of the master to use. Default: 0.\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void command_master(void) -{ - ec_ioctl_master_t data; - stringstream err; - unsigned int i; - - masterDev.open(MasterDevice::Read); - masterDev.getMaster(&data); - - cout - << "Master" << masterIndex << endl - << " Phase: "; - - switch (data.phase) { - case 0: cout << "Waiting for device..."; break; - case 1: cout << "Idle"; break; - case 2: cout << "Operation"; break; - default: cout << "???"; - } - - cout << endl - << " Slaves: " << data.slave_count << endl; - - for (i = 0; i < 2; i++) { - cout << " Device" << i << ": "; - if (data.devices[i].address[0] == 0x00 - && data.devices[i].address[1] == 0x00 - && data.devices[i].address[2] == 0x00 - && data.devices[i].address[3] == 0x00 - && data.devices[i].address[4] == 0x00 - && data.devices[i].address[5] == 0x00) { - cout << "None."; - } else { - cout << hex << setfill('0') - << setw(2) << (unsigned int) data.devices[i].address[0] << ":" - << setw(2) << (unsigned int) data.devices[i].address[1] << ":" - << setw(2) << (unsigned int) data.devices[i].address[2] << ":" - << setw(2) << (unsigned int) data.devices[i].address[3] << ":" - << setw(2) << (unsigned int) data.devices[i].address[4] << ":" - << setw(2) << (unsigned int) data.devices[i].address[5] << " (" - << (data.devices[i].attached ? "attached" : "waiting...") - << ")" << endl << dec - << " Tx count: " << data.devices[i].tx_count << endl - << " Rx count: " << data.devices[i].rx_count; - } - cout << endl; - } -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_pdos.cpp --- a/tool/cmd_pdos.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -using namespace std; - -#include "globals.h" - -/****************************************************************************/ - -const char *help_pdos = - "[OPTIONS]\n" - "\n" - "Displays sync managers, assigned Pdos and mapped Pdo entries.\n" - "\n" - "The information is displayed in three layers, which are indented\n" - "accordingly:\n" - "\n" - "1) Sync managers - Contains the sync manager information from the\n" - " SII: Index, physical start address, default size (raw value from\n" - " the SII), control register and enable word. Example:\n" - "\n" - " SM3: PhysAddr 0x1100, DefaultSize 0, ControlRegister 0x20, Enable 1\n" - "\n" - "2) Assigned Pdos - Pdo direction, hexadecimal index and -if available-\n" - " the Pdo name. Example:\n" - "\n" - " TxPdo 0x1a00 \"Channel1\"\n" - "\n" - "3) Mapped Pdo entries - Pdo entry index and subindex (both\n" - " hexadecimal), the length in bit and -if available- the\n" - " description. Example:\n" - "\n" - " Pdo entry 0x3101:01, 8 bit, \"Status\"\n" - "\n" - "Note, that the displayed Pdo assignment and Pdo mapping information\n" - "can either originate from the SII or from the CoE communication area.\n" - "\n" - "Command-specific options:\n" - " --slave -s Positive numerical ring position, or 'all' for\n" - " all slaves (default).\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void listSlavePdos(uint16_t, bool); - -/****************************************************************************/ - -void command_pdos(void) -{ - masterDev.open(MasterDevice::Read); - - if (slavePosition == -1) { - unsigned int numSlaves = masterDev.slaveCount(), i; - - for (i = 0; i < numSlaves; i++) { - listSlavePdos(i, true); - } - } else { - listSlavePdos(slavePosition, false); - } -} - -/****************************************************************************/ - -void listSlavePdos(uint16_t slavePosition, bool withHeader) -{ - ec_ioctl_slave_t slave; - ec_ioctl_slave_sync_t sync; - ec_ioctl_slave_sync_pdo_t pdo; - ec_ioctl_slave_sync_pdo_entry_t entry; - unsigned int i, j, k; - - masterDev.getSlave(&slave, slavePosition); - - if (withHeader) - cout << "=== Slave " << slavePosition << " ===" << endl; - - for (i = 0; i < slave.sync_count; i++) { - masterDev.getSync(&sync, slavePosition, i); - - cout << "SM" << i << ":" - << " PhysAddr 0x" - << hex << setfill('0') - << setw(4) << sync.physical_start_address - << ", DefaultSize " - << dec << setfill(' ') << setw(4) << sync.default_size - << ", ControlRegister 0x" - << hex << setfill('0') << setw(2) - << (unsigned int) sync.control_register - << ", Enable " << dec << (unsigned int) sync.enable - << endl; - - for (j = 0; j < sync.pdo_count; j++) { - masterDev.getPdo(&pdo, slavePosition, i, j); - - cout << " " << (sync.control_register & 0x04 ? "R" : "T") - << "xPdo 0x" - << hex << setfill('0') - << setw(4) << pdo.index - << " \"" << pdo.name << "\"" << endl; - - if (verbosity == Quiet) - continue; - - for (k = 0; k < pdo.entry_count; k++) { - masterDev.getPdoEntry(&entry, slavePosition, i, j, k); - - cout << " Pdo entry 0x" - << hex << setfill('0') - << setw(4) << entry.index - << ":" << setw(2) << (unsigned int) entry.subindex - << ", " << dec << (unsigned int) entry.bit_length - << " bit, \"" << entry.name << "\"" << endl; - } - } - } -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_sdos.cpp --- a/tool/cmd_sdos.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -using namespace std; - -#include "globals.h" -#include "coe_datatypes.h" - -/****************************************************************************/ - -const char *help_sdos = - "[OPTIONS]\n" - "\n" - "Displays the Sdo dictionary with Sdos and Sdo entries.\n" - "\n" - "Sdo dictionary information is displayed in two layers, with are\n" - "indented accordingly:\n" - "\n" - "1) Sdos - Hexadecimal Sdo index and the name. Example:\n" - "\n" - " Sdo 0x1018, \"Identity object\"\n" - "\n" - "2) Sdo entries - Sdo index and Sdo entry subindex (both hexadecimal)\n" - " followed by the data type, the length in bit, and the description.\n" - " Example:\n" - "\n" - " 0x1018:01, uint32, 32 bit, \"Vendor id\"\n" - "\n" - "If the --quiet option is given, only the Sdos are printed.\n" - "\n" - "Command-specific options:\n" - " --slave -s Positive numerical ring position, or 'all' for\n" - " all slaves (default).\n" - " --quiet -q Print only Sdos (without Sdo entries).\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void listSlaveSdos(uint16_t, bool); - -/****************************************************************************/ - -void command_sdos(void) -{ - masterDev.open(MasterDevice::Read); - - if (slavePosition == -1) { - unsigned int numSlaves = masterDev.slaveCount(), i; - - for (i = 0; i < numSlaves; i++) { - listSlaveSdos(i, true); - } - } else { - listSlaveSdos(slavePosition, false); - } -} - -/****************************************************************************/ - -void listSlaveSdos( - uint16_t slavePosition, - bool withHeader - ) -{ - ec_ioctl_slave_t slave; - ec_ioctl_slave_sdo_t sdo; - ec_ioctl_slave_sdo_entry_t entry; - unsigned int i, j; - const CoEDataType *d; - - masterDev.getSlave(&slave, slavePosition); - - if (withHeader) - cout << "=== Slave " << slavePosition << " ===" << endl; - - for (i = 0; i < slave.sdo_count; i++) { - masterDev.getSdo(&sdo, slavePosition, i); - - cout << "Sdo 0x" - << hex << setfill('0') - << setw(4) << sdo.sdo_index - << ", \"" << sdo.name << "\"" << endl; - - if (verbosity == Quiet) - continue; - - for (j = 0; j <= sdo.max_subindex; j++) { - masterDev.getSdoEntry(&entry, slavePosition, -i, j); - - cout << " 0x" << hex << setfill('0') - << setw(4) << sdo.sdo_index << ":" - << setw(2) << (unsigned int) entry.sdo_entry_subindex - << ", "; - - if ((d = findDataType(entry.data_type))) { - cout << d->name; - } else { - cout << "type " << setw(4) << entry.data_type; - } - - cout << ", " << dec << entry.bit_length << " bit, \"" - << entry.description << "\"" << endl; - } - } -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_sii_read.cpp --- a/tool/cmd_sii_read.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -using namespace std; - -#include "globals.h" - -/****************************************************************************/ - -const char *help_sii_read = - "[OPTIONS]\n" - "\n" - "Outputs the SII (EEPROM) contents of a slave.\n" - "\n" - "Without the --verbose option, binary SII contents are output. They can\n" - "be piped to a tool like hexdump, for example:\n" - "\n" - " ethercat sii_read -s2 | hexdump -C\n" - "\n" - "With the --verbose option given, a textual representation of the data\n" - "is output, that is separated by SII category names.\n" - "\n" - "Command-specific options:\n" - " --slave -s Positive numerical ring position (mandatory).\n" - " --verbose -v Output textual data with category names.\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -struct CategoryName { - uint16_t type; - const char *name; -}; - -static const CategoryName categoryNames[] = { - {0x000a, "STRINGS"}, - {0x0014, "DataTypes"}, - {0x001e, "General"}, - {0x0028, "FMMU"}, - {0x0029, "SyncM"}, - {0x0032, "TXPDO"}, - {0x0033, "RXPDO"}, - {0x003c, "DC"}, - {} -}; - -/****************************************************************************/ - -const char *getCategoryName(uint16_t type) -{ - const CategoryName *cn = categoryNames; - - while (cn->type) { - if (cn->type == type) { - return cn->name; - } - cn++; - } - - return "unknown"; -} - -/****************************************************************************/ - -void command_sii_read(void) -{ - ec_ioctl_slave_sii_t data; - ec_ioctl_slave_t slave; - unsigned int i; - const uint16_t *categoryHeader; - uint16_t categoryType, categorySize; - stringstream err; - - if (slavePosition < 0) { - err << "'" << commandName << "' requires a slave! " - << "Please specify --slave."; - throw InvalidUsageException(err); - } - data.slave_position = slavePosition; - - masterDev.open(MasterDevice::Read); - - masterDev.getSlave(&slave, slavePosition); - - if (!slave.sii_nwords) - return; - - data.offset = 0; - data.nwords = slave.sii_nwords; - data.words = new uint16_t[data.nwords]; - - try { - masterDev.readSii(&data); - } catch (MasterDeviceException &e) { - delete [] data.words; - throw e; - } - - if (verbosity == Verbose) { - cout << "SII Area:" << hex << setfill('0'); - for (i = 0; i < min(data.nwords, 0x0040U) * 2; i++) { - if (i % BreakAfterBytes) { - cout << " "; - } else { - cout << endl << " "; - } - cout << setw(2) << (unsigned int) *((uint8_t *) data.words + i); - } - cout << endl; - - if (data.nwords > 0x0040U) { - // cycle through categories - categoryHeader = data.words + 0x0040U; - categoryType = le16tocpu(*categoryHeader); - while (categoryType != 0xffff) { - cout << "SII Category 0x" << hex - << setw(4) << categoryType - << " (" << getCategoryName(categoryType) << ")" << flush; - - if (categoryHeader + 1 > data.words + data.nwords) { - err << "SII data seem to be corrupted!"; - throw CommandException(err); - } - categorySize = le16tocpu(*(categoryHeader + 1)); - cout << ", " << dec << categorySize << " words" << flush; - - if (categoryHeader + 2 + categorySize - > data.words + data.nwords) { - err << "SII data seem to be corrupted!"; - throw CommandException(err); - } - - cout << hex; - for (i = 0; i < categorySize * 2U; i++) { - if (i % BreakAfterBytes) { - cout << " "; - } else { - cout << endl << " "; - } - cout << setw(2) << (unsigned int) - *((uint8_t *) (categoryHeader + 2) + i); - } - cout << endl; - - if (categoryHeader + 2 + categorySize + 1 - > data.words + data.nwords) { - err << "SII data seem to be corrupted!"; - throw CommandException(err); - } - categoryHeader += 2 + categorySize; - categoryType = le16tocpu(*categoryHeader); - } - } - } else { - for (i = 0; i < data.nwords; i++) { - uint16_t *w = data.words + i; - cout << *(uint8_t *) w << *((uint8_t *) w + 1); - } - } - - delete [] data.words; -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_sii_write.cpp --- a/tool/cmd_sii_write.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -#include -using namespace std; - -#include "globals.h" -#include "sii_crc.h" - -/****************************************************************************/ - -const char *help_sii_write = - "[OPTIONS] \n" - "\n" - "Writes SII contents from a local file to a slave.\n" - "\n" - "The file contents are checked for validity and integrity. These checks\n" - "can be overridden with the --force option.\n" - "\n" - "Arguments:\n" - " FILENAME must be a path to a file that contains a positive number\n" - " of words.\n" - "\n" - "Command-specific options:\n" - " --slave -s Positive numerical ring position (mandatory).\n" - " --force Override validity checks.\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void command_sii_write(void) -{ - stringstream err; - ec_ioctl_slave_sii_t data; - ifstream file; - unsigned int byte_size; - const uint16_t *categoryHeader; - uint16_t categoryType, categorySize; - uint8_t crc; - - if (slavePosition < 0) { - err << "'" << commandName << "' requires a slave! " - << "Please specify --slave."; - throw InvalidUsageException(err); - } - data.slave_position = slavePosition; - - if (commandArgs.size() != 1) { - err << "'" << commandName << "' takes exactly one argument!"; - throw InvalidUsageException(err); - } - - file.open(commandArgs[0].c_str(), ifstream::in | ifstream::binary); - if (file.fail()) { - err << "Failed to open '" << commandArgs[0] << "'!"; - throw CommandException(err); - } - - // get length of file - file.seekg(0, ios::end); - byte_size = file.tellg(); - file.seekg(0, ios::beg); - - if (!byte_size || byte_size % 2) { - err << "Invalid file size! Must be non-zero and even."; - throw CommandException(err); - } - - data.nwords = byte_size / 2; - if (data.nwords < 0x0041 && !force) { - err << "SII data too short (" << data.nwords << " words)! Mimimum is" - " 40 fixed words + 1 delimiter. Use --force to write anyway."; - throw CommandException(err); - } - - // allocate buffer and read file into buffer - data.words = new uint16_t[data.nwords]; - file.read((char *) data.words, byte_size); - file.close(); - - if (!force) { - // calculate checksum over words 0 to 6 - crc = calcSiiCrc((const uint8_t *) data.words, 14); - if (crc != ((const uint8_t *) data.words)[14]) { - err << "CRC incorrect. Must be 0x" - << hex << setfill('0') << setw(2) << (unsigned int) crc - << ". Use --force to write anyway."; - throw CommandException(err); - } - - // cycle through categories to detect corruption - categoryHeader = data.words + 0x0040U; - categoryType = le16tocpu(*categoryHeader); - while (categoryType != 0xffff) { - if (categoryHeader + 1 > data.words + data.nwords) { - err << "SII data seem to be corrupted! " - << "Use --force to write anyway."; - throw CommandException(err); - } - categorySize = le16tocpu(*(categoryHeader + 1)); - if (categoryHeader + 2 + categorySize + 1 - > data.words + data.nwords) { - err << "SII data seem to be corrupted! " - "Use --force to write anyway."; - throw CommandException(err); - } - categoryHeader += 2 + categorySize; - categoryType = le16tocpu(*categoryHeader); - } - } - - // send data to master - masterDev.open(MasterDevice::ReadWrite); - data.offset = 0; - masterDev.writeSii(&data); -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_slaves.cpp --- a/tool/cmd_slaves.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,283 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -#include -using namespace std; - -#include "globals.h" - -/****************************************************************************/ - -const char *help_slaves = - "[OPTIONS]\n" - "\n" - "Display slaves on the bus.\n" - "\n" - "If the --verbose option is not given, the slaves are displayed\n" - "one-per-line. Example:\n" - "\n" - "1 5555:0 PREOP + EL3162 2C. Ana. Input 0-10V\n" - "| | | | | |\n" - "| | | | | \\- Name from SII if avaliable, otherwise\n" - "| | | | | hexadecimal vendor ID and product code\n" - "| | | | | separated by a colon.\n" - "| | | | \\- Error flag. '+' means no error, 'E' means,\n" - "| | | | that scanning or configuration failed.\n" - "| | | \\- Current slave state.\n" - "| | \\- Relative position (decimal) after the last slave with an\n" - "| | alias address set.\n" - "| \\- Alias address of the slave (if set to non-zero), or the alias\n" - "| of the last slave with an alias set, or zero if there is none.\n" - "\\- Ring position (use this with any --slave option).\n" - "\n" - "If the --verbose option is given, a detailed (multi-line) description\n" - "is output for each slave.\n" - "\n" - "Command-specific options:\n" - " --slave -s Positive numerical ring position, or 'all' for\n" - " all slaves (default).\n" - " --verbose -v Show detailed slave information.\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void listSlaves(int); -void showSlave(uint16_t); - -/****************************************************************************/ - -void command_slaves() -{ - masterDev.open(MasterDevice::Read); - - if (verbosity == Verbose) { - if (slavePosition == -1) { - unsigned int numSlaves = masterDev.slaveCount(), i; - - for (i = 0; i < numSlaves; i++) { - showSlave(i); - } - } else { - showSlave(slavePosition); - } - } else { - listSlaves(slavePosition); - } -} - -/****************************************************************************/ - -string slaveState(uint8_t state) -{ - switch (state) { - case 1: return "INIT"; - case 2: return "PREOP"; - case 4: return "SAFEOP"; - case 8: return "OP"; - default: return "???"; - } -} - -/****************************************************************************/ - -struct SlaveInfo { - string pos; - string alias; - string relPos; - string state; - string flag; - string name; -}; - -void listSlaves(int slavePosition) -{ - unsigned int numSlaves, i; - ec_ioctl_slave_t slave; - uint16_t lastAlias, aliasIndex; - SlaveInfo slaveInfo; - typedef list SlaveInfoList; - SlaveInfoList slaveInfoList; - SlaveInfoList::const_iterator iter; - stringstream str; - unsigned int maxPosWidth = 0, maxAliasWidth = 0, - maxRelPosWidth = 0, maxStateWidth = 0; - - numSlaves = masterDev.slaveCount(); - - lastAlias = 0; - aliasIndex = 0; - for (i = 0; i < numSlaves; i++) { - masterDev.getSlave(&slave, i); - - if (slave.alias) { - lastAlias = slave.alias; - aliasIndex = 0; - } - - if (slavePosition == -1 || i == (unsigned int) slavePosition) { - str << dec << i; - slaveInfo.pos = str.str(); - str.clear(); - str.str(""); - - str << lastAlias; - slaveInfo.alias = str.str(); - str.str(""); - - str << aliasIndex; - slaveInfo.relPos = str.str(); - str.str(""); - - slaveInfo.state = slaveState(slave.state); - slaveInfo.flag = (slave.error_flag ? 'E' : '+'); - - if (strlen(slave.name)) { - slaveInfo.name = slave.name; - } else { - str << "0x" << hex << setfill('0') - << setw(8) << slave.vendor_id << ":0x" - << setw(8) << slave.product_code; - slaveInfo.name = str.str(); - str.str(""); - } - - - slaveInfoList.push_back(slaveInfo); - - if (slaveInfo.pos.length() > maxPosWidth) - maxPosWidth = slaveInfo.pos.length(); - if (slaveInfo.alias.length() > maxAliasWidth) - maxAliasWidth = slaveInfo.alias.length(); - if (slaveInfo.relPos.length() > maxRelPosWidth) - maxRelPosWidth = slaveInfo.relPos.length(); - if (slaveInfo.state.length() > maxStateWidth) - maxStateWidth = slaveInfo.state.length(); - } - - aliasIndex++; - } - - for (iter = slaveInfoList.begin(); iter != slaveInfoList.end(); iter++) { - cout << setfill(' ') << right - << setw(maxPosWidth) << iter->pos << " " - << setw(maxAliasWidth) << iter->alias - << ":" << left - << setw(maxRelPosWidth) << iter->relPos << " " - << setw(maxStateWidth) << iter->state << " " - << iter->flag << " " - << iter->name << endl; - } -} - -/****************************************************************************/ - -void showSlave(uint16_t slavePosition) -{ - ec_ioctl_slave_t slave; - list protoList; - list::const_iterator protoIter; - - masterDev.getSlave(&slave, slavePosition); - - cout << "=== Slave " << dec << slavePosition << " ===" << endl; - - if (slave.alias) - cout << "Alias: " << slave.alias << endl; - - cout - << "State: " << slaveState(slave.state) << endl - << "Flag: " << (slave.error_flag ? 'E' : '+') << endl - << "Identity:" << endl - << " Vendor Id: 0x" - << hex << setfill('0') - << setw(8) << slave.vendor_id << endl - << " Product code: 0x" - << setw(8) << slave.product_code << endl - << " Revision number: 0x" - << setw(8) << slave.revision_number << endl - << " Serial number: 0x" - << setw(8) << slave.serial_number << endl; - - if (slave.mailbox_protocols) { - cout << "Mailboxes:" << endl - << " RX: 0x" - << hex << setw(4) << slave.rx_mailbox_offset << "/" - << dec << slave.rx_mailbox_size - << ", TX: 0x" - << hex << setw(4) << slave.tx_mailbox_offset << "/" - << dec << slave.tx_mailbox_size << endl - << " Supported protocols: "; - - if (slave.mailbox_protocols & EC_MBOX_AOE) { - protoList.push_back("AoE"); - } - if (slave.mailbox_protocols & EC_MBOX_EOE) { - protoList.push_back("EoE"); - } - if (slave.mailbox_protocols & EC_MBOX_COE) { - protoList.push_back("CoE"); - } - if (slave.mailbox_protocols & EC_MBOX_FOE) { - protoList.push_back("FoE"); - } - if (slave.mailbox_protocols & EC_MBOX_SOE) { - protoList.push_back("SoE"); - } - if (slave.mailbox_protocols & EC_MBOX_VOE) { - protoList.push_back("VoE"); - } - - for (protoIter = protoList.begin(); protoIter != protoList.end(); - protoIter++) { - if (protoIter != protoList.begin()) - cout << ", "; - cout << *protoIter; - } - cout << endl; - } - - if (slave.has_general_category) { - cout << "General:" << endl - << " Group: " << slave.group << endl - << " Image name: " << slave.image << endl - << " Order number: " << slave.order << endl - << " Device name: " << slave.name << endl; - - if (slave.mailbox_protocols & EC_MBOX_COE) { - cout << " CoE details:" << endl - << " Enable Sdo: " - << (slave.coe_details.enable_sdo ? "yes" : "no") << endl - << " Enable Sdo Info: " - << (slave.coe_details.enable_sdo_info ? "yes" : "no") << endl - << " Enable Pdo Assign: " - << (slave.coe_details.enable_pdo_assign - ? "yes" : "no") << endl - << " Enable Pdo Configuration: " - << (slave.coe_details.enable_pdo_configuration - ? "yes" : "no") << endl - << " Enable Upload at startup: " - << (slave.coe_details.enable_upload_at_startup - ? "yes" : "no") << endl - << " Enable Sdo complete access: " - << (slave.coe_details.enable_sdo_complete_access - ? "yes" : "no") << endl; - } - - cout << " Flags:" << endl - << " Enable SafeOp: " - << (slave.general_flags.enable_safeop ? "yes" : "no") << endl - << " Enable notLRW: " - << (slave.general_flags.enable_not_lrw ? "yes" : "no") << endl - << " Current consumption: " - << dec << slave.current_on_ebus << " mA" << endl; - } -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_states.cpp --- a/tool/cmd_states.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -using namespace std; - -#include "globals.h" - -/****************************************************************************/ - -const char *help_states = - "[OPTIONS] \n" - "\n" - "Request an application-layer state change for the specified slaves.\n" - "\n" - "Arguments:\n" - " STATE can be 'INIT', 'PREOP', 'SAFEOP', or 'OP'\n" - "\n" - "Command-specific options:\n" - " --slave -s Positive numerical ring position, or 'all' for\n" - " all slaves (default).\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void command_states(void) -{ - stringstream err; - string stateStr; - uint8_t state; - - if (commandArgs.size() != 1) { - err << "'" << commandName << "' takes exactly one argument!"; - throw InvalidUsageException(err); - } - - stateStr = commandArgs[0]; - transform(stateStr.begin(), stateStr.end(), - stateStr.begin(), (int (*) (int)) std::toupper); - - if (stateStr == "INIT") { - state = 0x01; - } else if (stateStr == "PREOP") { - state = 0x02; - } else if (stateStr == "SAFEOP") { - state = 0x04; - } else if (stateStr == "OP") { - state = 0x08; - } else { - err << "Invalid state '" << commandArgs[0] << "'!"; - throw InvalidUsageException(err); - } - - masterDev.open(MasterDevice::ReadWrite); - - if (slavePosition == -1) { - unsigned int i, numSlaves = masterDev.slaveCount(); - for (i = 0; i < numSlaves; i++) - masterDev.requestState(i, state); - } else { - masterDev.requestState(slavePosition, state); - } -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_upload.cpp --- a/tool/cmd_upload.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,172 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -using namespace std; - -#include "globals.h" -#include "coe_datatypes.h" - -/****************************************************************************/ - -const char *help_upload = - "[OPTIONS] \n" - "\n" - "Upload an Sdo entry from a slave.\n" - "\n" - "The data type of the Sdo entry is taken from the Sdo dictionary by\n" - "default. It can be overridden with the --type option. If the slave\n" - "does not support the Sdo information service or the Sdo is not in the\n" - "dictionary, the --type option is mandatory.\n" - "\n" - "These are the valid Sdo entry data types:\n" - " int8, int16, int32, uint8, uint16, uint32, string.\n" - "\n" - "Arguments:\n" - " INDEX is the Sdo index and must be an unsigned 16 bit number.\n" - " SUBINDEX is the Sdo entry subindex and must be an unsigned 8 bit\n" - " number.\n" - "\n" - "Command-specific options:\n" - " --slave -s Positive numerical ring position (mandatory).\n" - " --type -t Forced Sdo entry data type (see above).\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void command_upload(void) -{ - stringstream err, strIndex, strSubIndex; - int sval; - ec_ioctl_slave_sdo_upload_t data; - unsigned int uval; - const CoEDataType *dataType = NULL; - - if (slavePosition < 0) { - err << "'" << commandName << "' requires a slave! " - << "Please specify --slave."; - throw InvalidUsageException(err); - } - data.slave_position = slavePosition; - - if (commandArgs.size() != 2) { - err << "'" << commandName << "' takes two arguments!"; - throw InvalidUsageException(err); - } - - strIndex << commandArgs[0]; - strIndex - >> resetiosflags(ios::basefield) // guess base from prefix - >> data.sdo_index; - if (strIndex.fail()) { - err << "Invalid Sdo index '" << commandArgs[0] << "'!"; - throw InvalidUsageException(err); - } - - strSubIndex << commandArgs[1]; - strSubIndex - >> resetiosflags(ios::basefield) // guess base from prefix - >> uval; - if (strSubIndex.fail() || uval > 0xff) { - err << "Invalid Sdo subindex '" << commandArgs[1] << "'!"; - throw InvalidUsageException(err); - } - data.sdo_entry_subindex = uval; - - if (dataTypeStr != "") { // data type specified - if (!(dataType = findDataType(dataTypeStr))) { - err << "Invalid data type '" << dataTypeStr << "'!"; - throw InvalidUsageException(err); - } - } else { // no data type specified: fetch from dictionary - ec_ioctl_slave_sdo_entry_t entry; - - masterDev.open(MasterDevice::Read); - - try { - masterDev.getSdoEntry(&entry, slavePosition, - data.sdo_index, data.sdo_entry_subindex); - } catch (MasterDeviceException &e) { - err << "Failed to determine Sdo entry data type. " - << "Please specify --type."; - throw CommandException(err); - } - if (!(dataType = findDataType(entry.data_type))) { - err << "Pdo entry has unknown data type 0x" - << hex << setfill('0') << setw(4) << entry.data_type << "!" - << " Please specify --type."; - throw CommandException(err); - } - } - - if (dataType->byteSize) { - data.target_size = dataType->byteSize; - } else { - data.target_size = DefaultBufferSize; - } - - data.target = new uint8_t[data.target_size + 1]; - - masterDev.open(MasterDevice::Read); - - try { - masterDev.sdoUpload(&data); - } catch (MasterDeviceException &e) { - delete [] data.target; - throw e; - } - - masterDev.close(); - - if (dataType->byteSize && data.data_size != dataType->byteSize) { - err << "Data type mismatch. Expected " << dataType->name - << " with " << dataType->byteSize << " byte, but got " - << data.data_size << " byte."; - throw CommandException(err); - } - - cout << setfill('0'); - switch (dataType->coeCode) { - case 0x0002: // int8 - sval = *(int8_t *) data.target; - cout << sval << " 0x" << hex << setw(2) << sval << endl; - break; - case 0x0003: // int16 - sval = le16tocpu(*(int16_t *) data.target); - cout << sval << " 0x" << hex << setw(4) << sval << endl; - break; - case 0x0004: // int32 - sval = le32tocpu(*(int32_t *) data.target); - cout << sval << " 0x" << hex << setw(8) << sval << endl; - break; - case 0x0005: // uint8 - uval = (unsigned int) *(uint8_t *) data.target; - cout << uval << " 0x" << hex << setw(2) << uval << endl; - break; - case 0x0006: // uint16 - uval = le16tocpu(*(uint16_t *) data.target); - cout << uval << " 0x" << hex << setw(4) << uval << endl; - break; - case 0x0007: // uint32 - uval = le32tocpu(*(uint32_t *) data.target); - cout << uval << " 0x" << hex << setw(8) << uval << endl; - break; - case 0x0009: // string - cout << string((const char *) data.target, data.data_size) - << endl; - break; - default: - printRawData(data.target, data.data_size); - break; - } - - delete [] data.target; -} - -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/cmd_xml.cpp --- a/tool/cmd_xml.cpp Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include -#include -using namespace std; - -#include "globals.h" - -/****************************************************************************/ - -const char *help_xml = - "[OPTIONS]\n" - "\n" - "Generate slave description XMLs from the master's slave information.\n" - "\n" - "Note that the Pdo information can either originate from the SII or\n" - "from the CoE communication area. For some slaves, this is dependant on\n" - "the last slave configuration.\n" - "\n" - "Command-specific options:\n" - " --slave -s Positive numerical ring position, or 'all' for\n" - " all slaves (default).\n" - "\n" - "Numerical values can be specified either with decimal (no prefix),\n" - "octal (prefix '0') or hexadecimal (prefix '0x') base.\n"; - -/****************************************************************************/ - -void generateSlaveXml(uint16_t); - -/****************************************************************************/ - -void command_xml(void) -{ - masterDev.open(MasterDevice::Read); - - if (slavePosition == -1) { - unsigned int numSlaves = masterDev.slaveCount(), i; - - for (i = 0; i < numSlaves; i++) { - generateSlaveXml(i); - } - } else { - generateSlaveXml(slavePosition); - } -} - -/****************************************************************************/ - -void generateSlaveXml(uint16_t slavePosition) -{ - ec_ioctl_slave_t slave; - ec_ioctl_slave_sync_t sync; - ec_ioctl_slave_sync_pdo_t pdo; - string pdoType; - ec_ioctl_slave_sync_pdo_entry_t entry; - unsigned int i, j, k; - - masterDev.getSlave(&slave, slavePosition); - - cout - << "" << endl - << " " << endl - << " " << endl - << " " << endl - << " " << slave.vendor_id << "" << endl - << " " << endl - << " " << endl - << " " << endl - << " " << endl - << " " << slave.order << "" << endl; - - if (strlen(slave.name)) { - cout - << " " << endl; - } - - for (i = 0; i < slave.sync_count; i++) { - masterDev.getSync(&sync, slavePosition, i); - - cout - << " " << endl; - } - - for (i = 0; i < slave.sync_count; i++) { - masterDev.getSync(&sync, slavePosition, i); - - for (j = 0; j < sync.pdo_count; j++) { - masterDev.getPdo(&pdo, slavePosition, i, j); - pdoType = (sync.control_register & 0x04 ? "R" : "T"); - pdoType += "xPdo"; - - cout - << " <" << pdoType - << " Sm=\"" << i << "\" Fixed=\"1\" Mandatory=\"1\">" << endl - << " #x" - << hex << setfill('0') << setw(4) << pdo.index - << "" << endl - << " " << pdo.name << "" << endl; - - for (k = 0; k < pdo.entry_count; k++) { - masterDev.getPdoEntry(&entry, slavePosition, i, j, k); - - cout - << " " << endl - << " #x" - << hex << setfill('0') << setw(4) << entry.index - << "" << endl; - if (entry.index) - cout - << " " - << dec << (unsigned int) entry.subindex - << "" << endl; - - cout - << " " - << dec << (unsigned int) entry.bit_length - << "" << endl; - - if (entry.index) { - cout - << " " << entry.name - << "" << endl - << " "; - - if (entry.bit_length == 1) { - cout << "BOOL"; - } else if (!(entry.bit_length % 8)) { - if (entry.bit_length <= 64) - cout << "UINT" << (unsigned int) entry.bit_length; - else - cout << "STRING(" - << (unsigned int) (entry.bit_length / 8) - << ")"; - } else { - cerr << "Invalid bit length " - << (unsigned int) entry.bit_length << endl; - } - - cout << "" << endl; - } - - cout << " " << endl; - } - - cout - << " " << endl; - } - } - - cout - << " " << endl - << " " << endl - << " " << endl - << "" << endl; -} -/*****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/globals.h --- a/tool/globals.h Thu Jul 24 08:15:44 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/***************************************************************************** - * - * $Id$ - * - ****************************************************************************/ - -#include - -#include -#include -#include -using namespace std; - -#include "MasterDevice.h" - -/*****************************************************************************/ - -enum Verbosity { - Quiet, - Normal, - Verbose -}; - -extern string commandName; -extern unsigned int masterIndex; -extern int slavePosition; -extern int domainIndex; -extern vector commandArgs; -extern Verbosity verbosity; -extern string dataTypeStr; -extern bool force; - -extern MasterDevice masterDev; - -/****************************************************************************/ - -class InvalidUsageException: - public runtime_error -{ - public: - /** Constructor with std::string parameter. */ - InvalidUsageException( - const stringstream &s /**< Message. */ - ): runtime_error(s.str()) {} -}; - -/****************************************************************************/ - -class CommandException: - public runtime_error -{ - public: - /** Constructor with std::string parameter. */ - CommandException( - const stringstream &s /**< Message. */ - ): runtime_error(s.str()) {} -}; - -/*****************************************************************************/ - -#define swap16(x) \ - ((uint16_t)( \ - (((uint16_t)(x) & 0x00ffU) << 8) | \ - (((uint16_t)(x) & 0xff00U) >> 8) )) -#define swap32(x) \ - ((uint32_t)( \ - (((uint32_t)(x) & 0x000000ffUL) << 24) | \ - (((uint32_t)(x) & 0x0000ff00UL) << 8) | \ - (((uint32_t)(x) & 0x00ff0000UL) >> 8) | \ - (((uint32_t)(x) & 0xff000000UL) >> 24) )) - -#if __BYTE_ORDER == __LITTLE_ENDIAN - -#define le16tocpu(x) x -#define le32tocpu(x) x - -#define cputole16(x) x -#define cputole32(x) x - -#elif __BYTE_ORDER == __BIG_ENDIAN - -#define le16tocpu(x) swap16(x) -#define le32tocpu(x) swap32(x) - -#define cputole16(x) swap16(x) -#define cputole32(x) swap32(x) - -#endif - -/****************************************************************************/ - -enum {BreakAfterBytes = 16}; -enum {DefaultBufferSize = 1024}; - -void printRawData(const uint8_t *, unsigned int); - -/****************************************************************************/ diff -r 7ffbca63fc72 -r 59be91dfcbe1 tool/main.cpp --- a/tool/main.cpp Thu Jul 24 08:15:44 2008 +0000 +++ b/tool/main.cpp Thu Jul 24 13:27:06 2008 +0000 @@ -9,96 +9,54 @@ #include #include -#include -#include -#include using namespace std; -#include "globals.h" +#include "CommandAlias.h" +#include "CommandConfig.h" +#include "CommandData.h" +#include "CommandDebug.h" +#include "CommandDomains.h" +#include "CommandMaster.h" +#include "CommandPdos.h" +#include "CommandSdos.h" +#include "CommandDownload.h" +#include "CommandUpload.h" +#include "CommandSlaves.h" +#include "CommandSiiRead.h" +#include "CommandSiiWrite.h" +#include "CommandStates.h" +#include "CommandXml.h" /*****************************************************************************/ +typedef list CommandList; +CommandList commandList; + +MasterDevice masterDev; + string binaryBaseName; +string commandName; +Command::StringVector commandArgs; + +// option variables unsigned int masterIndex = 0; int slavePosition = -1; int domainIndex = -1; -string commandName; -vector commandArgs; -Verbosity verbosity = Normal; string dataTypeStr; +Command::Verbosity verbosity = Command::Normal; bool force = false; - bool helpRequested = false; -MasterDevice masterDev; - -/*****************************************************************************/ - -struct Command { - const char *name; - void (*func)(void); - const char *helpString; - const char *briefDesc; - - int execute(void) const; - string getHelpString(void) const; -}; - -/*****************************************************************************/ - -#define DEFINE_EXTERN_COMMAND(name) \ - void command_##name(void); \ - extern const char *help_##name - -#define INIT_COMMAND(name, desc) \ - {#name, command_##name, help_##name, desc} - -DEFINE_EXTERN_COMMAND(alias); -DEFINE_EXTERN_COMMAND(config); -DEFINE_EXTERN_COMMAND(data); -DEFINE_EXTERN_COMMAND(debug); -DEFINE_EXTERN_COMMAND(domains); -DEFINE_EXTERN_COMMAND(master); -DEFINE_EXTERN_COMMAND(pdos); -DEFINE_EXTERN_COMMAND(sdos); -DEFINE_EXTERN_COMMAND(download); -DEFINE_EXTERN_COMMAND(upload); -DEFINE_EXTERN_COMMAND(slaves); -DEFINE_EXTERN_COMMAND(sii_read); -DEFINE_EXTERN_COMMAND(sii_write); -DEFINE_EXTERN_COMMAND(states); -DEFINE_EXTERN_COMMAND(xml); - -static const Command commands[] = { - INIT_COMMAND(alias, "Write alias addresses."), - INIT_COMMAND(config, "Show bus configuration."), - INIT_COMMAND(data, "Output binary domain process data."), - INIT_COMMAND(debug, "Set the master's debug level."), - INIT_COMMAND(domains, "Show domain information."), - INIT_COMMAND(master, "Show master information."), - INIT_COMMAND(pdos, "List Pdo assignment/mapping."), - INIT_COMMAND(sdos, "List Sdo dictionaries."), - INIT_COMMAND(download, "Write an Sdo entry."), - INIT_COMMAND(upload, "Read an Sdo entry."), - INIT_COMMAND(slaves, "Show slaves."), - INIT_COMMAND(sii_read, "Output a slave's SII contents."), - INIT_COMMAND(sii_write, "Write slave's SII contents."), - INIT_COMMAND(states, "Request slave states."), - INIT_COMMAND(xml, "Generate slave information XML."), -}; - -static const Command *cmdEnd = commands + sizeof(commands) / sizeof(Command); - /*****************************************************************************/ void printUsage() { - const Command *cmd; + CommandList::const_iterator ci; size_t maxWidth = 0; - for (cmd = commands; cmd < cmdEnd; cmd++) { - if (strlen(cmd->name) > maxWidth) { - maxWidth = strlen(cmd->name); + for (ci = commandList.begin(); ci != commandList.end(); ci++) { + if ((*ci)->getName().length() > maxWidth) { + maxWidth = (*ci)->getName().length(); } } @@ -108,9 +66,9 @@ << "Commands (can be abbreviated):" << endl; cerr << left; - for (cmd = commands; cmd < cmdEnd; cmd++) { - cerr << " " << setw(maxWidth) << cmd->name - << " " << cmd->briefDesc << endl; + for (ci = commandList.begin(); ci != commandList.end(); ci++) { + cerr << " " << setw(maxWidth) << (*ci)->getName() + << " " << (*ci)->getBriefDescription() << endl; } cerr @@ -207,11 +165,11 @@ break; case 'q': - verbosity = Quiet; + verbosity = Command::Quiet; break; case 'v': - verbosity = Verbose; + verbosity = Command::Verbose; break; case 'h': @@ -245,76 +203,23 @@ /****************************************************************************/ -int Command::execute() const +list getMatchingCommands(const string &cmdStr) { - try { - func(); - } catch (InvalidUsageException &e) { - cerr << e.what() << endl << endl; - cerr << getHelpString(); - return 1; - } catch (CommandException &e) { - cerr << e.what() << endl; - return 1; - } catch (MasterDeviceException &e) { - cerr << e.what() << endl; - return 1; - } - - return 0; -} - -/****************************************************************************/ - -string Command::getHelpString() const -{ - stringstream help; - help << binaryBaseName << " " << commandName << " " << helpString; - return help.str(); -} - -/****************************************************************************/ - -bool substrMatch(const string &abb, const string &full) -{ - return full.substr(0, abb.length()) == abb; -} - -/****************************************************************************/ - -bool abbrevMatch(const string &abb, const string &full) -{ - unsigned int abbIndex; - size_t fullPos = 0; - - for (abbIndex = 0; abbIndex < abb.length(); abbIndex++) { - fullPos = full.find(abb[abbIndex], fullPos); - if (fullPos == string::npos) - return false; - } - - return true; -} - -/****************************************************************************/ - -list getMatchingCommands(const string &cmdStr) -{ - const Command *cmd; - list res; + CommandList::iterator ci; + list res; // find matching commands from beginning of the string - for (cmd = commands; cmd < cmdEnd; cmd++) { - if (substrMatch(cmdStr, cmd->name)) { - res.push_back(cmd); + for (ci = commandList.begin(); ci != commandList.end(); ci++) { + if ((*ci)->matchesSubstr(cmdStr)) { + res.push_back(*ci); } } if (!res.size()) { // nothing found // find /any/ matching commands - for (cmd = commands; cmd < cmdEnd; cmd++) { - if (abbrevMatch(cmdStr, cmd->name)) { - res.push_back(cmd); + for (ci = commandList.begin(); ci != commandList.end(); ci++) { + if ((*ci)->matchesAbbrev(cmdStr)) { + res.push_back(*ci); } } } @@ -327,29 +232,59 @@ int main(int argc, char **argv) { int retval = 0; - list commands; - list::const_iterator ci; - const Command *cmd; + list matchingCommands; + list::const_iterator ci; + Command *cmd; binaryBaseName = basename(argv[0]); + + commandList.push_back(new CommandAlias()); + commandList.push_back(new CommandConfig()); + commandList.push_back(new CommandData()); + commandList.push_back(new CommandDebug()); + commandList.push_back(new CommandDomains()); + commandList.push_back(new CommandDownload()); + commandList.push_back(new CommandMaster()); + commandList.push_back(new CommandPdos()); + commandList.push_back(new CommandSdos()); + commandList.push_back(new CommandSiiRead()); + commandList.push_back(new CommandSiiWrite()); + commandList.push_back(new CommandSlaves()); + commandList.push_back(new CommandStates()); + commandList.push_back(new CommandUpload()); + commandList.push_back(new CommandXml()); + getOptions(argc, argv); - commands = getMatchingCommands(commandName); - - if (commands.size()) { - if (commands.size() == 1) { - cmd = commands.front(); - commandName = cmd->name; + matchingCommands = getMatchingCommands(commandName); + masterDev.setIndex(masterIndex); + + if (matchingCommands.size()) { + if (matchingCommands.size() == 1) { + cmd = matchingCommands.front(); if (!helpRequested) { - masterDev.setIndex(masterIndex); - retval = cmd->execute(); + try { + cmd->execute(masterDev, commandArgs); + } catch (InvalidUsageException &e) { + cerr << e.what() << endl << endl; + cerr << cmd->helpString(); + retval = 1; + } catch (CommandException &e) { + cerr << e.what() << endl; + retval = 1; + } catch (MasterDeviceException &e) { + cerr << e.what() << endl; + retval = 1; + } } else { - cout << cmd->getHelpString(); + cout << cmd->helpString(); } } else { cerr << "Ambiguous command abbreviation! Matching:" << endl; - for (ci = commands.begin(); ci != commands.end(); ci++) { - cerr << (*ci)->name << endl; + for (ci = matchingCommands.begin(); + ci != matchingCommands.end(); + ci++) { + cerr << (*ci)->getName() << endl; } cerr << endl; printUsage(); @@ -365,19 +300,3 @@ } /****************************************************************************/ - -void printRawData( - const uint8_t *data, - unsigned int size - ) -{ - cout << hex << setfill('0'); - while (size--) { - cout << "0x" << setw(2) << (unsigned int) *data++; - if (size) - cout << " "; - } - cout << endl; -} - -/****************************************************************************/