From 6929f2f71813df1ae509a3cf08dea2bf8605ea12 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Tue, 30 Nov 2010 15:24:21 +0100 Subject: [PATCH 1/5] Added ecrt_master_reset() method. --- include/ecrt.h | 12 +++++++++ lib/master.c | 9 +++++++ master/cdev.c | 23 +++++++++++++++++ master/ioctl.h | 65 +++++++++++++++++++++++++------------------------ master/master.c | 14 +++++++++++ 5 files changed, 91 insertions(+), 32 deletions(-) diff --git a/include/ecrt.h b/include/ecrt.h index d3b82731..2cf1dbe3 100644 --- a/include/ecrt.h +++ b/include/ecrt.h @@ -78,6 +78,7 @@ * - Added ecrt_slave_config_idn() method for storing SoE IDN configurations, * and ecrt_master_read_idn() and ecrt_master_write_idn() to read/write IDNs * ad-hoc via the user-space library. + * - Added ecrt_master_reset() to initiate retrying to configure slaves. * * @{ */ @@ -859,6 +860,17 @@ uint32_t ecrt_master_sync_monitor_process( ec_master_t *master /**< EtherCAT master. */ ); +/** Retry configuring slaves. + * + * Via this method, the application can tell the master to bring all slaves to + * OP state. In general, this is not necessary, because it is automatically + * done by the master. But with special slaves, that can be reconfigured by + * the vendor during runtime, it can be useful. + */ +void ecrt_master_reset( + ec_master_t *master /**< EtherCAT master. */ + ); + /****************************************************************************** * Slave configuration methods *****************************************************************************/ diff --git a/lib/master.c b/lib/master.c index 3ad0b063..20b082f1 100644 --- a/lib/master.c +++ b/lib/master.c @@ -572,3 +572,12 @@ uint32_t ecrt_master_sync_monitor_process(ec_master_t *master) } /*****************************************************************************/ + +void ecrt_master_reset(ec_master_t *master) +{ + if (ioctl(master->fd, EC_IOCTL_RESET, NULL) == -1) { + fprintf(stderr, "Failed to reset master: %s\n", strerror(errno)); + } +} + +/*****************************************************************************/ diff --git a/master/cdev.c b/master/cdev.c index faad92ce..6ed7f883 100644 --- a/master/cdev.c +++ b/master/cdev.c @@ -1992,6 +1992,25 @@ int ec_cdev_ioctl_sync_mon_process( /*****************************************************************************/ +/** Reset configuration. + */ +int ec_cdev_ioctl_reset( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + if (unlikely(!priv->requested)) + return -EPERM; + + down(&master->master_sem); + ecrt_master_reset(master); + up(&master->master_sem); + return 0; +} + +/*****************************************************************************/ + /** Configure a sync manager. */ int ec_cdev_ioctl_sc_sync( @@ -3671,6 +3690,10 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; return ec_cdev_ioctl_sync_mon_process(master, arg, priv); + case EC_IOCTL_RESET: + if (!(filp->f_mode & FMODE_WRITE)) + return -EPERM; + return ec_cdev_ioctl_reset(master, arg, priv); case EC_IOCTL_SC_SYNC: if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; diff --git a/master/ioctl.h b/master/ioctl.h index c2f69500..d4082a23 100644 --- a/master/ioctl.h +++ b/master/ioctl.h @@ -56,7 +56,7 @@ * * Increment this when changing the ioctl interface! */ -#define EC_IOCTL_VERSION_MAGIC 10 +#define EC_IOCTL_VERSION_MAGIC 11 // Command-line tool #define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t) @@ -95,7 +95,7 @@ // Application interface #define EC_IOCTL_REQUEST EC_IO(0x1e) #define EC_IOCTL_CREATE_DOMAIN EC_IO(0x1f) -#define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x10, ec_ioctl_config_t) +#define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x20, ec_ioctl_config_t) #define EC_IOCTL_ACTIVATE EC_IOR(0x21, size_t) #define EC_IOCTL_DEACTIVATE EC_IO(0x22) #define EC_IOCTL_SEND EC_IO(0x23) @@ -106,36 +106,37 @@ #define EC_IOCTL_SYNC_SLAVES EC_IO(0x28) #define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x29) #define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x2a, uint32_t) -#define EC_IOCTL_SC_SYNC EC_IOW(0x2b, ec_ioctl_config_t) -#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x2c, ec_ioctl_config_t) -#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x2d, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x2e, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x2f, ec_ioctl_add_pdo_entry_t) -#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x20, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x21, ec_ioctl_reg_pdo_entry_t) -#define EC_IOCTL_SC_DC EC_IOW(0x32, ec_ioctl_config_t) -#define EC_IOCTL_SC_SDO EC_IOW(0x33, ec_ioctl_sc_sdo_t) -#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x34, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SC_VOE EC_IOWR(0x35, ec_ioctl_voe_t) -#define EC_IOCTL_SC_STATE EC_IOWR(0x36, ec_ioctl_sc_state_t) -#define EC_IOCTL_SC_IDN EC_IOW(0x37, ec_ioctl_sc_idn_t) -#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x38) -#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x39) -#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x3a) -#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x3b, ec_ioctl_domain_state_t) -#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x3c, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x3d, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x3e, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x3f, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x30, ec_ioctl_sdo_request_t) -#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x41, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x42, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ EC_IOW(0x43, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x44, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_WRITE EC_IOWR(0x45, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_EXEC EC_IOWR(0x46, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_DATA EC_IOWR(0x47, ec_ioctl_voe_t) -#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x48, size_t) +#define EC_IOCTL_RESET EC_IO(0x2b) +#define EC_IOCTL_SC_SYNC EC_IOW(0x2c, ec_ioctl_config_t) +#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x2d, ec_ioctl_config_t) +#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x2e, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x2f, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x30, ec_ioctl_add_pdo_entry_t) +#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x31, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x32, ec_ioctl_reg_pdo_entry_t) +#define EC_IOCTL_SC_DC EC_IOW(0x33, ec_ioctl_config_t) +#define EC_IOCTL_SC_SDO EC_IOW(0x34, ec_ioctl_sc_sdo_t) +#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x35, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SC_VOE EC_IOWR(0x36, ec_ioctl_voe_t) +#define EC_IOCTL_SC_STATE EC_IOWR(0x37, ec_ioctl_sc_state_t) +#define EC_IOCTL_SC_IDN EC_IOW(0x38, ec_ioctl_sc_idn_t) +#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x39) +#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x3a) +#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x3b) +#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x3c, ec_ioctl_domain_state_t) +#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x3d, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x3e, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x3f, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x40, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x41, ec_ioctl_sdo_request_t) +#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x42, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x43, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ EC_IOW(0x44, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x45, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_WRITE EC_IOWR(0x46, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_EXEC EC_IOWR(0x47, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_DATA EC_IOWR(0x48, ec_ioctl_voe_t) +#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x49, size_t) /*****************************************************************************/ diff --git a/master/master.c b/master/master.c index 0bbe5b76..3e7708fd 100644 --- a/master/master.c +++ b/master/master.c @@ -2501,6 +2501,19 @@ int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position, /*****************************************************************************/ +void ecrt_master_reset(ec_master_t *master) +{ + ec_slave_config_t *sc; + + list_for_each_entry(sc, &master->configs, list) { + if (sc->slave) { + ec_slave_request_state(sc->slave, EC_SLAVE_STATE_OP); + } + } +} + +/*****************************************************************************/ + /** \cond */ EXPORT_SYMBOL(ecrt_master_create_domain); @@ -2521,6 +2534,7 @@ EXPORT_SYMBOL(ecrt_master_sync_monitor_queue); EXPORT_SYMBOL(ecrt_master_sync_monitor_process); EXPORT_SYMBOL(ecrt_master_write_idn); EXPORT_SYMBOL(ecrt_master_read_idn); +EXPORT_SYMBOL(ecrt_master_reset); /** \endcond */ From bf144c593c5adc9a58f621bb5a019c11a3646d13 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Tue, 14 Dec 2010 21:58:53 +0100 Subject: [PATCH 2/5] Implemented ranges for slaves, configs and domains. --- TODO | 1 - tool/Command.cpp | 255 ++++++++++++++++++++++++++------------ tool/Command.h | 43 ++----- tool/NumberListParser.cpp | 30 +++-- tool/NumberListParser.h | 12 +- tool/main.cpp | 46 ++----- 6 files changed, 221 insertions(+), 166 deletions(-) diff --git a/TODO b/TODO index 66341b7a..b0d60341 100644 --- a/TODO +++ b/TODO @@ -15,7 +15,6 @@ Version 1.5.0: - Add native drivers from 2.6.24 up to 2.6.31. * ethercat tool: - Output error after usage. - - Implement ranges for slaves and domains. * Fix casting away constness during expected WC calculation. * Include SoE drive_no in ethercat tool. diff --git a/tool/Command.cpp b/tool/Command.cpp index 12d35c68..d2089454 100644 --- a/tool/Command.cpp +++ b/tool/Command.cpp @@ -29,6 +29,9 @@ * ****************************************************************************/ +#include +using namespace std; + #include "Command.h" #include "MasterDevice.h" #include "NumberListParser.h" @@ -38,13 +41,89 @@ class MasterIndexParser: public NumberListParser { - unsigned int getMax() - { - MasterDevice dev; - dev.setIndex(0U); - dev.open(MasterDevice::Read); - return dev.getMasterCount() - 1; - }; + protected: + int getMax() { + MasterDevice dev; + dev.setIndex(0U); + dev.open(MasterDevice::Read); + return (int) dev.getMasterCount() - 1; + }; +}; + +/*****************************************************************************/ + +class SlaveAliasParser: + public NumberListParser +{ + public: + SlaveAliasParser(ec_ioctl_master_t &master, MasterDevice &dev): + master(master), dev(dev) {} + + protected: + int getMax() { + unsigned int i; + + uint16_t maxAlias = 0; + for (i = 0; i < master.slave_count; i++) { + ec_ioctl_slave_t slave; + dev.getSlave(&slave, i); + if (slave.alias > maxAlias) { + maxAlias = slave.alias; + } + } + return maxAlias ? maxAlias : -1; + }; + + private: + ec_ioctl_master_t &master; + MasterDevice &dev; +}; + +/*****************************************************************************/ + +class ConfigAliasParser: + public NumberListParser +{ + public: + ConfigAliasParser(ec_ioctl_master_t &master, MasterDevice &dev): + master(master), dev(dev) {} + + protected: + int getMax() { + unsigned int i; + + uint16_t maxAlias = 0; + for (i = 0; i < master.config_count; i++) { + ec_ioctl_config_t config; + dev.getConfig(&config, i); + if (config.alias > maxAlias) { + maxAlias = config.alias; + } + } + return maxAlias ? maxAlias : -1; + }; + + private: + ec_ioctl_master_t &master; + MasterDevice &dev; +}; + +/*****************************************************************************/ + +class PositionParser: + public NumberListParser +{ + public: + PositionParser(unsigned int count): + count(count) {} + + protected: + int getMax() { + return count - 1; + }; + + private: + const unsigned int count; }; /*****************************************************************************/ @@ -78,23 +157,23 @@ void Command::setVerbosity(Verbosity v) /*****************************************************************************/ -void Command::setAlias(int a) +void Command::setAliases(const string &a) { - alias = a; + aliases = a; }; /*****************************************************************************/ -void Command::setPosition(int p) +void Command::setPositions(const string &p) { - position = p; + positions = p; }; /*****************************************************************************/ -void Command::setDomain(int d) +void Command::setDomains(const string &d) { - domain = d; + domains = d; }; /*****************************************************************************/ @@ -227,51 +306,59 @@ unsigned int Command::getSingleMasterIndex() const Command::SlaveList Command::selectedSlaves(MasterDevice &m) { ec_ioctl_master_t master; - unsigned int i, aliasIndex; - uint16_t lastAlias; + unsigned int i; ec_ioctl_slave_t slave; SlaveList list; m.getMaster(&master); - if (alias == -1) { // no alias given - if (position == -1) { // no alias and position given - // all items - for (i = 0; i < master.slave_count; i++) { - m.getSlave(&slave, i); - list.push_back(slave); - } - } else { // no alias, but position given - // one item by position - m.getSlave(&slave, position); + if (aliases == "-") { // no alias given + PositionParser pp(master.slave_count); + NumberListParser::List posList = pp.parse(positions.c_str()); + NumberListParser::List::const_iterator pi; + for (pi = posList.begin(); pi != posList.end(); pi++) { + m.getSlave(&slave, *pi); list.push_back(slave); } - } else { // alias given - if (position == -1) { // alias, but no position given - // take all items with a given alias - lastAlias = 0; + } else { // aliases given + SlaveAliasParser ap(master, m); + NumberListParser::List aliasList = ap.parse(aliases.c_str()); + NumberListParser::List::const_iterator ai; + + for (ai = aliasList.begin(); ai != aliasList.end(); ai++) { + + // gather slaves with that alias (and following) + uint16_t lastAlias = 0; + vector aliasSlaves; + for (i = 0; i < master.slave_count; i++) { m.getSlave(&slave, i); if (slave.alias) { + if (lastAlias && lastAlias == *ai && slave.alias != *ai) { + // ignore multiple ocurrences of the same alias to + // assure consistency for the position argument + break; + } lastAlias = slave.alias; } - if (lastAlias == (uint16_t) alias) { - list.push_back(slave); + if (lastAlias == *ai) { + aliasSlaves.push_back(slave); } } - } else { // alias and position given - lastAlias = 0; - aliasIndex = 0; - for (i = 0; i < master.slave_count; i++) { - m.getSlave(&slave, i); - if (slave.alias && slave.alias == (uint16_t) alias) { - lastAlias = slave.alias; - aliasIndex = 0; + + PositionParser pp(aliasSlaves.size()); + NumberListParser::List posList = pp.parse(positions.c_str()); + NumberListParser::List::const_iterator pi; + + for (pi = posList.begin(); pi != posList.end(); pi++) { + if (*pi < aliasSlaves.size()) { + list.push_back(aliasSlaves[*pi]); + } else { + stringstream err; + err << "Warning: Slave " << *ai << ":" << *pi + << " does not exist on master " << m.getIndex(); + throwCommandException(err); } - if (lastAlias && aliasIndex == (unsigned int) position) { - list.push_back(slave); - } - aliasIndex++; } } } @@ -302,37 +389,50 @@ Command::ConfigList Command::selectedConfigs(MasterDevice &m) m.getMaster(&master); - if (alias == -1) { // no alias given - if (position == -1) { // no alias and position given - // all items - for (i = 0; i < master.config_count; i++) { - m.getConfig(&config, i); - list.push_back(config); - } - } else { // no alias, but position given - for (i = 0; i < master.config_count; i++) { - m.getConfig(&config, i); - if (!config.alias && config.position == position) { - list.push_back(config); - break; // there can be at most one matching - } - } + if (aliases == "-") { // no alias given + PositionParser pp(master.config_count); + NumberListParser::List posList = pp.parse(positions.c_str()); + NumberListParser::List::const_iterator pi; + for (pi = posList.begin(); pi != posList.end(); pi++) { + m.getConfig(&config, *pi); // FIXME use sorted list + list.push_back(config); } } else { // alias given - if (position == -1) { // alias, but no position given - // take all items with a given alias + ConfigAliasParser ap(master, m); + NumberListParser::List aliasList = ap.parse(aliases.c_str()); + NumberListParser::List::const_iterator ai; + + for (ai = aliasList.begin(); ai != aliasList.end(); ai++) { + + // gather configs with that alias + map aliasConfigs; + + int maxPos = -1; for (i = 0; i < master.config_count; i++) { m.getConfig(&config, i); - if (config.alias == alias) { - list.push_back(config); + if (config.alias == *ai) { + aliasConfigs[config.position] = config; + if (config.position > maxPos) { + maxPos = config.position; + } } } - } else { // alias and position given - for (i = 0; i < master.config_count; i++) { - m.getConfig(&config, i); - if (config.alias == alias && config.position == position) { - list.push_back(config); - break; // there can be at most one matching + + PositionParser pp(maxPos + 1); + NumberListParser::List posList = pp.parse(positions.c_str()); + NumberListParser::List::const_iterator pi; + + for (pi = posList.begin(); pi != posList.end(); pi++) { + map::const_iterator ci; + ci = aliasConfigs.find(*pi); + + if (ci != aliasConfigs.end()) { + list.push_back(ci->second); + } else { + stringstream err; + err << "Warning: Config " << *ai << ":" << *pi + << " does not exist on master " << m.getIndex(); + throwCommandException(err); } } } @@ -346,21 +446,18 @@ Command::ConfigList Command::selectedConfigs(MasterDevice &m) Command::DomainList Command::selectedDomains(MasterDevice &m) { - ec_ioctl_domain_t d; + ec_ioctl_master_t master; DomainList list; - if (domain == -1) { - ec_ioctl_master_t master; - unsigned int i; + m.getMaster(&master); - m.getMaster(&master); + PositionParser pp(master.domain_count); + NumberListParser::List domList = pp.parse(domains.c_str()); + NumberListParser::List::const_iterator di; - for (i = 0; i < master.domain_count; i++) { - m.getDomain(&d, i); - list.push_back(d); - } - } else { - m.getDomain(&d, domain); + for (di = domList.begin(); di != domList.end(); di++) { + ec_ioctl_domain_t d; + m.getDomain(&d, *di); list.push_back(d); } diff --git a/tool/Command.h b/tool/Command.h index 14306c53..46d3d579 100644 --- a/tool/Command.h +++ b/tool/Command.h @@ -96,16 +96,20 @@ class Command }; void setVerbosity(Verbosity); Verbosity getVerbosity() const; - void setAlias(int); - int getAlias() const; - void setPosition(int); - int getPosition() const; - void setDomain(int); - int getDomain() const; + + void setAliases(const string &); + void setPositions(const string &); + + void setDomains(const string &); + typedef list DomainIndexList; + DomainIndexList getDomainIndices() const; + void setDataType(const string &); const string &getDataType() const; + void setForce(bool); bool getForce() const; + void setOutputFile(const string &); const string &getOutputFile() const; @@ -141,9 +145,9 @@ class Command string briefDesc; string masters; Verbosity verbosity; - int alias; - int position; - int domain; + string aliases; + string positions; + string domains; string dataType; bool force; string outputFile; @@ -174,27 +178,6 @@ inline Command::Verbosity Command::getVerbosity() const /****************************************************************************/ -inline int Command::getAlias() const -{ - return alias; -} - -/****************************************************************************/ - -inline int Command::getPosition() const -{ - return position; -} - -/****************************************************************************/ - -inline int Command::getDomain() const -{ - return domain; -} - -/****************************************************************************/ - inline const string &Command::getDataType() const { return dataType; diff --git a/tool/NumberListParser.cpp b/tool/NumberListParser.cpp index bdef69f1..33e46720 100644 --- a/tool/NumberListParser.cpp +++ b/tool/NumberListParser.cpp @@ -50,9 +50,9 @@ NumberListParser::~NumberListParser() /*****************************************************************************/ -NumberListParser::NumberList NumberListParser::parse(const char *data) +NumberListParser::List NumberListParser::parse(const char *data) { - NumberList ret; + List ret; unsigned int i = 0, size = strlen(data), firstNum = 0U, secondNum = 0U; typedef enum { SectionStart, @@ -108,18 +108,22 @@ NumberListParser::NumberList NumberListParser::parse(const char *data) case Range: if (i >= size) { - secondNum = maximum(); - NumberList r = range(firstNum, secondNum); - ret.splice(ret.end(), r); + int max = maximum(); + if (max >= 0) { + List r = range(firstNum, max); + ret.splice(ret.end(), r); + } state = Finished; } else if (isNumeric(data[i])) { secondNum = parseNumber(data, &i, size); state = SecondNumber; } else if (data[i] == ',') { + int max = maximum(); i++; - secondNum = maximum(); - NumberList r = range(firstNum, secondNum); - ret.splice(ret.end(), r); + if (max >= 0) { + List r = range(firstNum, max); + ret.splice(ret.end(), r); + } state = SectionStart; } else { stringstream err; @@ -132,12 +136,12 @@ NumberListParser::NumberList NumberListParser::parse(const char *data) case SecondNumber: if (i >= size) { - NumberList r = range(firstNum, secondNum); + List r = range(firstNum, secondNum); ret.splice(ret.end(), r); state = Finished; } else if (data[i] == ',') { i++; - NumberList r = range(firstNum, secondNum); + List r = range(firstNum, secondNum); ret.splice(ret.end(), r); state = SectionStart; } else { @@ -163,7 +167,7 @@ NumberListParser::NumberList NumberListParser::parse(const char *data) /*****************************************************************************/ -unsigned int NumberListParser::maximum() +int NumberListParser::maximum() { if (!hasMax) { max = getMax(); @@ -207,12 +211,12 @@ unsigned int NumberListParser::parseNumber( /****************************************************************************/ -NumberListParser::NumberList NumberListParser::range( +NumberListParser::List NumberListParser::range( unsigned int i, unsigned int j ) { - NumberList ret; + List ret; if (i <= j) { for (; i <= j; i++) { diff --git a/tool/NumberListParser.h b/tool/NumberListParser.h index 6cf0dd16..ec30aa67 100644 --- a/tool/NumberListParser.h +++ b/tool/NumberListParser.h @@ -38,22 +38,22 @@ class NumberListParser NumberListParser(); virtual ~NumberListParser(); - typedef list NumberList; + typedef list List; - NumberList parse(const char *); + List parse(const char *); - virtual unsigned int getMax() = 0; + virtual int getMax() = 0; private: - unsigned int max; + int max; bool hasMax; - unsigned int maximum(); + int maximum(); static bool isNumeric(char); static unsigned int parseNumber(const char *, unsigned int *, unsigned int); - static NumberList range(unsigned int, unsigned int); + static List range(unsigned int, unsigned int); }; /****************************************************************************/ diff --git a/tool/main.cpp b/tool/main.cpp index 0afa35c9..6f6948b0 100644 --- a/tool/main.cpp +++ b/tool/main.cpp @@ -77,9 +77,9 @@ Command::StringVector commandArgs; // option variables string masters = "-"; // all masters -int slavePosition = -1; -int slaveAlias = -1; -int domainIndex = -1; +string positions = "-"; // all positions +string aliases = "-"; // all aliases +string domains = "-"; // all domains string dataTypeStr; Command::Verbosity verbosity = Command::Normal; bool force = false; @@ -163,43 +163,15 @@ void getOptions(int argc, char **argv) break; case 'a': - str.clear(); - str.str(""); - str << optarg; - str >> resetiosflags(ios::basefield) // guess base from prefix - >> slaveAlias; - if (str.fail() || slaveAlias < 0 || slaveAlias > 0xFFFF) { - cerr << "Invalid slave alias " << optarg << "!" << endl - << endl << usage(); - exit(1); - } + aliases = optarg; break; case 'p': - str.clear(); - str.str(""); - str << optarg; - str >> resetiosflags(ios::basefield) // guess base from prefix - >> slavePosition; - if (str.fail() - || slavePosition < 0 || slavePosition > 0xFFFF) { - cerr << "Invalid slave position " << optarg << "!" << endl - << endl << usage(); - exit(1); - } + positions = optarg; break; case 'd': - str.clear(); - str.str(""); - str << optarg; - str >> resetiosflags(ios::basefield) // guess base from prefix - >> domainIndex; - if (str.fail() || domainIndex < 0) { - cerr << "Invalid domain index " << optarg << "!" << endl - << endl << usage(); - exit(1); - } + domains = optarg; break; case 't': @@ -331,9 +303,9 @@ int main(int argc, char **argv) try { cmd->setMasters(masters); cmd->setVerbosity(verbosity); - cmd->setAlias(slaveAlias); - cmd->setPosition(slavePosition); - cmd->setDomain(domainIndex); + cmd->setAliases(aliases); + cmd->setPositions(positions); + cmd->setDomains(domains); cmd->setDataType(dataTypeStr); cmd->setOutputFile(outputFile); cmd->setForce(force); From abfc3192323b78006ea9b44217a0cdb53b88a8ea Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Tue, 4 Jan 2011 08:36:41 +0100 Subject: [PATCH 3/5] Assume increasing ranges if second number is omitted. --- tool/NumberListParser.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tool/NumberListParser.cpp b/tool/NumberListParser.cpp index 33e46720..9744a763 100644 --- a/tool/NumberListParser.cpp +++ b/tool/NumberListParser.cpp @@ -109,7 +109,8 @@ NumberListParser::List NumberListParser::parse(const char *data) case Range: if (i >= size) { int max = maximum(); - if (max >= 0) { + // only increasing ranges if second number omitted + if (max >= 0 && firstNum <= (unsigned int) max) { List r = range(firstNum, max); ret.splice(ret.end(), r); } From f83d10d66b1dccec239e20ed9aa266b9d5a72a40 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Tue, 4 Jan 2011 08:39:51 +0100 Subject: [PATCH 4/5] Fixed / improved config selection. --- tool/Command.cpp | 111 +++++++++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/tool/Command.cpp b/tool/Command.cpp index d2089454..4e68bf34 100644 --- a/tool/Command.cpp +++ b/tool/Command.cpp @@ -38,6 +38,11 @@ using namespace std; /*****************************************************************************/ +typedef map AliasMap; +typedef map ConfigMap; + +/*****************************************************************************/ + class MasterIndexParser: public NumberListParser { @@ -85,27 +90,14 @@ class ConfigAliasParser: public NumberListParser { public: - ConfigAliasParser(ec_ioctl_master_t &master, MasterDevice &dev): - master(master), dev(dev) {} + ConfigAliasParser(unsigned int maxAlias): + maxAlias(maxAlias) {} protected: - int getMax() { - unsigned int i; - - uint16_t maxAlias = 0; - for (i = 0; i < master.config_count; i++) { - ec_ioctl_config_t config; - dev.getConfig(&config, i); - if (config.alias > maxAlias) { - maxAlias = config.alias; - } - } - return maxAlias ? maxAlias : -1; - }; + int getMax() { return maxAlias; }; private: - ec_ioctl_master_t &master; - MasterDevice &dev; + unsigned int maxAlias; }; /*****************************************************************************/ @@ -128,6 +120,33 @@ class PositionParser: /*****************************************************************************/ +class AliasPositionParser: + public NumberListParser +{ + public: + AliasPositionParser(const AliasMap &aliasMap): + aliasMap(aliasMap) {} + + protected: + int getMax() { + AliasMap::const_iterator i; + int maxPos = -1; + + for (i = aliasMap.begin(); i != aliasMap.end(); i++) { + if (i->first > maxPos) { + maxPos = i->first; + } + } + + return maxPos; + }; + + private: + const AliasMap &aliasMap; +}; + +/*****************************************************************************/ + Command::Command(const string &name, const string &briefDesc): name(name), briefDesc(briefDesc), @@ -293,11 +312,13 @@ Command::MasterIndexList Command::getMasterIndices() const unsigned int Command::getSingleMasterIndex() const { MasterIndexList masterIndices = getMasterIndices(); + if (masterIndices.size() != 1) { stringstream err; err << getName() << " requires to select a single master!"; throwInvalidUsageException(err); } + return masterIndices.front(); } @@ -316,6 +337,7 @@ Command::SlaveList Command::selectedSlaves(MasterDevice &m) PositionParser pp(master.slave_count); NumberListParser::List posList = pp.parse(positions.c_str()); NumberListParser::List::const_iterator pi; + for (pi = posList.begin(); pi != posList.end(); pi++) { m.getSlave(&slave, *pi); list.push_back(slave); @@ -389,50 +411,47 @@ Command::ConfigList Command::selectedConfigs(MasterDevice &m) m.getMaster(&master); - if (aliases == "-") { // no alias given - PositionParser pp(master.config_count); - NumberListParser::List posList = pp.parse(positions.c_str()); - NumberListParser::List::const_iterator pi; - for (pi = posList.begin(); pi != posList.end(); pi++) { - m.getConfig(&config, *pi); // FIXME use sorted list + if (aliases == "-" && positions == "-") { // shortcut + for (i = 0; i < master.config_count; i++) { + m.getConfig(&config, i); list.push_back(config); } - } else { // alias given - ConfigAliasParser ap(master, m); + } else { // take the long way home... + ConfigMap configs; + uint16_t maxAlias = 0; + + // fill cascaded map structure with all configs + for (i = 0; i < master.config_count; i++) { + m.getConfig(&config, i); + AliasMap &aliasMap = configs[config.alias]; + aliasMap[config.position] = config; + if (config.alias > maxAlias) { + maxAlias = config.alias; + } + } + + ConfigAliasParser ap(maxAlias); NumberListParser::List aliasList = ap.parse(aliases.c_str()); NumberListParser::List::const_iterator ai; for (ai = aliasList.begin(); ai != aliasList.end(); ai++) { - // gather configs with that alias - map aliasConfigs; - - int maxPos = -1; - for (i = 0; i < master.config_count; i++) { - m.getConfig(&config, i); - if (config.alias == *ai) { - aliasConfigs[config.position] = config; - if (config.position > maxPos) { - maxPos = config.position; - } - } + ConfigMap::iterator ci = configs.find(*ai); + if (ci == configs.end()) { + continue; } - PositionParser pp(maxPos + 1); + AliasMap &aliasMap = configs[*ai]; + AliasPositionParser pp(aliasMap); NumberListParser::List posList = pp.parse(positions.c_str()); NumberListParser::List::const_iterator pi; for (pi = posList.begin(); pi != posList.end(); pi++) { - map::const_iterator ci; - ci = aliasConfigs.find(*pi); + AliasMap::const_iterator ci; - if (ci != aliasConfigs.end()) { + ci = aliasMap.find(*pi); + if (ci != aliasMap.end()) { list.push_back(ci->second); - } else { - stringstream err; - err << "Warning: Config " << *ai << ":" << *pi - << " does not exist on master " << m.getIndex(); - throwCommandException(err); } } } From cec2d4460940fb928cf17bc21fe54c3233d29573 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Tue, 4 Jan 2011 08:48:25 +0100 Subject: [PATCH 5/5] Be more tolerant when selecting slaves and domains. --- tool/Command.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tool/Command.cpp b/tool/Command.cpp index 4e68bf34..de9e246c 100644 --- a/tool/Command.cpp +++ b/tool/Command.cpp @@ -339,8 +339,10 @@ Command::SlaveList Command::selectedSlaves(MasterDevice &m) NumberListParser::List::const_iterator pi; for (pi = posList.begin(); pi != posList.end(); pi++) { - m.getSlave(&slave, *pi); - list.push_back(slave); + if (*pi < master.slave_count) { + m.getSlave(&slave, *pi); + list.push_back(slave); + } } } else { // aliases given SlaveAliasParser ap(master, m); @@ -375,11 +377,6 @@ Command::SlaveList Command::selectedSlaves(MasterDevice &m) for (pi = posList.begin(); pi != posList.end(); pi++) { if (*pi < aliasSlaves.size()) { list.push_back(aliasSlaves[*pi]); - } else { - stringstream err; - err << "Warning: Slave " << *ai << ":" << *pi - << " does not exist on master " << m.getIndex(); - throwCommandException(err); } } } @@ -475,9 +472,11 @@ Command::DomainList Command::selectedDomains(MasterDevice &m) NumberListParser::List::const_iterator di; for (di = domList.begin(); di != domList.end(); di++) { - ec_ioctl_domain_t d; - m.getDomain(&d, *di); - list.push_back(d); + if (*di < master.domain_count) { + ec_ioctl_domain_t d; + m.getDomain(&d, *di); + list.push_back(d); + } } return list;