merged
This commit is contained in:
commit
dda18aa1f6
5
TODO
5
TODO
|
|
@ -13,17 +13,12 @@ Version 1.5.0:
|
|||
* Ethernet drivers:
|
||||
- Fix link detection in generic driver.
|
||||
- Add native drivers from 2.6.24 up to 2.6.31.
|
||||
* ethercat tool:
|
||||
- Implement ranges for slaves and domains.
|
||||
|
||||
Future issues:
|
||||
|
||||
* Remove allow_scanning flag.
|
||||
* Output skipped datagrams again.
|
||||
* Check for Enable SDO Complete Access flag.
|
||||
* Do not output 'SDO does not exist' when querying data type.
|
||||
* Always write down PDO assignment/mapping in doubt? If not, add an interface
|
||||
for enforcing this.
|
||||
* Read AL status code on spontaneous state change.
|
||||
* recompile tool/CommandVersion.cpp if revision changes.
|
||||
* Log SoE IDNs with real name ([SP]-x-yyyy).
|
||||
|
|
|
|||
|
|
@ -76,6 +76,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.
|
||||
* - Added support for overlapping PDOs which allows inputs to use the same
|
||||
* space as outputs on the frame. This reduces the frame length.
|
||||
*
|
||||
|
|
@ -885,6 +886,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
|
||||
*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -591,3 +591,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));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -2009,6 +2009,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;
|
||||
|
||||
ec_mutex_lock(&master->master_mutex);
|
||||
ecrt_master_reset(master);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Configure a sync manager.
|
||||
*/
|
||||
int ec_cdev_ioctl_sc_sync(
|
||||
|
|
@ -3723,6 +3742,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;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@
|
|||
*
|
||||
* Increment this when changing the ioctl interface!
|
||||
*/
|
||||
#define EC_IOCTL_VERSION_MAGIC 11
|
||||
#define EC_IOCTL_VERSION_MAGIC 12
|
||||
|
||||
// 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,38 +106,39 @@
|
|||
#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_MASTER_SC_STATE EC_IOR(0x49, ec_master_state_t)
|
||||
#define EC_IOCTL_SC_OVERLAPPING_IO EC_IOW(0x50, ec_ioctl_config_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)
|
||||
#define EC_IOCTL_MASTER_SC_STATE EC_IOR(0x50, ec_master_state_t)
|
||||
#define EC_IOCTL_SC_OVERLAPPING_IO EC_IOW(0x51, ec_ioctl_config_t)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -2475,6 +2475,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);
|
||||
|
|
@ -2494,6 +2507,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 */
|
||||
|
||||
|
|
|
|||
275
tool/Command.cpp
275
tool/Command.cpp
|
|
@ -29,22 +29,120 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
#include "Command.h"
|
||||
#include "MasterDevice.h"
|
||||
#include "NumberListParser.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef map<uint16_t, ec_ioctl_config_t> AliasMap;
|
||||
typedef map<uint16_t, AliasMap> ConfigMap;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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(unsigned int maxAlias):
|
||||
maxAlias(maxAlias) {}
|
||||
|
||||
protected:
|
||||
int getMax() { return maxAlias; };
|
||||
|
||||
private:
|
||||
unsigned int maxAlias;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class PositionParser:
|
||||
public NumberListParser
|
||||
{
|
||||
public:
|
||||
PositionParser(unsigned int count):
|
||||
count(count) {}
|
||||
|
||||
protected:
|
||||
int getMax() {
|
||||
return count - 1;
|
||||
};
|
||||
|
||||
private:
|
||||
const unsigned int count;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -78,23 +176,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;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -214,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();
|
||||
}
|
||||
|
||||
|
|
@ -227,51 +327,57 @@ 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);
|
||||
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++) {
|
||||
if (*pi < master.slave_count) {
|
||||
m.getSlave(&slave, *pi);
|
||||
list.push_back(slave);
|
||||
}
|
||||
} else { // no alias, but position given
|
||||
// one item by position
|
||||
m.getSlave(&slave, position);
|
||||
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<ec_ioctl_slave_t> 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]);
|
||||
}
|
||||
if (lastAlias && aliasIndex == (unsigned int) position) {
|
||||
list.push_back(slave);
|
||||
}
|
||||
aliasIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -302,37 +408,47 @@ 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 == "-" && positions == "-") { // shortcut
|
||||
for (i = 0; i < master.config_count; i++) {
|
||||
m.getConfig(&config, i);
|
||||
list.push_back(config);
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
} else { // alias given
|
||||
if (position == -1) { // alias, but no position given
|
||||
// take all items with a given alias
|
||||
for (i = 0; i < master.config_count; i++) {
|
||||
m.getConfig(&config, i);
|
||||
if (config.alias == alias) {
|
||||
list.push_back(config);
|
||||
}
|
||||
|
||||
ConfigAliasParser ap(maxAlias);
|
||||
NumberListParser::List aliasList = ap.parse(aliases.c_str());
|
||||
NumberListParser::List::const_iterator ai;
|
||||
|
||||
for (ai = aliasList.begin(); ai != aliasList.end(); ai++) {
|
||||
|
||||
ConfigMap::iterator ci = configs.find(*ai);
|
||||
if (ci == configs.end()) {
|
||||
continue;
|
||||
}
|
||||
} 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
|
||||
|
||||
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++) {
|
||||
AliasMap::const_iterator ci;
|
||||
|
||||
ci = aliasMap.find(*pi);
|
||||
if (ci != aliasMap.end()) {
|
||||
list.push_back(ci->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -346,22 +462,21 @@ 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);
|
||||
for (di = domList.begin(); di != domList.end(); di++) {
|
||||
if (*di < master.domain_count) {
|
||||
ec_ioctl_domain_t d;
|
||||
m.getDomain(&d, *di);
|
||||
list.push_back(d);
|
||||
}
|
||||
} else {
|
||||
m.getDomain(&d, domain);
|
||||
list.push_back(d);
|
||||
}
|
||||
|
||||
return list;
|
||||
|
|
|
|||
|
|
@ -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<unsigned int> 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;
|
||||
|
|
|
|||
|
|
@ -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,23 @@ 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();
|
||||
// only increasing ranges if second number omitted
|
||||
if (max >= 0 && firstNum <= (unsigned int) max) {
|
||||
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 +137,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 +168,7 @@ NumberListParser::NumberList NumberListParser::parse(const char *data)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
unsigned int NumberListParser::maximum()
|
||||
int NumberListParser::maximum()
|
||||
{
|
||||
if (!hasMax) {
|
||||
max = getMax();
|
||||
|
|
@ -207,12 +212,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++) {
|
||||
|
|
|
|||
|
|
@ -38,22 +38,22 @@ class NumberListParser
|
|||
NumberListParser();
|
||||
virtual ~NumberListParser();
|
||||
|
||||
typedef list<unsigned int> NumberList;
|
||||
typedef list<unsigned int> 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);
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue