Skip to content
Snippets Groups Projects
Commit 67180543 authored by Florian Pose's avatar Florian Pose
Browse files

Redesigned command interface.

parent 8e241946
No related branches found
No related tags found
No related merge requests found
Showing
with 1020 additions and 264 deletions
/*****************************************************************************
*
* $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();
}
/****************************************************************************/
......@@ -4,10 +4,10 @@
*
****************************************************************************/
#include <sys/types.h>
#ifndef __COMMAND_H__
#define __COMMAND_H__
#include <string>
#include <sstream>
#include <stdexcept>
#include <vector>
using namespace std;
......@@ -15,30 +15,21 @@ using namespace std;
/*****************************************************************************/
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. */
friend class Command;
protected:
/** Constructor with stringstream parameter. */
InvalidUsageException(
const stringstream &s /**< Message. */
): runtime_error(s.str()) {}
......@@ -49,49 +40,78 @@ class InvalidUsageException:
class CommandException:
public runtime_error
{
public:
/** Constructor with std::string parameter. */
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();
#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) ))
enum Verbosity {
Quiet,
Normal,
Verbose
};
void setVerbosity(Verbosity);
#if __BYTE_ORDER == __LITTLE_ENDIAN
const string &getName() const;
const string &getBriefDescription() const;
Verbosity getVerbosity() const;
#define le16tocpu(x) x
#define le32tocpu(x) x
bool matchesSubstr(const string &) const;
bool matchesAbbrev(const string &) const;
#define cputole16(x) x
#define cputole32(x) x
virtual string helpString() const = 0;
#elif __BYTE_ORDER == __BIG_ENDIAN
typedef vector<string> StringVector;
virtual void execute(MasterDevice &, const StringVector &) = 0;
#define le16tocpu(x) swap16(x)
#define le32tocpu(x) swap32(x)
protected:
void throwInvalidUsageException(const stringstream &);
void throwCommandException(const stringstream &);
#define cputole16(x) swap16(x)
#define cputole32(x) swap32(x)
enum {BreakAfterBytes = 16};
static string numericInfo();
#endif
private:
string name;
string briefDesc;
Verbosity verbosity;
Command();
};
/****************************************************************************/
inline const string &Command::getName() const
{
return name;
}
/****************************************************************************/
enum {BreakAfterBytes = 16};
enum {DefaultBufferSize = 1024};
inline const string &Command::getBriefDescription() const
{
return briefDesc;
}
/****************************************************************************/
void printRawData(const uint8_t *, unsigned int);
inline Command::Verbosity Command::getVerbosity() const
{
return verbosity;
}
/****************************************************************************/
#endif
......@@ -9,56 +9,67 @@
#include <sstream>
using namespace std;
#include "globals.h"
#include "CommandAlias.h"
#include "sii_crc.h"
#include "byteorder.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";
CommandAlias::CommandAlias():
Command("alias", "Write alias addresses.")
{
}
/*****************************************************************************/
void writeSlaveAlias(uint16_t, uint16_t);
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 command_alias(void)
void CommandAlias::execute(MasterDevice &m, const StringVector &args)
{
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);
if (args.size() != 1) {
err << "'" << getName() << "' takes exactly one argument!";
throwInvalidUsageException(err);
}
strAlias << commandArgs[0];
strAlias << args[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);
err << "Invalid alias '" << args[0] << "'!";
throwInvalidUsageException(err);
}
alias = number;
......@@ -66,18 +77,18 @@ void command_alias(void)
if (!force) {
err << "This will write the alias addresses of all slaves to "
<< alias << "! Please specify --force to proceed.";
throw CommandException(err);
throwCommandException(err);
}
masterDev.open(MasterDevice::ReadWrite);
numSlaves = masterDev.slaveCount();
m.open(MasterDevice::ReadWrite);
numSlaves = m.slaveCount();
for (i = 0; i < numSlaves; i++) {
writeSlaveAlias(i, alias);
writeSlaveAlias(m, i, alias);
}
} else {
masterDev.open(MasterDevice::ReadWrite);
writeSlaveAlias(slavePosition, alias);
m.open(MasterDevice::ReadWrite);
writeSlaveAlias(m, slavePosition, alias);
}
}
......@@ -85,7 +96,8 @@ void command_alias(void)
/** Writes the Secondary slave address (alias) to the slave's SII.
*/
void writeSlaveAlias(
void CommandAlias::writeSlaveAlias(
MasterDevice &m,
uint16_t slavePosition,
uint16_t alias
)
......@@ -95,12 +107,12 @@ void writeSlaveAlias(
stringstream err;
uint8_t crc;
masterDev.getSlave(&slave, slavePosition);
m.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);
throwCommandException(err);
}
// read first 8 SII words
......@@ -110,11 +122,11 @@ void writeSlaveAlias(
data.words = new uint16_t[data.nwords];
try {
masterDev.readSii(&data);
m.readSii(&data);
} catch (MasterDeviceException &e) {
delete [] data.words;
err << "Failed to read SII: " << e.what();
throw CommandException(err);
throwCommandException(err);
}
// write new alias address in word 4
......@@ -128,11 +140,11 @@ void writeSlaveAlias(
// write first 8 words with new alias and checksum
try {
masterDev.writeSii(&data);
m.writeSii(&data);
} catch (MasterDeviceException &e) {
delete [] data.words;
err << "Failed to read SII: " << e.what();
throw CommandException(err);
throwCommandException(err);
}
delete [] data.words;
......
/*****************************************************************************
*
* $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
......@@ -10,47 +10,50 @@
#include <sstream>
using namespace std;
#include "globals.h"
#include "CommandConfig.h"
#include "byteorder.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";
CommandConfig::CommandConfig():
Command("config", "Show slave configurations.")
{
}
/*****************************************************************************/
struct ConfigInfo {
string alias;
string pos;
string ident;
string att;
string op;
};
string CommandConfig::helpString() const
{
stringstream str;
typedef list<ec_ioctl_config_t> ConfigList;
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();
}
void showDetailedConfigs(const ConfigList &configList);
void listConfigs(const ConfigList &configList);
/*****************************************************************************/
/*****************************************************************************/
......@@ -64,25 +67,25 @@ bool operator<(const ec_ioctl_config_t &a, const ec_ioctl_config_t &b)
/** Lists the bus configuration.
*/
void command_config(void)
void CommandConfig::execute(MasterDevice &m, const StringVector &args)
{
ec_ioctl_master_t master;
unsigned int i;
ec_ioctl_config_t config;
ConfigList configList;
masterDev.open(MasterDevice::Read);
masterDev.getMaster(&master);
m.open(MasterDevice::Read);
m.getMaster(&master);
for (i = 0; i < master.config_count; i++) {
masterDev.getConfig(&config, i);
m.getConfig(&config, i);
configList.push_back(config);
}
configList.sort();
if (verbosity == Verbose) {
showDetailedConfigs(configList);
if (getVerbosity() == Verbose) {
showDetailedConfigs(m, configList);
} else {
listConfigs(configList);
}
......@@ -92,7 +95,10 @@ void command_config(void)
/** Lists the complete bus configuration.
*/
void showDetailedConfigs(const ConfigList &configList)
void CommandConfig::showDetailedConfigs(
MasterDevice &m,
const ConfigList &configList
)
{
ConfigList::const_iterator configIter;
unsigned int j, k, l;
......@@ -121,14 +127,14 @@ void showDetailedConfigs(const ConfigList &configList)
<< (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);
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++) {
masterDev.getConfigPdoEntry(&entry,
m.getConfigPdoEntry(&entry,
configIter->config_index, j, k, l);
cout << " Pdo entry 0x" << hex
......@@ -144,7 +150,7 @@ void showDetailedConfigs(const ConfigList &configList)
cout << "Sdo configuration:" << endl;
if (configIter->sdo_count) {
for (j = 0; j < configIter->sdo_count; j++) {
masterDev.getConfigSdo(&sdo, configIter->config_index, j);
m.getConfigSdo(&sdo, configIter->config_index, j);
cout << " 0x"
<< hex << setfill('0')
......@@ -183,14 +189,14 @@ void showDetailedConfigs(const ConfigList &configList)
/** Lists the bus configuration.
*/
void listConfigs(const ConfigList &configList)
void CommandConfig::listConfigs(const ConfigList &configList)
{
ConfigList::const_iterator configIter;
stringstream str;
ConfigInfo info;
typedef list<ConfigInfo> ConfigInfoList;
ConfigInfoList list;
ConfigInfoList::const_iterator iter;
Info info;
typedef list<Info> InfoList;
InfoList list;
InfoList::const_iterator iter;
unsigned int maxAliasWidth = 0, maxPosWidth = 0,
maxAttWidth = 0, maxOpWidth = 0;
......
/*****************************************************************************
*
* $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
......@@ -7,57 +7,66 @@
#include <iostream>
using namespace std;
#include "globals.h"
#include "CommandData.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";
CommandData::CommandData():
Command("data", "Output binary domain process data.")
{
}
/****************************************************************************/
/*****************************************************************************/
void outputDomainData(unsigned int);
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 command_data()
void CommandData::execute(MasterDevice &m, const StringVector &args)
{
masterDev.open(MasterDevice::Read);
m.open(MasterDevice::Read);
if (domainIndex == -1) {
unsigned int i;
ec_ioctl_master_t master;
masterDev.getMaster(&master);
m.getMaster(&master);
for (i = 0; i < master.domain_count; i++) {
outputDomainData(i);
outputDomainData(m, i);
}
} else {
outputDomainData(domainIndex);
outputDomainData(m, domainIndex);
}
}
/****************************************************************************/
void outputDomainData(unsigned int 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;
masterDev.getDomain(&domain, domainIndex);
m.getDomain(&domain, domainIndex);
if (!domain.data_size)
return;
......@@ -65,7 +74,7 @@ void outputDomainData(unsigned int domainIndex)
processData = new unsigned char[domain.data_size];
try {
masterDev.getData(&data, domainIndex, domain.data_size, processData);
m.getData(&data, domainIndex, domain.data_size, processData);
} catch (MasterDeviceException &e) {
delete [] processData;
throw e;
......
/*****************************************************************************
*
* $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
......@@ -8,51 +8,63 @@
#include <iomanip>
using namespace std;
#include "globals.h"
#include "CommandDebug.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";
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 command_debug(void)
void CommandDebug::execute(MasterDevice &m, const StringVector &args)
{
stringstream str;
int debugLevel;
if (commandArgs.size() != 1) {
if (args.size() != 1) {
stringstream err;
err << "'" << commandName << "' takes exactly one argument!";
throw InvalidUsageException(err);
err << "'" << getName() << "' takes exactly one argument!";
throwInvalidUsageException(err);
}
str << commandArgs[0];
str << args[0];
str >> resetiosflags(ios::basefield) // guess base from prefix
>> debugLevel;
if (str.fail()) {
stringstream err;
err << "Invalid debug level '" << commandArgs[0] << "'!";
throw InvalidUsageException(err);
err << "Invalid debug level '" << args[0] << "'!";
throwInvalidUsageException(err);
}
masterDev.open(MasterDevice::ReadWrite);
masterDev.setDebug(debugLevel);
m.open(MasterDevice::ReadWrite);
m.setDebug(debugLevel);
}
/*****************************************************************************/
/*****************************************************************************
*
* $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
......@@ -8,71 +8,83 @@
#include <iomanip>
using namespace std;
#include "globals.h"
#include "CommandDomains.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";
CommandDomains::CommandDomains():
Command("domains", "Show configured domains.")
{
}
/****************************************************************************/
/*****************************************************************************/
void showDomain(unsigned int);
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 command_domains(void)
void CommandDomains::execute(MasterDevice &m, const StringVector &args)
{
masterDev.open(MasterDevice::Read);
m.open(MasterDevice::Read);
if (domainIndex == -1) {
unsigned int i;
ec_ioctl_master_t master;
masterDev.getMaster(&master);
m.getMaster(&master);
for (i = 0; i < master.domain_count; i++) {
showDomain(i);
showDomain(m, i);
}
} else {
showDomain(domainIndex);
showDomain(m, domainIndex);
}
}
/****************************************************************************/
void showDomain(unsigned int domainIndex)
void CommandDomains::showDomain(MasterDevice &m, unsigned int domainIndex)
{
ec_ioctl_domain_t domain;
unsigned char *processData;
......@@ -81,7 +93,7 @@ void showDomain(unsigned int domainIndex)
ec_ioctl_domain_fmmu_t fmmu;
unsigned int dataOffset;
masterDev.getDomain(&domain, domainIndex);
m.getDomain(&domain, domainIndex);
cout << "Domain" << dec << domainIndex << ":"
<< " LogBaseAddr 0x"
......@@ -93,20 +105,20 @@ void showDomain(unsigned int domainIndex)
<< domain.working_counter << "/"
<< domain.expected_working_counter << endl;
if (!domain.data_size || verbosity != Verbose)
if (!domain.data_size || getVerbosity() != Verbose)
return;
processData = new unsigned char[domain.data_size];
try {
masterDev.getData(&data, domainIndex, domain.data_size, processData);
m.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);
m.getFmmu(&fmmu, domainIndex, i);
cout << " SlaveConfig "
<< dec << fmmu.slave_config_alias
......@@ -124,7 +136,7 @@ void showDomain(unsigned int domainIndex)
stringstream err;
delete [] processData;
err << "Fmmu information corrupted!";
throw CommandException(err);
throwCommandException(err);
}
cout << " " << hex << setfill('0');
......
/*****************************************************************************
*
* $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
......@@ -8,42 +8,58 @@
#include <iomanip>
using namespace std;
#include "globals.h"
#include "CommandDownload.h"
#include "coe_datatypes.h"
#include "byteorder.h"
/****************************************************************************/
/*****************************************************************************/
CommandDownload::CommandDownload():
Command("download", "Write an Sdo entry to a slave.")
{
}
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";
/*****************************************************************************/
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 command_download(void)
void CommandDownload::execute(MasterDevice &m, const StringVector &args)
{
stringstream strIndex, strSubIndex, strValue, err;
ec_ioctl_slave_sdo_download_t data;
......@@ -51,59 +67,59 @@ void command_download(void)
const CoEDataType *dataType = NULL;
if (slavePosition < 0) {
err << "'" << commandName << "' requires a slave! "
err << "'" << getName() << "' requires a slave! "
<< "Please specify --slave.";
throw InvalidUsageException(err);
throwInvalidUsageException(err);
}
data.slave_position = slavePosition;
if (commandArgs.size() != 3) {
err << "'" << commandName << "' takes 3 arguments!";
throw InvalidUsageException(err);
if (args.size() != 3) {
err << "'" << getName() << "' takes 3 arguments!";
throwInvalidUsageException(err);
}
strIndex << commandArgs[0];
strIndex << args[0];
strIndex
>> resetiosflags(ios::basefield) // guess base from prefix
>> data.sdo_index;
if (strIndex.fail()) {
err << "Invalid Sdo index '" << commandArgs[0] << "'!";
throw InvalidUsageException(err);
err << "Invalid Sdo index '" << args[0] << "'!";
throwInvalidUsageException(err);
}
strSubIndex << commandArgs[1];
strSubIndex << args[1];
strSubIndex
>> resetiosflags(ios::basefield) // guess base from prefix
>> number;
if (strSubIndex.fail() || number > 0xff) {
err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
throw InvalidUsageException(err);
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 << "'!";
throw InvalidUsageException(err);
throwInvalidUsageException(err);
}
} else { // no data type specified: fetch from dictionary
ec_ioctl_slave_sdo_entry_t entry;
masterDev.open(MasterDevice::ReadWrite);
m.open(MasterDevice::ReadWrite);
try {
masterDev.getSdoEntry(&entry, slavePosition,
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.";
throw CommandException(err);
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.";
throw CommandException(err);
throwCommandException(err);
}
}
......@@ -115,7 +131,7 @@ void command_download(void)
data.data = new uint8_t[data.data_size + 1];
strValue << commandArgs[2];
strValue << args[2];
strValue >> resetiosflags(ios::basefield); // guess base from prefix
strValue.exceptions(ios::failbit);
......@@ -170,7 +186,7 @@ void command_download(void)
case 0x0009: // string
if (strValue.str().size() >= data.data_size) {
err << "String too large";
throw CommandException(err);
throwCommandException(err);
}
data.data_size = strValue.str().size();
strValue >> (char *) data.data;
......@@ -179,19 +195,19 @@ void command_download(void)
default:
delete [] data.data;
err << "Unknown data type 0x" << hex << dataType->coeCode;
throw CommandException(err);
throwCommandException(err);
}
} catch (ios::failure &e) {
delete [] data.data;
err << "Invalid value argument '" << commandArgs[2]
err << "Invalid value argument '" << args[2]
<< "' for type '" << dataType->name << "'!";
throw InvalidUsageException(err);
throwInvalidUsageException(err);
}
masterDev.open(MasterDevice::ReadWrite);
m.open(MasterDevice::ReadWrite);
try {
masterDev.sdoDownload(&data);
m.sdoDownload(&data);
} catch(MasterDeviceException &e) {
delete [] data.data;
throw e;
......
/*****************************************************************************
*
* $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
......@@ -8,31 +8,43 @@
#include <iomanip>
using namespace std;
#include "globals.h"
#include "CommandMaster.h"
/*****************************************************************************/
CommandMaster::CommandMaster():
Command("alias", "Show master and Ethernet device information.")
{
}
/****************************************************************************/
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";
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 command_master(void)
void CommandMaster::execute(MasterDevice &m, const StringVector &args)
{
ec_ioctl_master_t data;
stringstream err;
unsigned int i;
masterDev.open(MasterDevice::Read);
masterDev.getMaster(&data);
m.open(MasterDevice::Read);
m.getMaster(&data);
cout
<< "Master" << masterIndex << endl
......
/*****************************************************************************
*
* $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
......@@ -8,69 +8,84 @@
#include <iomanip>
using namespace std;
#include "globals.h"
#include "CommandPdos.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";
CommandPdos::CommandPdos():
Command("pdos", "List Sync managers, Pdo assignment and mapping.")
{
}
/****************************************************************************/
void listSlavePdos(uint16_t, bool);
/*****************************************************************************/
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 command_pdos(void)
void CommandPdos::execute(MasterDevice &m, const StringVector &args)
{
masterDev.open(MasterDevice::Read);
m.open(MasterDevice::Read);
if (slavePosition == -1) {
unsigned int numSlaves = masterDev.slaveCount(), i;
unsigned int numSlaves = m.slaveCount(), i;
for (i = 0; i < numSlaves; i++) {
listSlavePdos(i, true);
listSlavePdos(m, i, true);
}
} else {
listSlavePdos(slavePosition, false);
listSlavePdos(m, slavePosition, false);
}
}
/****************************************************************************/
void listSlavePdos(uint16_t slavePosition, bool withHeader)
void CommandPdos::listSlavePdos(
MasterDevice &m,
uint16_t slavePosition,
bool withHeader
)
{
ec_ioctl_slave_t slave;
ec_ioctl_slave_sync_t sync;
......@@ -78,13 +93,13 @@ void listSlavePdos(uint16_t slavePosition, bool withHeader)
ec_ioctl_slave_sync_pdo_entry_t entry;
unsigned int i, j, k;
masterDev.getSlave(&slave, slavePosition);
m.getSlave(&slave, slavePosition);
if (withHeader)
cout << "=== Slave " << slavePosition << " ===" << endl;
for (i = 0; i < slave.sync_count; i++) {
masterDev.getSync(&sync, slavePosition, i);
m.getSync(&sync, slavePosition, i);
cout << "SM" << i << ":"
<< " PhysAddr 0x"
......@@ -99,7 +114,7 @@ void listSlavePdos(uint16_t slavePosition, bool withHeader)
<< endl;
for (j = 0; j < sync.pdo_count; j++) {
masterDev.getPdo(&pdo, slavePosition, i, j);
m.getPdo(&pdo, slavePosition, i, j);
cout << " " << (sync.control_register & 0x04 ? "R" : "T")
<< "xPdo 0x"
......@@ -107,11 +122,11 @@ void listSlavePdos(uint16_t slavePosition, bool withHeader)
<< setw(4) << pdo.index
<< " \"" << pdo.name << "\"" << endl;
if (verbosity == Quiet)
if (getVerbosity() == Quiet)
continue;
for (k = 0; k < pdo.entry_count; k++) {
masterDev.getPdoEntry(&entry, slavePosition, i, j, k);
m.getPdoEntry(&entry, slavePosition, i, j, k);
cout << " Pdo entry 0x"
<< hex << setfill('0')
......
/*****************************************************************************
*
* $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
......@@ -8,63 +8,73 @@
#include <iomanip>
using namespace std;
#include "globals.h"
#include "CommandSdos.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";
CommandSdos::CommandSdos():
Command("sdos", "List Sdo dictionaries.")
{
}
/****************************************************************************/
/*****************************************************************************/
void listSlaveSdos(uint16_t, bool);
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 command_sdos(void)
void CommandSdos::execute(MasterDevice &m, const StringVector &args)
{
masterDev.open(MasterDevice::Read);
m.open(MasterDevice::Read);
if (slavePosition == -1) {
unsigned int numSlaves = masterDev.slaveCount(), i;
unsigned int numSlaves = m.slaveCount(), i;
for (i = 0; i < numSlaves; i++) {
listSlaveSdos(i, true);
listSlaveSdos(m, i, true);
}
} else {
listSlaveSdos(slavePosition, false);
listSlaveSdos(m, slavePosition, false);
}
}
/****************************************************************************/
void listSlaveSdos(
void CommandSdos::listSlaveSdos(
MasterDevice &m,
uint16_t slavePosition,
bool withHeader
)
......@@ -75,24 +85,24 @@ void listSlaveSdos(
unsigned int i, j;
const CoEDataType *d;
masterDev.getSlave(&slave, slavePosition);
m.getSlave(&slave, slavePosition);
if (withHeader)
cout << "=== Slave " << slavePosition << " ===" << endl;
for (i = 0; i < slave.sdo_count; i++) {
masterDev.getSdo(&sdo, slavePosition, i);
m.getSdo(&sdo, slavePosition, i);
cout << "Sdo 0x"
<< hex << setfill('0')
<< setw(4) << sdo.sdo_index
<< ", \"" << sdo.name << "\"" << endl;
if (verbosity == Quiet)
if (getVerbosity() == Quiet)
continue;
for (j = 0; j <= sdo.max_subindex; j++) {
masterDev.getSdoEntry(&entry, slavePosition, -i, j);
m.getSdoEntry(&entry, slavePosition, -i, j);
cout << " 0x" << hex << setfill('0')
<< setw(4) << sdo.sdo_index << ":"
......
/*****************************************************************************
*
* $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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment