--- a/tool/Master.cpp Mon Jul 21 22:06:33 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2175 +0,0 @@
-/*****************************************************************************
- *
- * $Id$
- *
- ****************************************************************************/
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-
-#include <iostream>
-#include <iomanip>
-#include <sstream>
-#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
-
-/****************************************************************************/
-
-struct CoEDataType {
- const char *name;
- uint16_t coeCode;
- unsigned int byteSize;
-};
-
-static const CoEDataType dataTypes[] = {
- {"int8", 0x0002, 1},
- {"int16", 0x0003, 2},
- {"int32", 0x0004, 4},
- {"uint8", 0x0005, 1},
- {"uint16", 0x0006, 2},
- {"uint32", 0x0007, 4},
- {"string", 0x0009, 0},
- {"raw", 0xffff, 0},
- {}
-};
-
-/****************************************************************************/
-
-const CoEDataType *findDataType(const string &str)
-{
- const CoEDataType *d;
-
- for (d = dataTypes; d->name; d++)
- if (str == d->name)
- return d;
-
- return NULL;
-}
-
-/****************************************************************************/
-
-const CoEDataType *findDataType(uint16_t code)
-{
- const CoEDataType *d;
-
- for (d = dataTypes; d->name; d++)
- if (code == d->coeCode)
- return d;
-
- return NULL;
-}
-
-/****************************************************************************/
-
-Master::Master()
-{
- index = 0;
- verbosity = Normal;
- fd = -1;
-}
-
-/****************************************************************************/
-
-Master::~Master()
-{
- close();
-}
-
-/****************************************************************************/
-
-void Master::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);
- }
-}
-
-/*****************************************************************************/
-
-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 Master::showConfigs()
-{
- ec_ioctl_master_t master;
- unsigned int i;
- ec_ioctl_config_t config;
- ConfigList configList;
-
- open(Read);
- getMaster(&master);
-
- for (i = 0; i < master.config_count; i++) {
- getConfig(&config, i);
- configList.push_back(config);
- }
-
- configList.sort();
-
- if (verbosity == Verbose) {
- showDetailedConfigs(configList);
- } else {
- listConfigs(configList);
- }
-}
-
-/****************************************************************************/
-
-void Master::outputData(int domainIndex)
-{
- open(Read);
-
- if (domainIndex == -1) {
- unsigned int i;
- ec_ioctl_master_t master;
-
- getMaster(&master);
-
- for (i = 0; i < master.domain_count; i++) {
- outputDomainData(i);
- }
- } else {
- outputDomainData(domainIndex);
- }
-}
-
-/****************************************************************************/
-
-void Master::setDebug(const vector<string> &commandArgs)
-{
- stringstream str;
- int debugLevel;
-
- if (commandArgs.size() != 1) {
- stringstream err;
- err << "'debug' takes exactly one argument!";
- throw MasterException(err.str());
- }
-
- str << commandArgs[0];
- str >> resetiosflags(ios::basefield) // guess base from prefix
- >> debugLevel;
-
- if (str.fail()) {
- stringstream err;
- err << "Invalid debug level '" << commandArgs[0] << "'!";
- throw MasterException(err.str());
- }
-
- open(ReadWrite);
-
- if (ioctl(fd, EC_IOCTL_MASTER_DEBUG, debugLevel) < 0) {
- stringstream err;
- err << "Failed to set debug level: " << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::showDomains(int domainIndex)
-{
- open(Read);
-
- if (domainIndex == -1) {
- unsigned int i;
- ec_ioctl_master_t master;
-
- getMaster(&master);
-
- for (i = 0; i < master.domain_count; i++) {
- showDomain(i);
- }
- } else {
- showDomain(domainIndex);
- }
-}
-
-/****************************************************************************/
-
-void Master::showMaster()
-{
- ec_ioctl_master_t data;
- stringstream err;
- unsigned int i;
-
- open(Read);
- getMaster(&data);
-
- cout
- << "Master" << index << endl
- << " Phase: ";
-
- switch (data.phase) {
- case 0: cout << "Waiting for device..."; break;
- case 1: cout << "Idle"; break;
- case 2: cout << "Operation"; break;
- default:
- err << "Invalid master phase " << data.phase;
- throw MasterException(err.str());
- }
-
- cout << endl
- << " Slaves: " << data.slave_count << endl;
-
- for (i = 0; i < 2; i++) {
- cout << " Device" << i << ": ";
- if (data.devices[i].address[0] == 0x00
- && data.devices[i].address[1] == 0x00
- && data.devices[i].address[2] == 0x00
- && data.devices[i].address[3] == 0x00
- && data.devices[i].address[4] == 0x00
- && data.devices[i].address[5] == 0x00) {
- cout << "None.";
- } else {
- cout << hex << setfill('0')
- << setw(2) << (unsigned int) data.devices[i].address[0] << ":"
- << setw(2) << (unsigned int) data.devices[i].address[1] << ":"
- << setw(2) << (unsigned int) data.devices[i].address[2] << ":"
- << setw(2) << (unsigned int) data.devices[i].address[3] << ":"
- << setw(2) << (unsigned int) data.devices[i].address[4] << ":"
- << setw(2) << (unsigned int) data.devices[i].address[5] << " ("
- << (data.devices[i].attached ? "attached" : "waiting...")
- << ")" << endl << dec
- << " Tx count: " << data.devices[i].tx_count << endl
- << " Rx count: " << data.devices[i].rx_count;
- }
- cout << endl;
- }
-}
-
-/****************************************************************************/
-
-void Master::listPdos(int slavePosition)
-{
- open(Read);
-
- if (slavePosition == -1) {
- unsigned int numSlaves = slaveCount(), i;
-
- for (i = 0; i < numSlaves; i++) {
- listSlavePdos(i, true);
- }
- } else {
- listSlavePdos(slavePosition, false);
- }
-}
-
-/****************************************************************************/
-
-void Master::listSdos(int slavePosition)
-{
- open(Read);
-
- if (slavePosition == -1) {
- unsigned int numSlaves = slaveCount(), i;
-
- for (i = 0; i < numSlaves; i++) {
- listSlaveSdos(i, true);
- }
- } else {
- listSlaveSdos(slavePosition, false);
- }
-}
-
-/****************************************************************************/
-
-void Master::sdoDownload(
- int slavePosition,
- const string &dataTypeStr,
- const vector<string> &commandArgs
- )
-{
- stringstream strIndex, strSubIndex, strValue, err;
- ec_ioctl_slave_sdo_download_t data;
- unsigned int number;
- const CoEDataType *dataType = NULL;
-
- if (slavePosition < 0) {
- err << "'sdo_download' requires a slave! Please specify --slave.";
- throw MasterException(err.str());
- }
- data.slave_position = slavePosition;
-
- if (commandArgs.size() != 3) {
- err << "'sdo_download' takes 3 arguments!";
- throw MasterException(err.str());
- }
-
- strIndex << commandArgs[0];
- strIndex
- >> resetiosflags(ios::basefield) // guess base from prefix
- >> data.sdo_index;
- if (strIndex.fail()) {
- err << "Invalid Sdo index '" << commandArgs[0] << "'!";
- throw MasterException(err.str());
- }
-
- strSubIndex << commandArgs[1];
- strSubIndex
- >> resetiosflags(ios::basefield) // guess base from prefix
- >> number;
- if (strSubIndex.fail() || number > 0xff) {
- err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
- throw MasterException(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());
- }
- } else { // no data type specified: fetch from dictionary
- ec_ioctl_slave_sdo_entry_t entry;
-
- open(ReadWrite);
-
- try {
- getSdoEntry(&entry, slavePosition,
- data.sdo_index, data.sdo_entry_subindex);
- } catch (MasterException &e) {
- err << "Failed to determine Sdo entry data type. "
- << "Please specify --type.";
- throw MasterException(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());
- }
- }
-
- if (dataType->byteSize) {
- data.data_size = dataType->byteSize;
- } else {
- data.data_size = DefaultBufferSize;
- }
-
- data.data = new uint8_t[data.data_size + 1];
-
- strValue << commandArgs[2];
- strValue >> resetiosflags(ios::basefield); // guess base from prefix
- strValue.exceptions(ios::failbit);
-
- try {
- switch (dataType->coeCode) {
- case 0x0002: // int8
- {
- int16_t val; // uint8_t is interpreted as char
- strValue >> val;
- if (val > 127 || val < -128)
- throw ios::failure("Value out of range");
- *data.data = val;
- break;
- }
- case 0x0003: // int16
- {
- int16_t val;
- strValue >> val;
- *(int16_t *) data.data = cputole16(val);
- break;
- }
- case 0x0004: // int32
- {
- int32_t val;
- strValue >> val;
- *(int32_t *) data.data = cputole32(val);
- break;
- }
- case 0x0005: // uint8
- {
- uint16_t val; // uint8_t is interpreted as char
- strValue >> val;
- if (val > 0xff)
- throw ios::failure("Value out of range");
- *data.data = val;
- break;
- }
- case 0x0006: // uint16
- {
- uint16_t val;
- strValue >> val;
- *(uint16_t *) data.data = cputole16(val);
- break;
- }
- case 0x0007: // uint32
- {
- uint32_t val;
- strValue >> val;
- *(uint32_t *) data.data = cputole32(val);
- break;
- }
- case 0x0009: // string
- if (strValue.str().size() >= data.data_size) {
- err << "String too large";
- throw MasterException(err.str());
- }
- data.data_size = strValue.str().size();
- strValue >> (char *) data.data;
- break;
-
- default:
- delete [] data.data;
- err << "Unknown data type 0x" << hex << dataType->coeCode;
- throw MasterException(err.str());
- }
- } catch (ios::failure &e) {
- delete [] data.data;
- err << "Invalid value argument '" << commandArgs[2]
- << "' for type '" << dataType->name << "'!";
- throw MasterException(err.str());
- }
-
- open(ReadWrite);
-
- if (ioctl(fd, EC_IOCTL_SLAVE_SDO_DOWNLOAD, &data) < 0) {
- stringstream err;
- err << "Failed to download Sdo: ";
- if (errno == EIO && data.abort_code) {
- err << "Abort code 0x" << hex << setfill('0')
- << setw(8) << data.abort_code;
- } else {
- err << strerror(errno);
- }
- delete [] data.data;
- throw MasterException(err.str());
- }
-
- delete [] data.data;
-}
-
-/****************************************************************************/
-
-void Master::sdoUpload(
- int slavePosition,
- const string &dataTypeStr,
- const vector<string> &commandArgs
- )
-{
- stringstream strIndex, strSubIndex;
- int sval;
- ec_ioctl_slave_sdo_upload_t data;
- unsigned int uval;
- const CoEDataType *dataType = NULL;
-
- if (slavePosition < 0) {
- stringstream err;
- err << "'sdo_upload' requires a slave! Please specify --slave.";
- throw MasterException(err.str());
- }
- data.slave_position = slavePosition;
-
- if (commandArgs.size() != 2) {
- stringstream err;
- err << "'sdo_upload' takes two arguments!";
- throw MasterException(err.str());
- }
-
- strIndex << commandArgs[0];
- strIndex
- >> resetiosflags(ios::basefield) // guess base from prefix
- >> data.sdo_index;
- if (strIndex.fail()) {
- stringstream err;
- err << "Invalid Sdo index '" << commandArgs[0] << "'!";
- throw MasterException(err.str());
- }
-
- strSubIndex << commandArgs[1];
- strSubIndex
- >> resetiosflags(ios::basefield) // guess base from prefix
- >> uval;
- if (strSubIndex.fail() || uval > 0xff) {
- stringstream err;
- err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
- throw MasterException(err.str());
- }
- data.sdo_entry_subindex = uval;
-
- if (dataTypeStr != "") { // data type specified
- if (!(dataType = findDataType(dataTypeStr))) {
- stringstream err;
- err << "Invalid data type '" << dataTypeStr << "'!";
- throw MasterException(err.str());
- }
- } else { // no data type specified: fetch from dictionary
- ec_ioctl_slave_sdo_entry_t entry;
-
- open(Read);
-
- try {
- getSdoEntry(&entry, slavePosition,
- data.sdo_index, data.sdo_entry_subindex);
- } catch (MasterException &e) {
- stringstream err;
- err << "Failed to determine Sdo entry data type. "
- << "Please specify --type.";
- throw MasterException(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());
- }
- }
-
- if (dataType->byteSize) {
- data.target_size = dataType->byteSize;
- } else {
- data.target_size = DefaultBufferSize;
- }
-
- data.target = new uint8_t[data.target_size + 1];
-
- open(Read);
-
- if (ioctl(fd, EC_IOCTL_SLAVE_SDO_UPLOAD, &data) < 0) {
- stringstream err;
- err << "Failed to upload Sdo: ";
- if (errno == EIO && data.abort_code) {
- err << "Abort code 0x" << hex << setfill('0')
- << setw(8) << data.abort_code;
- } else {
- err << strerror(errno);
- }
- delete [] data.target;
- close();
- throw MasterException(err.str());
- }
-
- close();
-
- if (dataType->byteSize && data.data_size != dataType->byteSize) {
- stringstream err;
- err << "Data type mismatch. Expected " << dataType->name
- << " with " << dataType->byteSize << " byte, but got "
- << data.data_size << " byte.";
- throw MasterException(err.str());
- }
-
- cout << setfill('0');
- switch (dataType->coeCode) {
- case 0x0002: // int8
- sval = *(int8_t *) data.target;
- cout << sval << " 0x" << hex << setw(2) << sval << endl;
- break;
- case 0x0003: // int16
- sval = le16tocpu(*(int16_t *) data.target);
- cout << sval << " 0x" << hex << setw(4) << sval << endl;
- break;
- case 0x0004: // int32
- sval = le32tocpu(*(int32_t *) data.target);
- cout << sval << " 0x" << hex << setw(8) << sval << endl;
- break;
- case 0x0005: // uint8
- uval = (unsigned int) *(uint8_t *) data.target;
- cout << uval << " 0x" << hex << setw(2) << uval << endl;
- break;
- case 0x0006: // uint16
- uval = le16tocpu(*(uint16_t *) data.target);
- cout << uval << " 0x" << hex << setw(4) << uval << endl;
- break;
- case 0x0007: // uint32
- uval = le32tocpu(*(uint32_t *) data.target);
- cout << uval << " 0x" << hex << setw(8) << uval << endl;
- break;
- case 0x0009: // string
- cout << string((const char *) data.target, data.data_size)
- << endl;
- break;
- default:
- printRawData(data.target, data.data_size);
- break;
- }
-
- delete [] data.target;
-}
-
-/****************************************************************************/
-
-void Master::showSlaves(int slavePosition)
-{
- open(Read);
-
- if (verbosity == Verbose) {
- if (slavePosition == -1) {
- unsigned int numSlaves = slaveCount(), i;
-
- for (i = 0; i < numSlaves; i++) {
- showSlave(i);
- }
- } else {
- showSlave(slavePosition);
- }
- } else {
- listSlaves(slavePosition);
- }
-}
-
-/****************************************************************************/
-
-struct CategoryName {
- uint16_t type;
- const char *name;
-};
-
-static const CategoryName categoryNames[] = {
- {0x000a, "STRINGS"},
- {0x0014, "DataTypes"},
- {0x001e, "General"},
- {0x0028, "FMMU"},
- {0x0029, "SyncM"},
- {0x0032, "TXPDO"},
- {0x0033, "RXPDO"},
- {0x003c, "DC"},
- {}
-};
-
-const char *getCategoryName(uint16_t type)
-{
- const CategoryName *cn = categoryNames;
-
- while (cn->type) {
- if (cn->type == type) {
- return cn->name;
- }
- cn++;
- }
-
- return "unknown";
-}
-
-void Master::siiRead(int slavePosition)
-{
- ec_ioctl_slave_sii_t data;
- ec_ioctl_slave_t slave;
- unsigned int i;
- const uint16_t *categoryHeader;
- uint16_t categoryType, categorySize;
- stringstream err;
-
- if (slavePosition < 0) {
- stringstream err;
- err << "'sii_read' requires a slave! Please specify --slave.";
- throw MasterException(err.str());
- }
- data.slave_position = slavePosition;
-
- open(Read);
-
- getSlave(&slave, slavePosition);
-
- if (!slave.sii_nwords)
- return;
-
- data.offset = 0;
- data.nwords = slave.sii_nwords;
- data.words = new uint16_t[data.nwords];
-
- if (ioctl(fd, EC_IOCTL_SLAVE_SII_READ, &data) < 0) {
- stringstream err;
- delete [] data.words;
- err << "Failed to read SII: " << strerror(errno);
- throw MasterException(err.str());
- }
-
- if (verbosity == Verbose) {
- cout << "SII Area:" << hex << setfill('0');
- for (i = 0; i < min(data.nwords, 0x0040U) * 2; i++) {
- if (i % BreakAfterBytes) {
- cout << " ";
- } else {
- cout << endl << " ";
- }
- cout << setw(2) << (unsigned int) *((uint8_t *) data.words + i);
- }
- cout << endl;
-
- if (data.nwords > 0x0040U) {
- // cycle through categories
- categoryHeader = data.words + 0x0040U;
- categoryType = le16tocpu(*categoryHeader);
- while (categoryType != 0xffff) {
- cout << "SII Category 0x" << hex
- << setw(4) << categoryType
- << " (" << getCategoryName(categoryType) << ")" << flush;
-
- if (categoryHeader + 1 > data.words + data.nwords) {
- err << "SII data seem to be corrupted!";
- throw MasterException(err.str());
- }
- categorySize = le16tocpu(*(categoryHeader + 1));
- cout << ", " << dec << categorySize << " words" << flush;
-
- if (categoryHeader + 2 + categorySize
- > data.words + data.nwords) {
- err << "SII data seem to be corrupted!";
- throw MasterException(err.str());
- }
-
- cout << hex;
- for (i = 0; i < categorySize * 2U; i++) {
- if (i % BreakAfterBytes) {
- cout << " ";
- } else {
- cout << endl << " ";
- }
- cout << setw(2) << (unsigned int)
- *((uint8_t *) (categoryHeader + 2) + i);
- }
- cout << endl;
-
- if (categoryHeader + 2 + categorySize + 1
- > data.words + data.nwords) {
- err << "SII data seem to be corrupted!";
- throw MasterException(err.str());
- }
- categoryHeader += 2 + categorySize;
- categoryType = le16tocpu(*categoryHeader);
- }
- }
- } else {
- for (i = 0; i < data.nwords; i++) {
- uint16_t *w = data.words + i;
- cout << *(uint8_t *) w << *((uint8_t *) w + 1);
- }
- }
-
- delete [] data.words;
-}
-
-/****************************************************************************/
-
-void Master::siiWrite(
- int slavePosition,
- bool force,
- const vector<string> &commandArgs
- )
-{
- stringstream err;
- ec_ioctl_slave_sii_t data;
- ifstream file;
- unsigned int byte_size;
- const uint16_t *categoryHeader;
- uint16_t categoryType, categorySize;
- uint8_t crc;
-
- if (slavePosition < 0) {
- err << "'sii_write' requires a slave! Please specify --slave.";
- throw MasterException(err.str());
- }
- data.slave_position = slavePosition;
-
- if (commandArgs.size() != 1) {
- err << "'ssi_write' takes exactly one argument!";
- throw MasterException(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());
- }
-
- // get length of file
- file.seekg(0, ios::end);
- byte_size = file.tellg();
- file.seekg(0, ios::beg);
-
- if (!byte_size || byte_size % 2) {
- stringstream err;
- err << "Invalid file size! Must be non-zero and even.";
- throw MasterException(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());
- }
-
- // allocate buffer and read file into buffer
- data.words = new uint16_t[data.nwords];
- file.read((char *) data.words, byte_size);
- file.close();
-
- if (!force) {
- // calculate checksum over words 0 to 6
- crc = calcSiiCrc((const uint8_t *) data.words, 14);
- if (crc != ((const uint8_t *) data.words)[14]) {
- err << "CRC incorrect. Must be 0x"
- << hex << setfill('0') << setw(2) << (unsigned int) crc
- << ". Use --force to write anyway.";
- throw MasterException(err.str());
- }
-
- // cycle through categories to detect corruption
- categoryHeader = data.words + 0x0040U;
- categoryType = le16tocpu(*categoryHeader);
- while (categoryType != 0xffff) {
- if (categoryHeader + 1 > data.words + data.nwords) {
- err << "SII data seem to be corrupted! "
- << "Use --force to write anyway.";
- throw MasterException(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());
- }
- categoryHeader += 2 + categorySize;
- categoryType = le16tocpu(*categoryHeader);
- }
- }
-
- // send data to master
- open(ReadWrite);
- data.offset = 0;
- if (ioctl(fd, EC_IOCTL_SLAVE_SII_WRITE, &data) < 0) {
- stringstream err;
- err << "Failed to write SII: " << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::requestStates(
- int slavePosition,
- const vector<string> &commandArgs
- )
-{
- string stateStr;
- uint8_t state;
-
- if (commandArgs.size() != 1) {
- stringstream err;
- err << "'state' takes exactly one argument!";
- throw MasterException(err.str());
- }
-
- stateStr = commandArgs[0];
- transform(stateStr.begin(), stateStr.end(),
- stateStr.begin(), (int (*) (int)) std::toupper);
-
- if (stateStr == "INIT") {
- state = 0x01;
- } else if (stateStr == "PREOP") {
- state = 0x02;
- } else if (stateStr == "SAFEOP") {
- state = 0x04;
- } else if (stateStr == "OP") {
- state = 0x08;
- } else {
- stringstream err;
- err << "Invalid state '" << commandArgs[0] << "'!";
- throw MasterException(err.str());
- }
-
- open(ReadWrite);
-
- if (slavePosition == -1) {
- unsigned int i, numSlaves = slaveCount();
- for (i = 0; i < numSlaves; i++)
- requestState(i, state);
- } else {
- requestState(slavePosition, state);
- }
-}
-
-/****************************************************************************/
-
-void Master::generateXml(int slavePosition)
-{
- open(Read);
-
- if (slavePosition == -1) {
- unsigned int numSlaves = slaveCount(), i;
-
- for (i = 0; i < numSlaves; i++) {
- generateSlaveXml(i);
- }
- } else {
- generateSlaveXml(slavePosition);
- }
-}
-
-/****************************************************************************/
-
-void Master::open(Permissions perm)
-{
- stringstream deviceName;
-
- if (fd != -1) { // already open
- return;
- }
-
- deviceName << "/dev/EtherCAT" << index;
-
- if ((fd = ::open(deviceName.str().c_str(),
- perm == ReadWrite ? O_RDWR : O_RDONLY)) == -1) {
- stringstream err;
- err << "Failed to open master device " << deviceName.str() << ": "
- << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::close()
-{
- if (fd == -1)
- return;
-
- ::close(fd);
- 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;
-}
-
-/*****************************************************************************/
-
-/** Lists the complete bus configuration.
- */
-void Master::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++) {
- 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++) {
- 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++) {
- 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;
- }
-}
-
-/*****************************************************************************/
-
-struct ConfigInfo {
- string alias;
- string pos;
- string ident;
- string att;
- string op;
-};
-
-/** Lists the bus configuration.
- */
-void Master::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;
- }
-}
-
-/****************************************************************************/
-
-void Master::outputDomainData(unsigned int domainIndex)
-{
- ec_ioctl_domain_t domain;
- ec_ioctl_domain_data_t data;
- unsigned char *processData;
- unsigned int i;
-
- getDomain(&domain, domainIndex);
-
- if (!domain.data_size)
- return;
-
- processData = new unsigned char[domain.data_size];
-
- try {
- getData(&data, domainIndex, domain.data_size, processData);
- } catch (MasterException &e) {
- delete [] processData;
- throw e;
- }
-
- for (i = 0; i < data.data_size; i++)
- cout << processData[i];
- cout.flush();
-
- delete [] processData;
-}
-
-/****************************************************************************/
-
-void Master::showDomain(unsigned int domainIndex)
-{
- ec_ioctl_domain_t domain;
- unsigned char *processData;
- ec_ioctl_domain_data_t data;
- unsigned int i, j;
- ec_ioctl_domain_fmmu_t fmmu;
- unsigned int dataOffset;
-
- getDomain(&domain, domainIndex);
-
- cout << "Domain" << dec << domainIndex << ":"
- << " LogBaseAddr 0x"
- << hex << setfill('0')
- << setw(8) << domain.logical_base_address
- << ", Size " << dec << setfill(' ')
- << setw(3) << domain.data_size
- << ", WorkingCounter "
- << domain.working_counter << "/"
- << domain.expected_working_counter << endl;
-
- if (!domain.data_size || verbosity != Verbose)
- return;
-
- processData = new unsigned char[domain.data_size];
-
- try {
- getData(&data, domainIndex, domain.data_size, processData);
- } catch (MasterException &e) {
- delete [] processData;
- throw e;
- }
-
- for (i = 0; i < domain.fmmu_count; i++) {
- getFmmu(&fmmu, domainIndex, i);
-
- cout << " SlaveConfig "
- << dec << fmmu.slave_config_alias
- << ":" << fmmu.slave_config_position
- << ", SM" << (unsigned int) fmmu.sync_index << " ("
- << setfill(' ') << setw(6)
- << (fmmu.dir == EC_DIR_INPUT ? "Input" : "Output")
- << "), LogAddr 0x"
- << hex << setfill('0')
- << setw(8) << fmmu.logical_address
- << ", Size " << dec << fmmu.data_size << endl;
-
- dataOffset = fmmu.logical_address - domain.logical_base_address;
- if (dataOffset + fmmu.data_size > domain.data_size) {
- stringstream err;
- err << "Fmmu information corrupted!";
- delete [] processData;
- throw MasterException(err.str());
- }
-
- cout << " " << hex << setfill('0');
- for (j = 0; j < fmmu.data_size; j++) {
- if (j && !(j % BreakAfterBytes))
- cout << endl << " ";
- cout << setw(2)
- << (unsigned int) *(processData + dataOffset + j) << " ";
- }
- cout << endl;
- }
-
- delete [] processData;
-}
-
-/****************************************************************************/
-
-void Master::listSlavePdos(
- uint16_t slavePosition,
- bool withHeader
- )
-{
- ec_ioctl_slave_t slave;
- ec_ioctl_slave_sync_t sync;
- ec_ioctl_slave_sync_pdo_t pdo;
- ec_ioctl_slave_sync_pdo_entry_t entry;
- unsigned int i, j, k;
-
- getSlave(&slave, slavePosition);
-
- if (withHeader)
- cout << "=== Slave " << slavePosition << " ===" << endl;
-
- for (i = 0; i < slave.sync_count; i++) {
- getSync(&sync, slavePosition, i);
-
- cout << "SM" << i << ":"
- << " PhysAddr 0x"
- << hex << setfill('0')
- << setw(4) << sync.physical_start_address
- << ", DefaultSize "
- << dec << setfill(' ') << setw(4) << sync.default_size
- << ", ControlRegister 0x"
- << hex << setfill('0') << setw(2)
- << (unsigned int) sync.control_register
- << ", Enable " << dec << (unsigned int) sync.enable
- << endl;
-
- for (j = 0; j < sync.pdo_count; j++) {
- getPdo(&pdo, slavePosition, i, j);
-
- cout << " " << (sync.control_register & 0x04 ? "R" : "T")
- << "xPdo 0x"
- << hex << setfill('0')
- << setw(4) << pdo.index
- << " \"" << pdo.name << "\"" << endl;
-
- if (verbosity == Quiet)
- continue;
-
- for (k = 0; k < pdo.entry_count; k++) {
- getPdoEntry(&entry, slavePosition, i, j, k);
-
- cout << " Pdo entry 0x"
- << hex << setfill('0')
- << setw(4) << entry.index
- << ":" << setw(2) << (unsigned int) entry.subindex
- << ", " << dec << (unsigned int) entry.bit_length
- << " bit, \"" << entry.name << "\"" << endl;
- }
- }
- }
-}
-
-/****************************************************************************/
-
-void Master::listSlaveSdos(
- uint16_t slavePosition,
- bool withHeader
- )
-{
- ec_ioctl_slave_t slave;
- ec_ioctl_slave_sdo_t sdo;
- ec_ioctl_slave_sdo_entry_t entry;
- unsigned int i, j;
- const CoEDataType *d;
-
- getSlave(&slave, slavePosition);
-
- if (withHeader)
- cout << "=== Slave " << slavePosition << " ===" << endl;
-
- for (i = 0; i < slave.sdo_count; i++) {
- getSdo(&sdo, slavePosition, i);
-
- cout << "Sdo 0x"
- << hex << setfill('0')
- << setw(4) << sdo.sdo_index
- << ", \"" << sdo.name << "\"" << endl;
-
- if (verbosity == Quiet)
- continue;
-
- for (j = 0; j <= sdo.max_subindex; j++) {
- getSdoEntry(&entry, slavePosition, -i, j);
-
- cout << " 0x" << hex << setfill('0')
- << setw(4) << sdo.sdo_index << ":"
- << setw(2) << (unsigned int) entry.sdo_entry_subindex
- << ", ";
-
- if ((d = findDataType(entry.data_type))) {
- cout << d->name;
- } else {
- cout << "type " << setw(4) << entry.data_type;
- }
-
- cout << ", " << dec << entry.bit_length << " bit, \""
- << entry.description << "\"" << endl;
- }
- }
-}
-
-/****************************************************************************/
-
-struct SlaveInfo {
- string pos;
- string alias;
- string relPos;
- string state;
- string flag;
- string name;
-};
-
-void Master::listSlaves(int slavePosition)
-{
- unsigned int numSlaves, i;
- ec_ioctl_slave_t slave;
- uint16_t lastAlias, aliasIndex;
- SlaveInfo slaveInfo;
- typedef list<SlaveInfo> SlaveInfoList;
- SlaveInfoList slaveInfoList;
- SlaveInfoList::const_iterator iter;
- stringstream str;
- unsigned int maxPosWidth = 0, maxAliasWidth = 0,
- maxRelPosWidth = 0, maxStateWidth = 0;
-
- open(Read);
-
- numSlaves = slaveCount();
-
- lastAlias = 0;
- aliasIndex = 0;
- for (i = 0; i < numSlaves; i++) {
- getSlave(&slave, i);
-
- if (slave.alias) {
- lastAlias = slave.alias;
- aliasIndex = 0;
- }
-
- if (slavePosition == -1 || i == (unsigned int) slavePosition) {
- str << dec << i;
- slaveInfo.pos = str.str();
- str.clear();
- str.str("");
-
- str << lastAlias;
- slaveInfo.alias = str.str();
- str.str("");
-
- str << aliasIndex;
- slaveInfo.relPos = str.str();
- str.str("");
-
- slaveInfo.state = slaveState(slave.state);
- slaveInfo.flag = (slave.error_flag ? 'E' : '+');
-
- if (strlen(slave.name)) {
- slaveInfo.name = slave.name;
- } else {
- str << "0x" << hex << setfill('0')
- << setw(8) << slave.vendor_id << ":0x"
- << setw(8) << slave.product_code;
- slaveInfo.name = str.str();
- str.str("");
- }
-
-
- slaveInfoList.push_back(slaveInfo);
-
- if (slaveInfo.pos.length() > maxPosWidth)
- maxPosWidth = slaveInfo.pos.length();
- if (slaveInfo.alias.length() > maxAliasWidth)
- maxAliasWidth = slaveInfo.alias.length();
- if (slaveInfo.relPos.length() > maxRelPosWidth)
- maxRelPosWidth = slaveInfo.relPos.length();
- if (slaveInfo.state.length() > maxStateWidth)
- maxStateWidth = slaveInfo.state.length();
- }
-
- aliasIndex++;
- }
-
- for (iter = slaveInfoList.begin(); iter != slaveInfoList.end(); iter++) {
- cout << setfill(' ') << right
- << setw(maxPosWidth) << iter->pos << " "
- << setw(maxAliasWidth) << iter->alias
- << ":" << left
- << setw(maxRelPosWidth) << iter->relPos << " "
- << setw(maxStateWidth) << iter->state << " "
- << iter->flag << " "
- << iter->name << endl;
- }
-}
-
-/****************************************************************************/
-
-void Master::showSlave(uint16_t slavePosition)
-{
- ec_ioctl_slave_t slave;
- list<string> protoList;
- list<string>::const_iterator protoIter;
-
- getSlave(&slave, slavePosition);
-
- cout << "=== Slave " << dec << slavePosition << " ===" << endl;
-
- if (slave.alias)
- cout << "Alias: " << slave.alias << endl;
-
- cout
- << "State: " << slaveState(slave.state) << endl
- << "Flag: " << (slave.error_flag ? 'E' : '+') << endl
- << "Identity:" << endl
- << " Vendor Id: 0x"
- << hex << setfill('0')
- << setw(8) << slave.vendor_id << endl
- << " Product code: 0x"
- << setw(8) << slave.product_code << endl
- << " Revision number: 0x"
- << setw(8) << slave.revision_number << endl
- << " Serial number: 0x"
- << setw(8) << slave.serial_number << endl;
-
- if (slave.mailbox_protocols) {
- cout << "Mailboxes:" << endl
- << " RX: 0x"
- << hex << setw(4) << slave.rx_mailbox_offset << "/"
- << dec << slave.rx_mailbox_size
- << ", TX: 0x"
- << hex << setw(4) << slave.tx_mailbox_offset << "/"
- << dec << slave.tx_mailbox_size << endl
- << " Supported protocols: ";
-
- if (slave.mailbox_protocols & EC_MBOX_AOE) {
- protoList.push_back("AoE");
- }
- if (slave.mailbox_protocols & EC_MBOX_EOE) {
- protoList.push_back("EoE");
- }
- if (slave.mailbox_protocols & EC_MBOX_COE) {
- protoList.push_back("CoE");
- }
- if (slave.mailbox_protocols & EC_MBOX_FOE) {
- protoList.push_back("FoE");
- }
- if (slave.mailbox_protocols & EC_MBOX_SOE) {
- protoList.push_back("SoE");
- }
- if (slave.mailbox_protocols & EC_MBOX_VOE) {
- protoList.push_back("VoE");
- }
-
- for (protoIter = protoList.begin(); protoIter != protoList.end();
- protoIter++) {
- if (protoIter != protoList.begin())
- cout << ", ";
- cout << *protoIter;
- }
- cout << endl;
- }
-
- if (slave.has_general_category) {
- cout << "General:" << endl
- << " Group: " << slave.group << endl
- << " Image name: " << slave.image << endl
- << " Order number: " << slave.order << endl
- << " Device name: " << slave.name << endl;
-
- if (slave.mailbox_protocols & EC_MBOX_COE) {
- cout << " CoE details:" << endl
- << " Enable Sdo: "
- << (slave.coe_details.enable_sdo ? "yes" : "no") << endl
- << " Enable Sdo Info: "
- << (slave.coe_details.enable_sdo_info ? "yes" : "no") << endl
- << " Enable Pdo Assign: "
- << (slave.coe_details.enable_pdo_assign
- ? "yes" : "no") << endl
- << " Enable Pdo Configuration: "
- << (slave.coe_details.enable_pdo_configuration
- ? "yes" : "no") << endl
- << " Enable Upload at startup: "
- << (slave.coe_details.enable_upload_at_startup
- ? "yes" : "no") << endl
- << " Enable Sdo complete access: "
- << (slave.coe_details.enable_sdo_complete_access
- ? "yes" : "no") << endl;
- }
-
- cout << " Flags:" << endl
- << " Enable SafeOp: "
- << (slave.general_flags.enable_safeop ? "yes" : "no") << endl
- << " Enable notLRW: "
- << (slave.general_flags.enable_not_lrw ? "yes" : "no") << endl
- << " Current consumption: "
- << dec << slave.current_on_ebus << " mA" << endl;
- }
-}
-
-/****************************************************************************/
-
-void Master::generateSlaveXml(uint16_t slavePosition)
-{
- ec_ioctl_slave_t slave;
- ec_ioctl_slave_sync_t sync;
- ec_ioctl_slave_sync_pdo_t pdo;
- string pdoType;
- ec_ioctl_slave_sync_pdo_entry_t entry;
- unsigned int i, j, k;
-
- getSlave(&slave, slavePosition);
-
- cout
- << "<?xml version=\"1.0\" ?>" << endl
- << " <EtherCATInfo>" << endl
- << " <!-- Slave " << slave.position << " -->" << endl
- << " <Vendor>" << endl
- << " <Id>" << slave.vendor_id << "</Id>" << endl
- << " </Vendor>" << endl
- << " <Descriptions>" << endl
- << " <Devices>" << endl
- << " <Device>" << endl
- << " <Type ProductCode=\"#x"
- << hex << setfill('0') << setw(8) << slave.product_code
- << "\" RevisionNo=\"#x"
- << hex << setfill('0') << setw(8) << slave.revision_number
- << "\">" << slave.order << "</Type>" << endl;
-
- if (strlen(slave.name)) {
- cout
- << " <Name><![CDATA["
- << slave.name
- << "]]></Name>" << endl;
- }
-
- for (i = 0; i < slave.sync_count; i++) {
- getSync(&sync, slavePosition, i);
-
- cout
- << " <Sm Enable=\"" << dec << (unsigned int) sync.enable
- << "\" StartAddress=\"" << sync.physical_start_address
- << "\" ControlByte=\"" << (unsigned int) sync.control_register
- << "\" DefaultSize=\"" << sync.default_size
- << "\" />" << endl;
- }
-
- for (i = 0; i < slave.sync_count; i++) {
- getSync(&sync, slavePosition, i);
-
- for (j = 0; j < sync.pdo_count; j++) {
- getPdo(&pdo, slavePosition, i, j);
- pdoType = (sync.control_register & 0x04 ? "R" : "T");
- pdoType += "xPdo";
-
- cout
- << " <" << pdoType
- << " Sm=\"" << i << "\" Fixed=\"1\" Mandatory=\"1\">" << endl
- << " <Index>#x"
- << hex << setfill('0') << setw(4) << pdo.index
- << "</Index>" << endl
- << " <Name>" << pdo.name << "</Name>" << endl;
-
- for (k = 0; k < pdo.entry_count; k++) {
- getPdoEntry(&entry, slavePosition, i, j, k);
-
- cout
- << " <Entry>" << endl
- << " <Index>#x"
- << hex << setfill('0') << setw(4) << entry.index
- << "</Index>" << endl;
- if (entry.index)
- cout
- << " <SubIndex>"
- << dec << (unsigned int) entry.subindex
- << "</SubIndex>" << endl;
-
- cout
- << " <BitLen>"
- << dec << (unsigned int) entry.bit_length
- << "</BitLen>" << endl;
-
- if (entry.index) {
- cout
- << " <Name>" << entry.name
- << "</Name>" << endl
- << " <DataType>";
-
- if (entry.bit_length == 1) {
- cout << "BOOL";
- } else if (!(entry.bit_length % 8)) {
- if (entry.bit_length <= 64)
- cout << "UINT" << (unsigned int) entry.bit_length;
- else
- cout << "STRING("
- << (unsigned int) (entry.bit_length / 8)
- << ")";
- } else {
- cerr << "Invalid bit length "
- << (unsigned int) entry.bit_length << endl;
- }
-
- cout << "</DataType>" << endl;
- }
-
- cout << " </Entry>" << endl;
- }
-
- cout
- << " </" << pdoType << ">" << endl;
- }
- }
-
- cout
- << " </Device>" << endl
- << " </Devices>" << endl
- << " </Descriptions>" << endl
- << "</EtherCATInfo>" << endl;
-}
-
-/****************************************************************************/
-
-unsigned int Master::slaveCount()
-{
- ec_ioctl_master_t data;
-
- getMaster(&data);
- return data.slave_count;
-}
-
-/****************************************************************************/
-
-void Master::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());
- }
-}
-
-/****************************************************************************/
-
-void Master::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());
- }
-}
-
-/****************************************************************************/
-
-void Master::getConfigPdo(
- ec_ioctl_config_pdo_t *data,
- unsigned int index,
- uint8_t sync_index,
- uint16_t pdo_pos
- )
-{
- data->config_index = index;
- data->sync_index = sync_index;
- data->pdo_pos = pdo_pos;
-
- if (ioctl(fd, EC_IOCTL_CONFIG_PDO, data) < 0) {
- stringstream err;
- err << "Failed to get slave config Pdo: " << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::getConfigPdoEntry(
- ec_ioctl_config_pdo_entry_t *data,
- unsigned int index,
- uint8_t sync_index,
- uint16_t pdo_pos,
- uint8_t entry_pos
- )
-{
- data->config_index = index;
- data->sync_index = sync_index;
- data->pdo_pos = pdo_pos;
- data->entry_pos = entry_pos;
-
- 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());
- }
-}
-
-/****************************************************************************/
-
-void Master::getConfigSdo(
- ec_ioctl_config_sdo_t *data,
- unsigned int index,
- unsigned int sdo_pos
- )
-{
- data->config_index = index;
- data->sdo_pos = sdo_pos;
-
- if (ioctl(fd, EC_IOCTL_CONFIG_SDO, data) < 0) {
- stringstream err;
- err << "Failed to get slave config Sdo: " << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::getDomain(ec_ioctl_domain_t *data, unsigned int index)
-{
- data->index = index;
-
- if (ioctl(fd, EC_IOCTL_DOMAIN, data)) {
- stringstream err;
- err << "Failed to get domain: ";
- if (errno == EINVAL)
- err << "Domain " << index << " does not exist!";
- else
- err << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::getData(ec_ioctl_domain_data_t *data, unsigned int domainIndex,
- unsigned int dataSize, unsigned char *mem)
-{
- data->domain_index = domainIndex;
- data->data_size = dataSize;
- data->target = mem;
-
- if (ioctl(fd, EC_IOCTL_DOMAIN_DATA, data) < 0) {
- stringstream err;
- err << "Failed to get domain data: " << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex)
-{
- slave->position = slaveIndex;
-
- if (ioctl(fd, EC_IOCTL_SLAVE, slave)) {
- stringstream err;
- err << "Failed to get slave: ";
- if (errno == EINVAL)
- err << "Slave " << slaveIndex << " does not exist!";
- else
- err << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::getFmmu(
- ec_ioctl_domain_fmmu_t *fmmu,
- unsigned int domainIndex,
- unsigned int fmmuIndex
- )
-{
- fmmu->domain_index = domainIndex;
- fmmu->fmmu_index = fmmuIndex;
-
- if (ioctl(fd, EC_IOCTL_DOMAIN_FMMU, fmmu)) {
- stringstream err;
- err << "Failed to get domain FMMU: ";
- if (errno == EINVAL)
- err << "Either domain " << domainIndex << " does not exist, "
- << "or it contains less than " << (unsigned int) fmmuIndex + 1
- << " FMMus!";
- else
- err << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::getSync(
- ec_ioctl_slave_sync_t *sync,
- uint16_t slaveIndex,
- uint8_t syncIndex
- )
-{
- sync->slave_position = slaveIndex;
- sync->sync_index = syncIndex;
-
- if (ioctl(fd, EC_IOCTL_SLAVE_SYNC, sync)) {
- stringstream err;
- err << "Failed to get sync manager: ";
- if (errno == EINVAL)
- err << "Either slave " << slaveIndex << " does not exist, "
- << "or it contains less than " << (unsigned int) syncIndex + 1
- << " sync managers!";
- else
- err << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::getPdo(
- ec_ioctl_slave_sync_pdo_t *pdo,
- uint16_t slaveIndex,
- uint8_t syncIndex,
- uint8_t pdoPos
- )
-{
- pdo->slave_position = slaveIndex;
- pdo->sync_index = syncIndex;
- pdo->pdo_pos = pdoPos;
-
- if (ioctl(fd, EC_IOCTL_SLAVE_SYNC_PDO, pdo)) {
- stringstream err;
- err << "Failed to get Pdo: ";
- if (errno == EINVAL)
- err << "Either slave " << slaveIndex << " does not exist, "
- << "or it contains less than " << (unsigned int) syncIndex + 1
- << " sync managers, or sync manager "
- << (unsigned int) syncIndex << " contains less than "
- << pdoPos + 1 << " Pdos!" << endl;
- else
- err << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::getPdoEntry(
- ec_ioctl_slave_sync_pdo_entry_t *entry,
- uint16_t slaveIndex,
- uint8_t syncIndex,
- uint8_t pdoPos,
- uint8_t entryPos
- )
-{
- entry->slave_position = slaveIndex;
- entry->sync_index = syncIndex;
- entry->pdo_pos = pdoPos;
- entry->entry_pos = entryPos;
-
- if (ioctl(fd, EC_IOCTL_SLAVE_SYNC_PDO_ENTRY, entry)) {
- stringstream err;
- err << "Failed to get Pdo entry: ";
- if (errno == EINVAL)
- err << "Either slave " << slaveIndex << " does not exist, "
- << "or it contains less than " << (unsigned int) syncIndex + 1
- << " sync managers, or sync manager "
- << (unsigned int) syncIndex << " contains less than "
- << pdoPos + 1 << " Pdos, or the Pdo at position " << pdoPos
- << " contains less than " << (unsigned int) entryPos + 1
- << " entries!" << endl;
- else
- err << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::getSdo(
- ec_ioctl_slave_sdo_t *sdo,
- uint16_t slaveIndex,
- uint16_t sdoPosition
- )
-{
- sdo->slave_position = slaveIndex;
- sdo->sdo_position = sdoPosition;
-
- if (ioctl(fd, EC_IOCTL_SLAVE_SDO, sdo)) {
- stringstream err;
- err << "Failed to get Sdo: ";
- if (errno == EINVAL)
- err << "Either slave " << slaveIndex << " does not exist, "
- << "or it contains less than " << sdoPosition + 1 << " Sdos!"
- << endl;
- else
- err << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::getSdoEntry(
- ec_ioctl_slave_sdo_entry_t *entry,
- uint16_t slaveIndex,
- int sdoSpec,
- uint8_t entrySubindex
- )
-{
- entry->slave_position = slaveIndex;
- entry->sdo_spec = sdoSpec;
- entry->sdo_entry_subindex = entrySubindex;
-
- if (ioctl(fd, EC_IOCTL_SLAVE_SDO_ENTRY, entry)) {
- stringstream err;
- err << "Failed to get Sdo entry: ";
- err << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-void Master::requestState(
- uint16_t slavePosition,
- uint8_t state
- )
-{
- ec_ioctl_slave_state_t data;
-
- data.slave_position = slavePosition;
- data.requested_state = state;
-
- if (ioctl(fd, EC_IOCTL_SLAVE_STATE, &data)) {
- stringstream err;
- err << "Failed to request slave state: ";
- if (errno == EINVAL)
- err << "Slave " << slavePosition << " does not exist!";
- else
- err << strerror(errno);
- throw MasterException(err.str());
- }
-}
-
-/****************************************************************************/
-
-string Master::slaveState(uint8_t state)
-{
- switch (state) {
- case 1: return "INIT";
- case 2: return "PREOP";
- case 4: return "SAFEOP";
- case 8: return "OP";
- default: return "???";
- }
-}
-
-/****************************************************************************/
-
-void Master::printRawData(
- const uint8_t *data,
- unsigned int size)
-{
- cout << hex << setfill('0');
- while (size--) {
- cout << "0x" << setw(2) << (unsigned int) *data++;
- if (size)
- cout << " ";
- }
- cout << endl;
-}
-
-/*****************************************************************************/
-
-/**
- * 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;
-}
-
-/*****************************************************************************/