Redesigned command interface.
--- /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();
+}
+
+/****************************************************************************/
--- /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 <stdexcept>
+#include <vector>
+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<string> 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
--- /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 <iostream>
+#include <iomanip>
+#include <sstream>
+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] <ALIAS>" << 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 <index> 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;
+}
+
+/*****************************************************************************/
--- /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
--- /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 <list>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+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<Info> 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;
+ }
+}
+
+/*****************************************************************************/
--- /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 <list>
+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<ec_ioctl_config_t> ConfigList;
+
+ void showDetailedConfigs(MasterDevice &, const ConfigList &);
+ void listConfigs(const ConfigList &);
+};
+
+/****************************************************************************/
+
+#endif
--- /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 <iostream>
+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 <index> 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;
+}
+
+/****************************************************************************/
--- /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
--- /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 <sstream>
+#include <iomanip>
+using namespace std;
+
+#include "CommandDebug.h"
+
+/*****************************************************************************/
+
+CommandDebug::CommandDebug():
+ Command("debug", "Set the master's debug level.")
+{
+}
+
+/*****************************************************************************/
+
+string CommandDebug::helpString() const
+{
+ stringstream str;
+
+ str << getName() << " <LEVEL>" << 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);
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+#include <iomanip>
+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 <index> 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;
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+#include <iomanip>
+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] <INDEX> <SUBINDEX> <VALUE>" << 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 <index> Positive numerical ring position" << endl
+ << " (mandatory)." << endl
+ << " --type -t <type> 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;
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+#include <iomanip>
+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> 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;
+ }
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+#include <iomanip>
+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 <index> 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;
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+#include <iomanip>
+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 <index> 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;
+ }
+ }
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+#include <iomanip>
+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 <index> 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";
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+#include <iomanip>
+#include <fstream>
+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] <FILENAME>" << 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 <index> 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);
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+#include <iomanip>
+#include <list>
+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 <index> 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<Info> 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<string> protoList;
+ list<string>::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 "???";
+ }
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+using namespace std;
+
+#include "CommandStates.h"
+
+/*****************************************************************************/
+
+CommandStates::CommandStates():
+ Command("states", "Request application-layer states.")
+{
+}
+
+/*****************************************************************************/
+
+string CommandStates::helpString() const
+{
+ stringstream str;
+
+ str << getName() << " [OPTIONS] <STATE>" << endl
+ << endl
+ << getBriefDescription() << endl
+ << endl
+ << "Arguments:" << endl
+ << " STATE can be 'INIT', 'PREOP', 'SAFEOP', or 'OP'" << endl
+ << endl
+ << "Command-specific options:" << endl
+ << " --slave -s <index> 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);
+ }
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+#include <iomanip>
+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] <INDEX> <SUBINDEX>" << 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 <index> Positive numerical ring position" << endl
+ << " (mandatory)." << endl
+ << " --type -t <type> 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;
+}
+
+/*****************************************************************************/
--- /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
--- /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 <iostream>
+#include <iomanip>
+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 <index> 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
+ << "<?xml version=\"1.0\" ?>" << endl
+ << " <EtherCATInfo>" << endl
+ << " <!-- Slave " << slave.position << " -->" << endl
+ << " <Vendor>" << endl
+ << " <Id>" << slave.vendor_id << "</Id>" << endl
+ << " </Vendor>" << endl
+ << " <Descriptions>" << endl
+ << " <Devices>" << endl
+ << " <Device>" << endl
+ << " <Type ProductCode=\"#x"
+ << hex << setfill('0') << setw(8) << slave.product_code
+ << "\" RevisionNo=\"#x"
+ << hex << setfill('0') << setw(8) << slave.revision_number
+ << "\">" << slave.order << "</Type>" << endl;
+
+ if (strlen(slave.name)) {
+ cout
+ << " <Name><![CDATA["
+ << slave.name
+ << "]]></Name>" << endl;
+ }
+
+ for (i = 0; i < slave.sync_count; i++) {
+ m.getSync(&sync, slavePosition, i);
+
+ cout
+ << " <Sm Enable=\"" << dec << (unsigned int) sync.enable
+ << "\" StartAddress=\"" << sync.physical_start_address
+ << "\" ControlByte=\"" << (unsigned int) sync.control_register
+ << "\" DefaultSize=\"" << sync.default_size
+ << "\" />" << 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
+ << " <Index>#x"
+ << hex << setfill('0') << setw(4) << pdo.index
+ << "</Index>" << endl
+ << " <Name>" << pdo.name << "</Name>" << endl;
+
+ for (k = 0; k < pdo.entry_count; k++) {
+ m.getPdoEntry(&entry, slavePosition, i, j, k);
+
+ cout
+ << " <Entry>" << endl
+ << " <Index>#x"
+ << hex << setfill('0') << setw(4) << entry.index
+ << "</Index>" << endl;
+ if (entry.index)
+ cout
+ << " <SubIndex>"
+ << dec << (unsigned int) entry.subindex
+ << "</SubIndex>" << endl;
+
+ cout
+ << " <BitLen>"
+ << dec << (unsigned int) entry.bit_length
+ << "</BitLen>" << endl;
+
+ if (entry.index) {
+ cout
+ << " <Name>" << entry.name
+ << "</Name>" << endl
+ << " <DataType>";
+
+ 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 << "</DataType>" << endl;
+ }
+
+ cout << " </Entry>" << endl;
+ }
+
+ cout
+ << " </" << pdoType << ">" << endl;
+ }
+ }
+
+ cout
+ << " </Device>" << endl
+ << " </Devices>" << endl
+ << " </Descriptions>" << endl
+ << "</EtherCATInfo>" << endl;
+}
+/*****************************************************************************/
--- /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
--- 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
--- /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 <sys/types.h>
+
+/*****************************************************************************/
+
+#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
+
+/****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-#include <sstream>
-using namespace std;
-
-#include "globals.h"
-#include "sii_crc.h"
-
-/*****************************************************************************/
-
-const char *help_alias =
- "[OPTIONS] <ALIAS>\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 <index> 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;
-}
-
-/*****************************************************************************/
--- 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 <list>
-#include <iostream>
-#include <iomanip>
-#include <sstream>
-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<ec_ioctl_config_t> 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<ConfigInfo> 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;
- }
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-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 <index> 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;
-}
-
-/****************************************************************************/
--- 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 <sstream>
-#include <iomanip>
-using namespace std;
-
-#include "globals.h"
-
-/*****************************************************************************/
-
-const char *help_debug =
- "<LEVEL>\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);
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-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 <index> 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;
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-using namespace std;
-
-#include "globals.h"
-#include "coe_datatypes.h"
-
-/****************************************************************************/
-
-const char *help_download =
- "[OPTIONS] <INDEX> <SUBINDEX> <VALUE>\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 <index> Positive numerical ring position (mandatory).\n"
- " --type -t <type> 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;
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-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> 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;
- }
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-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 <index> 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;
- }
- }
- }
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-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 <index> 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;
- }
- }
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-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 <index> 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;
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-#include <fstream>
-using namespace std;
-
-#include "globals.h"
-#include "sii_crc.h"
-
-/****************************************************************************/
-
-const char *help_sii_write =
- "[OPTIONS] <FILENAME>\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 <index> 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);
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-#include <list>
-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 <index> 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<SlaveInfo> 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<string> protoList;
- list<string>::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;
- }
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-using namespace std;
-
-#include "globals.h"
-
-/****************************************************************************/
-
-const char *help_states =
- "[OPTIONS] <STATE>\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 <index> 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);
- }
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-using namespace std;
-
-#include "globals.h"
-#include "coe_datatypes.h"
-
-/****************************************************************************/
-
-const char *help_upload =
- "[OPTIONS] <INDEX> <SUBINDEX>\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 <index> Positive numerical ring position (mandatory).\n"
- " --type -t <type> 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;
-}
-
-/*****************************************************************************/
--- 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 <iostream>
-#include <iomanip>
-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 <index> 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
- << "<?xml version=\"1.0\" ?>" << endl
- << " <EtherCATInfo>" << endl
- << " <!-- Slave " << slave.position << " -->" << endl
- << " <Vendor>" << endl
- << " <Id>" << slave.vendor_id << "</Id>" << endl
- << " </Vendor>" << endl
- << " <Descriptions>" << endl
- << " <Devices>" << endl
- << " <Device>" << endl
- << " <Type ProductCode=\"#x"
- << hex << setfill('0') << setw(8) << slave.product_code
- << "\" RevisionNo=\"#x"
- << hex << setfill('0') << setw(8) << slave.revision_number
- << "\">" << slave.order << "</Type>" << endl;
-
- if (strlen(slave.name)) {
- cout
- << " <Name><![CDATA["
- << slave.name
- << "]]></Name>" << endl;
- }
-
- for (i = 0; i < slave.sync_count; i++) {
- masterDev.getSync(&sync, slavePosition, i);
-
- cout
- << " <Sm Enable=\"" << dec << (unsigned int) sync.enable
- << "\" StartAddress=\"" << sync.physical_start_address
- << "\" ControlByte=\"" << (unsigned int) sync.control_register
- << "\" DefaultSize=\"" << sync.default_size
- << "\" />" << 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
- << " <Index>#x"
- << hex << setfill('0') << setw(4) << pdo.index
- << "</Index>" << endl
- << " <Name>" << pdo.name << "</Name>" << endl;
-
- for (k = 0; k < pdo.entry_count; k++) {
- masterDev.getPdoEntry(&entry, slavePosition, i, j, k);
-
- cout
- << " <Entry>" << endl
- << " <Index>#x"
- << hex << setfill('0') << setw(4) << entry.index
- << "</Index>" << endl;
- if (entry.index)
- cout
- << " <SubIndex>"
- << dec << (unsigned int) entry.subindex
- << "</SubIndex>" << endl;
-
- cout
- << " <BitLen>"
- << dec << (unsigned int) entry.bit_length
- << "</BitLen>" << endl;
-
- if (entry.index) {
- cout
- << " <Name>" << entry.name
- << "</Name>" << endl
- << " <DataType>";
-
- 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 << "</DataType>" << endl;
- }
-
- cout << " </Entry>" << endl;
- }
-
- cout
- << " </" << pdoType << ">" << endl;
- }
- }
-
- cout
- << " </Device>" << endl
- << " </Devices>" << endl
- << " </Descriptions>" << endl
- << "</EtherCATInfo>" << endl;
-}
-/*****************************************************************************/
--- 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 <sys/types.h>
-
-#include <string>
-#include <sstream>
-#include <vector>
-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<string> 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);
-
-/****************************************************************************/
--- 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 <iostream>
#include <iomanip>
-#include <string>
-#include <vector>
-#include <list>
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<Command *> 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<string> 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<Command *> 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<const Command *> getMatchingCommands(const string &cmdStr)
-{
- const Command *cmd;
- list<const Command *> res;
+ CommandList::iterator ci;
+ list<Command *> 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<const Command *> commands;
- list<const Command *>::const_iterator ci;
- const Command *cmd;
+ list<Command *> matchingCommands;
+ list<Command *>::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;
-}
-
-/****************************************************************************/