diff --git a/tool/Makefile.am b/tool/Makefile.am index b235d2fca3805ca4064e9871f6f71c9c9461da33..41a68e35ea9a0aee22acf0ec4fcb8fe12d493ae3 100644 --- a/tool/Makefile.am +++ b/tool/Makefile.am @@ -34,7 +34,9 @@ bin_PROGRAMS = ethercat ethercat_SOURCES = \ - Master.cpp Master.h \ + MasterDevice.cpp MasterDevice.h \ + cmd_alias.cpp \ + cmd_config.cpp \ main.cpp ethercat_CXXFLAGS = -I../master -Wall diff --git a/tool/Master.cpp b/tool/MasterDevice.cpp similarity index 87% rename from tool/Master.cpp rename to tool/MasterDevice.cpp index d0172f6612defb3a70d3c9055d6dd9526a71486a..df1ffdf107d028168eb97ff2dbaca01897753e32 100644 --- a/tool/Master.cpp +++ b/tool/MasterDevice.cpp @@ -4,51 +4,23 @@ * ****************************************************************************/ -#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <sys/ioctl.h> -#include <iostream> -#include <iomanip> #include <sstream> +using namespace std; + +#if 0 +#include <iostream> #include <fstream> #include <cctype> // toupper() #include <list> -using namespace std; - -#include "Master.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 +#include "MasterDevice.h" + /****************************************************************************/ struct CoEDataType { @@ -97,86 +69,27 @@ const CoEDataType *findDataType(uint16_t code) /****************************************************************************/ -Master::Master() +MasterDevice::MasterDevice() { index = 0; - verbosity = Normal; fd = -1; } /****************************************************************************/ -Master::~Master() +MasterDevice::~MasterDevice() { close(); } /****************************************************************************/ -void Master::setIndex(unsigned int i) +void MasterDevice::setIndex(unsigned int i) { index = i; } -/****************************************************************************/ - -void Master::setVerbosity(Verbosity v) -{ - verbosity = v; -} - -/*****************************************************************************/ - -/** - * Writes the Secondary slave address (alias) to the slave's SII. - */ -void Master::writeAlias( - int slavePosition, - bool force, - const vector<string> &commandArgs - ) -{ - uint16_t alias; - stringstream err, strAlias; - int number; - - if (commandArgs.size() != 1) { - stringstream err; - err << "'alias' takes exactly one argument!"; - throw MasterException(err.str()); - } - - 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 MasterException(err.str()); - } - alias = number; - - if (slavePosition == -1) { - unsigned int numSlaves, i; - - if (!force) { - err << "This will write the alias addresses of all slaves to " - << alias << "! Please specify --force to proceed."; - throw MasterException(err.str()); - } - - open(ReadWrite); - numSlaves = slaveCount(); - - for (i = 0; i < numSlaves; i++) { - writeSlaveAlias(i, alias); - } - } else { - open(ReadWrite); - writeSlaveAlias(slavePosition, alias); - } -} - +#if 0 /*****************************************************************************/ bool operator<(const ec_ioctl_config_t &a, const ec_ioctl_config_t &b) @@ -241,7 +154,7 @@ void Master::setDebug(const vector<string> &commandArgs) if (commandArgs.size() != 1) { stringstream err; err << "'debug' takes exactly one argument!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } str << commandArgs[0]; @@ -251,7 +164,7 @@ void Master::setDebug(const vector<string> &commandArgs) if (str.fail()) { stringstream err; err << "Invalid debug level '" << commandArgs[0] << "'!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } open(ReadWrite); @@ -259,7 +172,7 @@ void Master::setDebug(const vector<string> &commandArgs) if (ioctl(fd, EC_IOCTL_MASTER_DEBUG, debugLevel) < 0) { stringstream err; err << "Failed to set debug level: " << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } @@ -304,7 +217,7 @@ void Master::showMaster() case 2: cout << "Operation"; break; default: err << "Invalid master phase " << data.phase; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } cout << endl @@ -385,13 +298,13 @@ void Master::sdoDownload( if (slavePosition < 0) { err << "'sdo_download' requires a slave! Please specify --slave."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } data.slave_position = slavePosition; if (commandArgs.size() != 3) { err << "'sdo_download' takes 3 arguments!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } strIndex << commandArgs[0]; @@ -400,7 +313,7 @@ void Master::sdoDownload( >> data.sdo_index; if (strIndex.fail()) { err << "Invalid Sdo index '" << commandArgs[0] << "'!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } strSubIndex << commandArgs[1]; @@ -409,14 +322,14 @@ void Master::sdoDownload( >> number; if (strSubIndex.fail() || number > 0xff) { err << "Invalid Sdo subindex '" << commandArgs[1] << "'!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } data.sdo_entry_subindex = number; if (dataTypeStr != "") { // data type specified if (!(dataType = findDataType(dataTypeStr))) { err << "Invalid data type '" << dataTypeStr << "'!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } else { // no data type specified: fetch from dictionary ec_ioctl_slave_sdo_entry_t entry; @@ -426,16 +339,16 @@ void Master::sdoDownload( try { getSdoEntry(&entry, slavePosition, data.sdo_index, data.sdo_entry_subindex); - } catch (MasterException &e) { + } catch (MasterDeviceException &e) { err << "Failed to determine Sdo entry data type. " << "Please specify --type."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } 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 MasterException(err.str()); + throw MasterDeviceException(err.str()); } } @@ -502,7 +415,7 @@ void Master::sdoDownload( case 0x0009: // string if (strValue.str().size() >= data.data_size) { err << "String too large"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } data.data_size = strValue.str().size(); strValue >> (char *) data.data; @@ -511,13 +424,13 @@ void Master::sdoDownload( default: delete [] data.data; err << "Unknown data type 0x" << hex << dataType->coeCode; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } catch (ios::failure &e) { delete [] data.data; err << "Invalid value argument '" << commandArgs[2] << "' for type '" << dataType->name << "'!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } open(ReadWrite); @@ -532,7 +445,7 @@ void Master::sdoDownload( err << strerror(errno); } delete [] data.data; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } delete [] data.data; @@ -555,14 +468,14 @@ void Master::sdoUpload( if (slavePosition < 0) { stringstream err; err << "'sdo_upload' requires a slave! Please specify --slave."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } data.slave_position = slavePosition; if (commandArgs.size() != 2) { stringstream err; err << "'sdo_upload' takes two arguments!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } strIndex << commandArgs[0]; @@ -572,7 +485,7 @@ void Master::sdoUpload( if (strIndex.fail()) { stringstream err; err << "Invalid Sdo index '" << commandArgs[0] << "'!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } strSubIndex << commandArgs[1]; @@ -582,7 +495,7 @@ void Master::sdoUpload( if (strSubIndex.fail() || uval > 0xff) { stringstream err; err << "Invalid Sdo subindex '" << commandArgs[1] << "'!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } data.sdo_entry_subindex = uval; @@ -590,7 +503,7 @@ void Master::sdoUpload( if (!(dataType = findDataType(dataTypeStr))) { stringstream err; err << "Invalid data type '" << dataTypeStr << "'!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } else { // no data type specified: fetch from dictionary ec_ioctl_slave_sdo_entry_t entry; @@ -600,18 +513,18 @@ void Master::sdoUpload( try { getSdoEntry(&entry, slavePosition, data.sdo_index, data.sdo_entry_subindex); - } catch (MasterException &e) { + } catch (MasterDeviceException &e) { stringstream err; err << "Failed to determine Sdo entry data type. " << "Please specify --type."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } if (!(dataType = findDataType(entry.data_type))) { stringstream err; err << "Pdo entry has unknown data type 0x" << hex << setfill('0') << setw(4) << entry.data_type << "!" << " Please specify --type."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } @@ -636,7 +549,7 @@ void Master::sdoUpload( } delete [] data.target; close(); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } close(); @@ -646,7 +559,7 @@ void Master::sdoUpload( err << "Data type mismatch. Expected " << dataType->name << " with " << dataType->byteSize << " byte, but got " << data.data_size << " byte."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } cout << setfill('0'); @@ -753,7 +666,7 @@ void Master::siiRead(int slavePosition) if (slavePosition < 0) { stringstream err; err << "'sii_read' requires a slave! Please specify --slave."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } data.slave_position = slavePosition; @@ -772,7 +685,7 @@ void Master::siiRead(int slavePosition) stringstream err; delete [] data.words; err << "Failed to read SII: " << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } if (verbosity == Verbose) { @@ -798,7 +711,7 @@ void Master::siiRead(int slavePosition) if (categoryHeader + 1 > data.words + data.nwords) { err << "SII data seem to be corrupted!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } categorySize = le16tocpu(*(categoryHeader + 1)); cout << ", " << dec << categorySize << " words" << flush; @@ -806,7 +719,7 @@ void Master::siiRead(int slavePosition) if (categoryHeader + 2 + categorySize > data.words + data.nwords) { err << "SII data seem to be corrupted!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } cout << hex; @@ -824,7 +737,7 @@ void Master::siiRead(int slavePosition) if (categoryHeader + 2 + categorySize + 1 > data.words + data.nwords) { err << "SII data seem to be corrupted!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } categoryHeader += 2 + categorySize; categoryType = le16tocpu(*categoryHeader); @@ -858,19 +771,19 @@ void Master::siiWrite( if (slavePosition < 0) { err << "'sii_write' requires a slave! Please specify --slave."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } data.slave_position = slavePosition; if (commandArgs.size() != 1) { err << "'ssi_write' takes exactly one argument!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } file.open(commandArgs[0].c_str(), ifstream::in | ifstream::binary); if (file.fail()) { err << "Failed to open '" << commandArgs[0] << "'!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } // get length of file @@ -881,14 +794,14 @@ void Master::siiWrite( if (!byte_size || byte_size % 2) { stringstream err; err << "Invalid file size! Must be non-zero and even."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } 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 MasterException(err.str()); + throw MasterDeviceException(err.str()); } // allocate buffer and read file into buffer @@ -903,7 +816,7 @@ void Master::siiWrite( err << "CRC incorrect. Must be 0x" << hex << setfill('0') << setw(2) << (unsigned int) crc << ". Use --force to write anyway."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } // cycle through categories to detect corruption @@ -913,14 +826,14 @@ void Master::siiWrite( if (categoryHeader + 1 > data.words + data.nwords) { err << "SII data seem to be corrupted! " << "Use --force to write anyway."; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } 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 MasterException(err.str()); + throw MasterDeviceException(err.str()); } categoryHeader += 2 + categorySize; categoryType = le16tocpu(*categoryHeader); @@ -933,7 +846,7 @@ void Master::siiWrite( if (ioctl(fd, EC_IOCTL_SLAVE_SII_WRITE, &data) < 0) { stringstream err; err << "Failed to write SII: " << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } @@ -950,7 +863,7 @@ void Master::requestStates( if (commandArgs.size() != 1) { stringstream err; err << "'state' takes exactly one argument!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } stateStr = commandArgs[0]; @@ -968,7 +881,7 @@ void Master::requestStates( } else { stringstream err; err << "Invalid state '" << commandArgs[0] << "'!"; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } open(ReadWrite); @@ -999,9 +912,10 @@ void Master::generateXml(int slavePosition) } } +#endif /****************************************************************************/ -void Master::open(Permissions perm) +void MasterDevice::open(Permissions perm) { stringstream deviceName; @@ -1016,13 +930,13 @@ void Master::open(Permissions perm) stringstream err; err << "Failed to open master device " << deviceName.str() << ": " << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::close() +void MasterDevice::close() { if (fd == -1) return; @@ -1031,61 +945,7 @@ void Master::close() fd = -1; } -/*****************************************************************************/ - -/** - * Writes the Secondary slave address (alias) to the slave's SII. - */ -void Master::writeSlaveAlias( - uint16_t slavePosition, - uint16_t alias - ) -{ - ec_ioctl_slave_sii_t data; - ec_ioctl_slave_t slave; - stringstream err; - uint8_t crc; - - open(ReadWrite); - - getSlave(&slave, slavePosition); - - if (slave.sii_nwords < 8) { - err << "Current SII contents are too small to set an alias " - << "(" << slave.sii_nwords << " words)!"; - throw MasterException(err.str()); - } - - data.slave_position = slavePosition; - data.offset = 0; - data.nwords = 8; - data.words = new uint16_t[data.nwords]; - - // read first 8 SII words - if (ioctl(fd, EC_IOCTL_SLAVE_SII_READ, &data) < 0) { - delete [] data.words; - err << "Failed to read SII: " << strerror(errno); - throw MasterException(err.str()); - } - - // 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 - if (ioctl(fd, EC_IOCTL_SLAVE_SII_WRITE, &data) < 0) { - delete [] data.words; - err << "Failed to write SII: " << strerror(errno); - throw MasterException(err.str()); - } - - delete [] data.words; -} +#if 0 /*****************************************************************************/ @@ -1275,7 +1135,7 @@ void Master::outputDomainData(unsigned int domainIndex) try { getData(&data, domainIndex, domain.data_size, processData); - } catch (MasterException &e) { + } catch (MasterDeviceException &e) { delete [] processData; throw e; } @@ -1317,7 +1177,7 @@ void Master::showDomain(unsigned int domainIndex) try { getData(&data, domainIndex, domain.data_size, processData); - } catch (MasterException &e) { + } catch (MasterDeviceException &e) { delete [] processData; throw e; } @@ -1341,7 +1201,7 @@ void Master::showDomain(unsigned int domainIndex) stringstream err; err << "Fmmu information corrupted!"; delete [] processData; - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } cout << " " << hex << setfill('0'); @@ -1781,10 +1641,10 @@ void Master::generateSlaveXml(uint16_t slavePosition) << " </Descriptions>" << endl << "</EtherCATInfo>" << endl; } - +#endif /****************************************************************************/ -unsigned int Master::slaveCount() +unsigned int MasterDevice::slaveCount() { ec_ioctl_master_t data; @@ -1794,31 +1654,31 @@ unsigned int Master::slaveCount() /****************************************************************************/ -void Master::getMaster(ec_ioctl_master_t *data) +void MasterDevice::getMaster(ec_ioctl_master_t *data) { if (ioctl(fd, EC_IOCTL_MASTER, data) < 0) { stringstream err; err << "Failed to get master information: " << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getConfig(ec_ioctl_config_t *data, unsigned int index) +void MasterDevice::getConfig(ec_ioctl_config_t *data, unsigned int index) { data->config_index = index; if (ioctl(fd, EC_IOCTL_CONFIG, data) < 0) { stringstream err; err << "Failed to get slave configuration: " << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getConfigPdo( +void MasterDevice::getConfigPdo( ec_ioctl_config_pdo_t *data, unsigned int index, uint8_t sync_index, @@ -1832,13 +1692,13 @@ void Master::getConfigPdo( if (ioctl(fd, EC_IOCTL_CONFIG_PDO, data) < 0) { stringstream err; err << "Failed to get slave config Pdo: " << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getConfigPdoEntry( +void MasterDevice::getConfigPdoEntry( ec_ioctl_config_pdo_entry_t *data, unsigned int index, uint8_t sync_index, @@ -1854,13 +1714,13 @@ void Master::getConfigPdoEntry( if (ioctl(fd, EC_IOCTL_CONFIG_PDO_ENTRY, data) < 0) { stringstream err; err << "Failed to get slave config Pdo entry: " << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getConfigSdo( +void MasterDevice::getConfigSdo( ec_ioctl_config_sdo_t *data, unsigned int index, unsigned int sdo_pos @@ -1872,13 +1732,13 @@ void Master::getConfigSdo( if (ioctl(fd, EC_IOCTL_CONFIG_SDO, data) < 0) { stringstream err; err << "Failed to get slave config Sdo: " << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getDomain(ec_ioctl_domain_t *data, unsigned int index) +void MasterDevice::getDomain(ec_ioctl_domain_t *data, unsigned int index) { data->index = index; @@ -1889,13 +1749,13 @@ void Master::getDomain(ec_ioctl_domain_t *data, unsigned int index) err << "Domain " << index << " does not exist!"; else err << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getData(ec_ioctl_domain_data_t *data, unsigned int domainIndex, +void MasterDevice::getData(ec_ioctl_domain_data_t *data, unsigned int domainIndex, unsigned int dataSize, unsigned char *mem) { data->domain_index = domainIndex; @@ -1905,13 +1765,13 @@ void Master::getData(ec_ioctl_domain_data_t *data, unsigned int domainIndex, if (ioctl(fd, EC_IOCTL_DOMAIN_DATA, data) < 0) { stringstream err; err << "Failed to get domain data: " << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex) +void MasterDevice::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex) { slave->position = slaveIndex; @@ -1922,13 +1782,13 @@ void Master::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex) err << "Slave " << slaveIndex << " does not exist!"; else err << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getFmmu( +void MasterDevice::getFmmu( ec_ioctl_domain_fmmu_t *fmmu, unsigned int domainIndex, unsigned int fmmuIndex @@ -1946,13 +1806,13 @@ void Master::getFmmu( << " FMMus!"; else err << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getSync( +void MasterDevice::getSync( ec_ioctl_slave_sync_t *sync, uint16_t slaveIndex, uint8_t syncIndex @@ -1970,13 +1830,13 @@ void Master::getSync( << " sync managers!"; else err << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getPdo( +void MasterDevice::getPdo( ec_ioctl_slave_sync_pdo_t *pdo, uint16_t slaveIndex, uint8_t syncIndex, @@ -1998,13 +1858,13 @@ void Master::getPdo( << pdoPos + 1 << " Pdos!" << endl; else err << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getPdoEntry( +void MasterDevice::getPdoEntry( ec_ioctl_slave_sync_pdo_entry_t *entry, uint16_t slaveIndex, uint8_t syncIndex, @@ -2030,13 +1890,13 @@ void Master::getPdoEntry( << " entries!" << endl; else err << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getSdo( +void MasterDevice::getSdo( ec_ioctl_slave_sdo_t *sdo, uint16_t slaveIndex, uint16_t sdoPosition @@ -2054,13 +1914,13 @@ void Master::getSdo( << endl; else err << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::getSdoEntry( +void MasterDevice::getSdoEntry( ec_ioctl_slave_sdo_entry_t *entry, uint16_t slaveIndex, int sdoSpec, @@ -2075,13 +1935,40 @@ void Master::getSdoEntry( stringstream err; err << "Failed to get Sdo entry: "; err << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); + } +} + +/****************************************************************************/ + +void MasterDevice::readSii( + ec_ioctl_slave_sii_t *data + ) +{ + if (ioctl(fd, EC_IOCTL_SLAVE_SII_READ, data) < 0) { + stringstream err; + err << "Failed to read SII: " << strerror(errno); + throw MasterDeviceException(err.str()); + } +} + +/****************************************************************************/ + +void MasterDevice::writeSii( + ec_ioctl_slave_sii_t *data + ) +{ + if (ioctl(fd, EC_IOCTL_SLAVE_SII_WRITE, data) < 0) { + stringstream err; + err << "Failed to write SII: " << strerror(errno); + throw MasterDeviceException(err.str()); } } /****************************************************************************/ -void Master::requestState( +#if 0 +void MasterDevice::requestState( uint16_t slavePosition, uint8_t state ) @@ -2098,7 +1985,7 @@ void Master::requestState( err << "Slave " << slavePosition << " does not exist!"; else err << strerror(errno); - throw MasterException(err.str()); + throw MasterDeviceException(err.str()); } } @@ -2130,46 +2017,5 @@ void Master::printRawData( cout << endl; } -/*****************************************************************************/ - -/** - * Calculates the SII checksum field. - * - * The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an - * initial value of 0xff (see IEC 61158-6-12 ch. 5.4). - * - * The below code was originally generated with PYCRC - * http://www.tty1.net/pycrc - * - * ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff - * --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit - * - * \return CRC8 - */ -uint8_t Master::calcSiiCrc( - const uint8_t *data, /**< pointer to data */ - size_t length /**< number of bytes in \a data */ - ) -{ - unsigned int i; - uint8_t bit, byte, crc = 0x48; - - while (length--) { - byte = *data++; - for (i = 0; i < 8; i++) { - bit = crc & 0x80; - crc = (crc << 1) | ((byte >> (7 - i)) & 0x01); - if (bit) crc ^= 0x07; - } - } - - for (i = 0; i < 8; i++) { - bit = crc & 0x80; - crc <<= 1; - if (bit) crc ^= 0x07; - } - - return crc; -} - +#endif /*****************************************************************************/ diff --git a/tool/Master.h b/tool/MasterDevice.h similarity index 67% rename from tool/Master.h rename to tool/MasterDevice.h index 9ba2327900838c85fd407487cfcfd2421e89fc71..a6e844d0f8009e91ba15c064b474970c681b3457 100644 --- a/tool/Master.h +++ b/tool/MasterDevice.h @@ -18,72 +18,32 @@ using namespace std; /****************************************************************************/ -class MasterException: +class MasterDeviceException: public runtime_error { public: /** Constructor with std::string parameter. */ - MasterException( + MasterDeviceException( const string &s /**< Message. */ ): runtime_error(s) {} - - /** Constructor with const char pointer parameter. */ - MasterException( - const char *s /**< Message. */ - ): runtime_error(s) {} }; /****************************************************************************/ -class Master +class MasterDevice { public: - Master(); - ~Master(); + MasterDevice(); + ~MasterDevice(); void setIndex(unsigned int); - enum Verbosity { - Quiet, - Normal, - Verbose - }; - void setVerbosity(Verbosity); - - void writeAlias(int, bool, const vector<string> &); - void showConfigs(); - void outputData(int); - void setDebug(const vector<string> &); - void showDomains(int); - void showMaster(); - void listPdos(int); - void listSdos(int); - void sdoDownload(int, const string &, const vector<string> &); - void sdoUpload(int, const string &, const vector<string> &); - void showSlaves(int); - void siiRead(int); - void siiWrite(int, bool, const vector<string> &); - void requestStates(int, const vector<string> &); - void generateXml(int); - - protected: enum Permissions {Read, ReadWrite}; void open(Permissions); void close(); - void writeSlaveAlias(uint16_t, uint16_t); - typedef list<ec_ioctl_config_t> ConfigList; - void showDetailedConfigs(const ConfigList &); - void listConfigs(const ConfigList &); - void outputDomainData(unsigned int); - enum {BreakAfterBytes = 16}; - void showDomain(unsigned int); - void listSlavePdos(uint16_t, bool = false); - void listSlaveSdos(uint16_t, bool = false); - void listSlaves(int); - void showSlave(uint16_t); - void generateSlaveXml(uint16_t); unsigned int slaveCount(); + void getMaster(ec_ioctl_master_t *); void getConfig(ec_ioctl_config_t *, unsigned int); void getConfigPdo(ec_ioctl_config_pdo_t *, unsigned int, uint8_t, @@ -102,17 +62,30 @@ class Master uint8_t, uint8_t); void getSdo(ec_ioctl_slave_sdo_t *, uint16_t, uint16_t); void getSdoEntry(ec_ioctl_slave_sdo_entry_t *, uint16_t, int, uint8_t); + void readSii(ec_ioctl_slave_sii_t *); + void writeSii(ec_ioctl_slave_sii_t *); + + protected: +#if 0 + void outputDomainData(unsigned int); + enum {BreakAfterBytes = 16}; + void showDomain(unsigned int); + void listSlavePdos(uint16_t, bool = false); + void listSlaveSdos(uint16_t, bool = false); + void listSlaves(int); + void showSlave(uint16_t); + void generateSlaveXml(uint16_t); void requestState(uint16_t, uint8_t); static string slaveState(uint8_t); static void printRawData(const uint8_t *, unsigned int); static uint8_t calcSiiCrc(const uint8_t *, unsigned int); +#endif private: - enum {DefaultBufferSize = 1024}; + //enum {DefaultBufferSize = 1024}; unsigned int index; - Verbosity verbosity; int fd; }; diff --git a/tool/cmd_alias.cpp b/tool/cmd_alias.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b821845b1570ff0a05d076c4a36b1f24e3a006b --- /dev/null +++ b/tool/cmd_alias.cpp @@ -0,0 +1,181 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include <iostream> +#include <iomanip> +#include <sstream> +using namespace std; + +#include "globals.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 a 16 bit unsigned integer, specified\n" + " either in decimal (no prefix), octal (prefix '0')\n" + " or hexadecimal (prefix '0x').\n" + "\n" + "Command-specific options:\n" + " -s <SLAVE> Write the alias of the slave with the given\n" + " ring position. If this option is not\n" + " specified, the alias of all slaves is set.\n" + " The --force option is required in this\n" + " case.\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 << "'" << command << "' 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 ExecutionFailureException(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); + } +} + +/*****************************************************************************/ + +/** Calculates the SII checksum field. + * + * The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an + * initial value of 0xff (see IEC 61158-6-12 ch. 5.4). + * + * The below code was originally generated with PYCRC + * http://www.tty1.net/pycrc + * + * ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff + * --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit + * + * \return CRC8 + */ +uint8_t calcSiiCrc( + const uint8_t *data, /**< pointer to data */ + size_t length /**< number of bytes in \a data */ + ) +{ + unsigned int i; + uint8_t bit, byte, crc = 0x48; + + while (length--) { + byte = *data++; + for (i = 0; i < 8; i++) { + bit = crc & 0x80; + crc = (crc << 1) | ((byte >> (7 - i)) & 0x01); + if (bit) crc ^= 0x07; + } + } + + for (i = 0; i < 8; i++) { + bit = crc & 0x80; + crc <<= 1; + if (bit) crc ^= 0x07; + } + + return crc; +} + +/*****************************************************************************/ + +/** 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 ExecutionFailureException(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 ExecutionFailureException(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 ExecutionFailureException(err); + } + + delete [] data.words; +} + +/*****************************************************************************/ diff --git a/tool/cmd_config.cpp b/tool/cmd_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff0e6b716872e81bfcd016329c84f7f7a4c39d36 --- /dev/null +++ b/tool/cmd_config.cpp @@ -0,0 +1,237 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include <list> +#include <iostream> +#include <iomanip> +#include <sstream> +using namespace std; + +#include "globals.h" + +/*****************************************************************************/ + +const char *help_config = + "[OPTIONS]\n" + "\n" + "\n" + "Command-specific options:\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; + } +} + +/*****************************************************************************/ diff --git a/tool/globals.h b/tool/globals.h new file mode 100644 index 0000000000000000000000000000000000000000..31e0647646d147909aa8009a2b7ae36bd266bb16 --- /dev/null +++ b/tool/globals.h @@ -0,0 +1,89 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include <sys/types.h> + +#include <string> +#include <sstream> +#include <vector> +using namespace std; + +#include "MasterDevice.h" + +/*****************************************************************************/ + +enum Verbosity { + Quiet, + Normal, + Verbose +}; + +extern string command; +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 ExecutionFailureException: + public runtime_error +{ + public: + /** Constructor with std::string parameter. */ + ExecutionFailureException( + 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 + +/****************************************************************************/ diff --git a/tool/main.cpp b/tool/main.cpp index 4418ff6b4bda1ef59fb0d26176b74ce0751b6064..c9f73eaa4df6c8badf826a7b35ce06b0cfdbcd27 100644 --- a/tool/main.cpp +++ b/tool/main.cpp @@ -12,29 +12,93 @@ #include <vector> using namespace std; -#include "Master.h" +#include "globals.h" /*****************************************************************************/ -#define DEFAULT_MASTER 0 - -static string cmdName; -static unsigned int masterIndex = DEFAULT_MASTER; -static int slavePosition = -1; -static int domainIndex = -1; -static string command; +string binaryBaseName; +unsigned int masterIndex = 0; +int slavePosition = -1; +int domainIndex = -1; +string command; vector<string> commandArgs; -static Master::Verbosity verbosity = Master::Normal; +Verbosity verbosity = Normal; string dataTypeStr; bool force = false; + bool helpRequested = false; +MasterDevice masterDev; + +/*****************************************************************************/ + +struct Command { + void (*func)(void); + const char *helpString; + + int execute(void) const; + void displayHelp(void) const; +}; + +struct CommandAlias { + const char *name; + const Command *command; +}; + +/*****************************************************************************/ + +#define COMMAND(name) \ + void command_##name(void); \ + extern const char *help_##name; \ + const Command cmd_##name = {command_##name, help_##name}; + +COMMAND(alias); +COMMAND(config); + +const CommandAlias commandAliases[] = { + {"alias", &cmd_alias}, + + {"config", &cmd_config}, + {"conf", &cmd_config}, + {"cf", &cmd_config}, +}; + +#if 0 + } else if (command == "data") { + master.outputData(domainIndex); + } else if (command == "debug") { + master.setDebug(commandArgs); + } else if (command == "domain") { + master.showDomains(domainIndex); + } else if (command == "master") { + master.showMaster(); + } else if (command == "pdos") { + master.listPdos(slavePosition); + } else if (command == "sdos") { + master.listSdos(slavePosition); + } else if (command == "sdo_download" || command == "sd") { + master.sdoDownload(slavePosition, dataTypeStr, commandArgs); + } else if (command == "sdo_upload" || command == "su") { + master.sdoUpload(slavePosition, dataTypeStr, commandArgs); + } else if (command == "slave" || command == "slaves" + || command == "list" || command == "ls") { + master.showSlaves(slavePosition); + } else if (command == "sii_read" || command == "sr") { + master.siiRead(slavePosition); + } else if (command == "sii_write" || command == "sw") { + master.siiWrite(slavePosition, force, commandArgs); + } else if (command == "state") { + master.requestStates(slavePosition, commandArgs); + } else if (command == "xml") { + master.generateXml(slavePosition); +#endif + /*****************************************************************************/ void printUsage() { cerr - << "Usage: " << cmdName << " <COMMAND> [OPTIONS]" << endl + << "Usage: " << binaryBaseName << " <COMMAND> [OPTIONS]" << endl << "Commands:" << endl << " alias Write alias addresses." << endl << " config Show bus configuration." << endl @@ -52,8 +116,8 @@ void printUsage() << " state Request slave states." << endl << " xml Generate slave information xmls." << endl << "Global options:" << endl - << " --master -m <master> Index of the master to use. Default: " - << DEFAULT_MASTER << endl + << " --master -m <master> Index of the master to use. Default: 0" + << endl << " --slave -s <index> Positive numerical ring position," << endl << " or 'all' for all slaves (default)." @@ -67,8 +131,8 @@ void printUsage() << " --quiet -q Output less information." << endl << " --verbose -v Output more information." << endl << " --help -h Show this help." << endl - << "Call '" << cmdName << " <COMMAND> --help' for command-specific " - << "help." << endl + << "Call '" << binaryBaseName + << " <COMMAND> --help' for command-specific help." << endl << "Send bug reports to " << PACKAGE_BUGREPORT << "." << endl; } @@ -146,11 +210,11 @@ void getOptions(int argc, char **argv) break; case 'q': - verbosity = Master::Quiet; + verbosity = Quiet; break; case 'v': - verbosity = Master::Verbose; + verbosity = Verbose; break; case 'h': @@ -184,60 +248,64 @@ void getOptions(int argc, char **argv) /****************************************************************************/ +int Command::execute() const +{ + try { + func(); + } catch (InvalidUsageException &e) { + cerr << e.what() << endl << endl; + displayHelp(); + return 1; + } catch (ExecutionFailureException &e) { + cerr << e.what() << endl; + return 1; + } catch (MasterDeviceException &e) { + cerr << e.what() << endl; + return 1; + } + + return 0; +} + +/****************************************************************************/ + +void Command::displayHelp() const +{ + cerr << binaryBaseName << " " << command << " " << helpString; +} + +/****************************************************************************/ + int main(int argc, char **argv) { - Master master; + int retval = 0; + const CommandAlias *alias; + const CommandAlias *endAlias = + commandAliases + sizeof(commandAliases) / sizeof(CommandAlias); - cmdName = basename(argv[0]); - + binaryBaseName = basename(argv[0]); getOptions(argc, argv); - master.setIndex(masterIndex); - master.setVerbosity(verbosity); + // search command alias in alias map + for (alias = commandAliases; alias < endAlias; alias++) { + if (command == alias->name) + break; + } - try { - if (command == "alias") { - master.writeAlias(slavePosition, force, commandArgs); - } else if (command == "config") { - master.showConfigs(); - } else if (command == "data") { - master.outputData(domainIndex); - } else if (command == "debug") { - master.setDebug(commandArgs); - } else if (command == "domain") { - master.showDomains(domainIndex); - } else if (command == "master") { - master.showMaster(); - } else if (command == "pdos") { - master.listPdos(slavePosition); - } else if (command == "sdos") { - master.listSdos(slavePosition); - } else if (command == "sdo_download" || command == "sd") { - master.sdoDownload(slavePosition, dataTypeStr, commandArgs); - } else if (command == "sdo_upload" || command == "su") { - master.sdoUpload(slavePosition, dataTypeStr, commandArgs); - } else if (command == "slave" || command == "slaves" - || command == "list" || command == "ls") { - master.showSlaves(slavePosition); - } else if (command == "sii_read" || command == "sr") { - master.siiRead(slavePosition); - } else if (command == "sii_write" || command == "sw") { - master.siiWrite(slavePosition, force, commandArgs); - } else if (command == "state") { - master.requestStates(slavePosition, commandArgs); - } else if (command == "xml") { - master.generateXml(slavePosition); + if (alias < endAlias) { // command alias found + if (!helpRequested) { + masterDev.setIndex(masterIndex); + retval = alias->command->execute(); } else { - cerr << "Unknown command " << command << "!" << endl; - printUsage(); - exit(1); + alias->command->displayHelp(); } - } catch (MasterException &e) { - cerr << e.what() << endl; - exit(1); + } else { // command not found + cerr << "Unknown command " << command << "!" << endl << endl; + printUsage(); + retval = 1; } - return 0; + return retval; } /****************************************************************************/