Multi-master support for command-line tool. The --master option supports
ranges like '1-3,6,7-9'. The ioctl() interface version is checked.
--- a/NEWS Tue Feb 23 17:40:46 2010 +0100
+++ b/NEWS Wed Feb 24 16:27:11 2010 +0100
@@ -65,6 +65,8 @@
* Significantly improved EoE bandwidth by running EoE processing in a kthread.
* Switched version control from Subversion to Mercurial.
* Implemented CompleteAccess for SDO downloads.
+* ethercat tool is now able to handle multiple masters. The --masters option
+ supports ranges like '0,3,8-10'.
Changes in 1.4.0:
--- a/TODO Tue Feb 23 17:40:46 2010 +0100
+++ b/TODO Wed Feb 24 16:27:11 2010 +0100
@@ -38,7 +38,6 @@
* Remove default buffer size in SDO upload.
* Improve application-triggered SDO transfers by moving the state machine into
the SDO handlers.
-* Check for ioctl() interface version.
* Remove allow_scanning flag.
* Override sync manager size?
* Show Record / Array / List type of SDOs.
@@ -71,6 +70,7 @@
- Data type abbreviations.
- Add a -n (numeric) switch.
- Check for unwanted options.
+ - Implement ranges for slaves, domains, etc.
* Simplify master fsm by introducing a common request state to handle external
requests (replace write_sii, sdo_request, etc).
--- a/lib/common.c Tue Feb 23 17:40:46 2010 +0100
+++ b/lib/common.c Wed Feb 24 16:27:11 2010 +0100
@@ -71,7 +71,8 @@
ec_master_t *ecrt_open_master(unsigned int master_index)
{
char path[MAX_PATH_LEN];
- ec_master_t *master;
+ ec_master_t *master = NULL;
+ ec_ioctl_module_t module_data;
master = malloc(sizeof(ec_master_t));
if (!master) {
@@ -87,11 +88,30 @@
master->fd = open(path, O_RDWR);
if (master->fd == -1) {
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
- free(master);
- return 0;
+ goto out_free;
+ }
+
+ if (ioctl(master->fd, EC_IOCTL_MODULE, &module_data) < 0) {
+ fprintf(stderr, "Failed to get module information from %s: %s\n",
+ path, strerror(errno));
+ goto out_close;
+ }
+
+ if (module_data.ioctl_version_magic != EC_IOCTL_VERSION_MAGIC) {
+ fprintf(stderr, "ioctl() version magic is differing:"
+ " %s: %u, libethercat: %u.\n",
+ path, module_data.ioctl_version_magic,
+ EC_IOCTL_VERSION_MAGIC);
+ goto out_close;
}
return master;
+
+out_close:
+ close(master->fd);
+out_free:
+ free(master);
+ return 0;
}
/*****************************************************************************/
--- a/master/cdev.c Tue Feb 23 17:40:46 2010 +0100
+++ b/master/cdev.c Wed Feb 24 16:27:11 2010 +0100
@@ -157,6 +157,25 @@
/*****************************************************************************/
+/** Get module information.
+ */
+int ec_cdev_ioctl_module(
+ unsigned long arg /**< Userspace address to store the results. */
+ )
+{
+ ec_ioctl_module_t data;
+
+ data.ioctl_version_magic = EC_IOCTL_VERSION_MAGIC;
+ data.master_count = ec_master_count();
+
+ if (copy_to_user((void __user *) arg, &data, sizeof(data)))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*****************************************************************************/
+
/** Get master information.
*/
int ec_cdev_ioctl_master(
@@ -3281,6 +3300,8 @@
#endif
switch (cmd) {
+ case EC_IOCTL_MODULE:
+ return ec_cdev_ioctl_module(arg);
case EC_IOCTL_MASTER:
return ec_cdev_ioctl_master(master, arg);
case EC_IOCTL_SLAVE:
--- a/master/globals.h Tue Feb 23 17:40:46 2010 +0100
+++ b/master/globals.h Wed Feb 24 16:27:11 2010 +0100
@@ -263,6 +263,7 @@
/*****************************************************************************/
+unsigned int ec_master_count(void);
void ec_print_data(const uint8_t *, size_t);
void ec_print_data_diff(const uint8_t *, const uint8_t *, size_t);
size_t ec_state_string(uint8_t, char *, uint8_t);
--- a/master/ioctl.h Tue Feb 23 17:40:46 2010 +0100
+++ b/master/ioctl.h Wed Feb 24 16:27:11 2010 +0100
@@ -52,78 +52,85 @@
#define EC_IOW(nr, type) _IOW(EC_IOCTL_TYPE, nr, type)
#define EC_IOWR(nr, type) _IOWR(EC_IOCTL_TYPE, nr, type)
+/** EtherCAT master ioctl() version magic.
+ *
+ * Increment this when changing the ioctl interface!
+ */
+#define EC_IOCTL_VERSION_MAGIC 1
+
// Command-line tool
-#define EC_IOCTL_MASTER EC_IOR(0x00, ec_ioctl_master_t)
-#define EC_IOCTL_SLAVE EC_IOWR(0x01, ec_ioctl_slave_t)
-#define EC_IOCTL_SLAVE_SYNC EC_IOWR(0x02, ec_ioctl_slave_sync_t)
-#define EC_IOCTL_SLAVE_SYNC_PDO EC_IOWR(0x03, ec_ioctl_slave_sync_pdo_t)
-#define EC_IOCTL_SLAVE_SYNC_PDO_ENTRY EC_IOWR(0x04, ec_ioctl_slave_sync_pdo_entry_t)
-#define EC_IOCTL_DOMAIN EC_IOWR(0x05, ec_ioctl_domain_t)
-#define EC_IOCTL_DOMAIN_FMMU EC_IOWR(0x06, ec_ioctl_domain_fmmu_t)
-#define EC_IOCTL_DOMAIN_DATA EC_IOWR(0x07, ec_ioctl_domain_data_t)
-#define EC_IOCTL_MASTER_DEBUG EC_IO(0x08)
-#define EC_IOCTL_SLAVE_STATE EC_IOW(0x09, ec_ioctl_slave_state_t)
-#define EC_IOCTL_SLAVE_SDO EC_IOWR(0x0a, ec_ioctl_slave_sdo_t)
-#define EC_IOCTL_SLAVE_SDO_ENTRY EC_IOWR(0x0b, ec_ioctl_slave_sdo_entry_t)
-#define EC_IOCTL_SLAVE_SDO_UPLOAD EC_IOWR(0x0c, ec_ioctl_slave_sdo_upload_t)
-#define EC_IOCTL_SLAVE_SDO_DOWNLOAD EC_IOWR(0x0d, ec_ioctl_slave_sdo_download_t)
-#define EC_IOCTL_SLAVE_SII_READ EC_IOWR(0x0e, ec_ioctl_slave_sii_t)
-#define EC_IOCTL_SLAVE_SII_WRITE EC_IOW(0x0f, ec_ioctl_slave_sii_t)
-#define EC_IOCTL_SLAVE_REG_READ EC_IOWR(0x10, ec_ioctl_slave_reg_t)
-#define EC_IOCTL_SLAVE_REG_WRITE EC_IOW(0x11, ec_ioctl_slave_reg_t)
-#define EC_IOCTL_SLAVE_FOE_READ EC_IOWR(0x12, ec_ioctl_slave_foe_t)
-#define EC_IOCTL_SLAVE_FOE_WRITE EC_IOW(0x13, ec_ioctl_slave_foe_t)
-#define EC_IOCTL_CONFIG EC_IOWR(0x14, ec_ioctl_config_t)
-#define EC_IOCTL_CONFIG_PDO EC_IOWR(0x15, ec_ioctl_config_pdo_t)
-#define EC_IOCTL_CONFIG_PDO_ENTRY EC_IOWR(0x16, ec_ioctl_config_pdo_entry_t)
-#define EC_IOCTL_CONFIG_SDO EC_IOWR(0x17, ec_ioctl_config_sdo_t)
+#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
+#define EC_IOCTL_MASTER EC_IOR(0x01, ec_ioctl_master_t)
+#define EC_IOCTL_SLAVE EC_IOWR(0x02, ec_ioctl_slave_t)
+#define EC_IOCTL_SLAVE_SYNC EC_IOWR(0x03, ec_ioctl_slave_sync_t)
+#define EC_IOCTL_SLAVE_SYNC_PDO EC_IOWR(0x04, ec_ioctl_slave_sync_pdo_t)
+#define EC_IOCTL_SLAVE_SYNC_PDO_ENTRY EC_IOWR(0x05, ec_ioctl_slave_sync_pdo_entry_t)
+#define EC_IOCTL_DOMAIN EC_IOWR(0x06, ec_ioctl_domain_t)
+#define EC_IOCTL_DOMAIN_FMMU EC_IOWR(0x07, ec_ioctl_domain_fmmu_t)
+#define EC_IOCTL_DOMAIN_DATA EC_IOWR(0x08, ec_ioctl_domain_data_t)
+#define EC_IOCTL_MASTER_DEBUG EC_IO(0x09)
+#define EC_IOCTL_SLAVE_STATE EC_IOW(0x0a, ec_ioctl_slave_state_t)
+#define EC_IOCTL_SLAVE_SDO EC_IOWR(0x0b, ec_ioctl_slave_sdo_t)
+#define EC_IOCTL_SLAVE_SDO_ENTRY EC_IOWR(0x0c, ec_ioctl_slave_sdo_entry_t)
+#define EC_IOCTL_SLAVE_SDO_UPLOAD EC_IOWR(0x0d, ec_ioctl_slave_sdo_upload_t)
+#define EC_IOCTL_SLAVE_SDO_DOWNLOAD EC_IOWR(0x0e, ec_ioctl_slave_sdo_download_t)
+#define EC_IOCTL_SLAVE_SII_READ EC_IOWR(0x0f, ec_ioctl_slave_sii_t)
+#define EC_IOCTL_SLAVE_SII_WRITE EC_IOW(0x10, ec_ioctl_slave_sii_t)
+#define EC_IOCTL_SLAVE_REG_READ EC_IOWR(0x11, ec_ioctl_slave_reg_t)
+#define EC_IOCTL_SLAVE_REG_WRITE EC_IOW(0x12, ec_ioctl_slave_reg_t)
+#define EC_IOCTL_SLAVE_FOE_READ EC_IOWR(0x13, ec_ioctl_slave_foe_t)
+#define EC_IOCTL_SLAVE_FOE_WRITE EC_IOW(0x14, ec_ioctl_slave_foe_t)
+#define EC_IOCTL_CONFIG EC_IOWR(0x15, ec_ioctl_config_t)
+#define EC_IOCTL_CONFIG_PDO EC_IOWR(0x16, ec_ioctl_config_pdo_t)
+#define EC_IOCTL_CONFIG_PDO_ENTRY EC_IOWR(0x17, ec_ioctl_config_pdo_entry_t)
+#define EC_IOCTL_CONFIG_SDO EC_IOWR(0x18, ec_ioctl_config_sdo_t)
#ifdef EC_EOE
-#define EC_IOCTL_EOE_HANDLER EC_IOWR(0x18, ec_ioctl_eoe_handler_t)
+#define EC_IOCTL_EOE_HANDLER EC_IOWR(0x19, ec_ioctl_eoe_handler_t)
#endif
// Application interface
-#define EC_IOCTL_REQUEST EC_IO(0x19)
-#define EC_IOCTL_CREATE_DOMAIN EC_IO(0x1a)
-#define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x1b, ec_ioctl_config_t)
-#define EC_IOCTL_ACTIVATE EC_IOR(0x1c, size_t)
-#define EC_IOCTL_DEACTIVATE EC_IO(0x1d)
-#define EC_IOCTL_SEND EC_IO(0x1e)
-#define EC_IOCTL_RECEIVE EC_IO(0x1f)
-#define EC_IOCTL_MASTER_STATE EC_IOR(0x20, ec_master_state_t)
-#define EC_IOCTL_APP_TIME EC_IOW(0x21, ec_ioctl_app_time_t)
-#define EC_IOCTL_SYNC_REF EC_IO(0x22)
-#define EC_IOCTL_SYNC_SLAVES EC_IO(0x23)
-#define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x24)
-#define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x25, uint32_t)
-#define EC_IOCTL_SC_SYNC EC_IOW(0x26, ec_ioctl_config_t)
-#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x27, ec_ioctl_config_t)
-#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x28, ec_ioctl_config_pdo_t)
-#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x29, ec_ioctl_config_pdo_t)
-#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x2a, ec_ioctl_add_pdo_entry_t)
-#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x2b, ec_ioctl_config_pdo_t)
-#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x2c, ec_ioctl_reg_pdo_entry_t)
-#define EC_IOCTL_SC_DC EC_IOW(0x2d, ec_ioctl_config_t)
-#define EC_IOCTL_SC_SDO EC_IOW(0x2e, ec_ioctl_sc_sdo_t)
-#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x2f, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SC_VOE EC_IOWR(0x20, ec_ioctl_voe_t)
-#define EC_IOCTL_SC_STATE EC_IOWR(0x31, ec_ioctl_sc_state_t)
-#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x32)
-#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x33)
-#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x34)
-#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x35, ec_ioctl_domain_state_t)
-#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x36, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x37, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x38, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x39, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x3a, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x3b, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x3c, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_READ EC_IOW(0x3d, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x3e, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_WRITE EC_IOWR(0x3f, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_EXEC EC_IOWR(0x40, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_DATA EC_IOWR(0x41, ec_ioctl_voe_t)
-#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x42, size_t)
+#define EC_IOCTL_REQUEST EC_IO(0x1a)
+#define EC_IOCTL_CREATE_DOMAIN EC_IO(0x1b)
+#define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x1c, ec_ioctl_config_t)
+#define EC_IOCTL_ACTIVATE EC_IOR(0x1d, size_t)
+#define EC_IOCTL_DEACTIVATE EC_IO(0x1e)
+#define EC_IOCTL_SEND EC_IO(0x1f)
+#define EC_IOCTL_RECEIVE EC_IO(0x20)
+#define EC_IOCTL_MASTER_STATE EC_IOR(0x21, ec_master_state_t)
+#define EC_IOCTL_APP_TIME EC_IOW(0x22, ec_ioctl_app_time_t)
+#define EC_IOCTL_SYNC_REF EC_IO(0x23)
+#define EC_IOCTL_SYNC_SLAVES EC_IO(0x24)
+#define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x25)
+#define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x26, uint32_t)
+#define EC_IOCTL_SC_SYNC EC_IOW(0x27, ec_ioctl_config_t)
+#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x28, ec_ioctl_config_t)
+#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x29, ec_ioctl_config_pdo_t)
+#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x2a, ec_ioctl_config_pdo_t)
+#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x2b, ec_ioctl_add_pdo_entry_t)
+#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x2c, ec_ioctl_config_pdo_t)
+#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x2d, ec_ioctl_reg_pdo_entry_t)
+#define EC_IOCTL_SC_DC EC_IOW(0x2e, ec_ioctl_config_t)
+#define EC_IOCTL_SC_SDO EC_IOW(0x2f, ec_ioctl_sc_sdo_t)
+#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x20, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SC_VOE EC_IOWR(0x31, ec_ioctl_voe_t)
+#define EC_IOCTL_SC_STATE EC_IOWR(0x32, ec_ioctl_sc_state_t)
+#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x33)
+#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x34)
+#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x35)
+#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x36, ec_ioctl_domain_state_t)
+#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x37, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x38, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x39, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x3a, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x3b, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x3c, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x3d, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_READ EC_IOW(0x3e, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x3f, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_WRITE EC_IOWR(0x40, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_EXEC EC_IOWR(0x41, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_DATA EC_IOWR(0x42, ec_ioctl_voe_t)
+#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x43, size_t)
/*****************************************************************************/
@@ -132,6 +139,13 @@
/*****************************************************************************/
typedef struct {
+ uint32_t ioctl_version_magic;
+ uint32_t master_count;
+} ec_ioctl_module_t;
+
+/*****************************************************************************/
+
+typedef struct {
uint32_t slave_count;
uint32_t config_count;
uint32_t domain_count;
--- a/master/module.c Tue Feb 23 17:40:46 2010 +0100
+++ b/master/module.c Wed Feb 24 16:27:11 2010 +0100
@@ -195,6 +195,15 @@
EC_INFO("Master module cleaned up.\n");
}
+/*****************************************************************************/
+
+/** Get the number of masters.
+ */
+unsigned int ec_master_count(void)
+{
+ return master_count;
+}
+
/*****************************************************************************
* MAC address functions
****************************************************************************/
--- a/tool/Command.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/Command.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -28,6 +28,7 @@
****************************************************************************/
#include "Command.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -46,6 +47,13 @@
/*****************************************************************************/
+void Command::setMasterIndices(const MasterIndexList &indices)
+{
+ masterIndices = indices;
+};
+
+/*****************************************************************************/
+
void Command::setVerbosity(Verbosity v)
{
verbosity = v;
--- a/tool/Command.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/Command.h Wed Feb 24 16:27:11 2010 +0100
@@ -33,9 +33,12 @@
#include <stdexcept>
#include <vector>
#include <list>
+#include <sstream>
using namespace std;
-#include "MasterDevice.h"
+#include "../master/ioctl.h"
+
+class MasterDevice;
/****************************************************************************/
@@ -76,6 +79,9 @@
const string &getName() const;
const string &getBriefDescription() const;
+ typedef list<unsigned int> MasterIndexList;
+ void setMasterIndices(const MasterIndexList &);
+ const MasterIndexList &getMasterIndices() const;
enum Verbosity {
Quiet,
Normal,
@@ -102,7 +108,7 @@
virtual string helpString() const = 0;
typedef vector<string> StringVector;
- virtual void execute(MasterDevice &, const StringVector &) = 0;
+ virtual void execute(const StringVector &) = 0;
static string numericInfo();
@@ -125,6 +131,7 @@
private:
string name;
string briefDesc;
+ MasterIndexList masterIndices;
Verbosity verbosity;
int alias;
int position;
@@ -152,6 +159,13 @@
/****************************************************************************/
+inline const Command::MasterIndexList &Command::getMasterIndices() const
+{
+ return masterIndices;
+}
+
+/****************************************************************************/
+
inline Command::Verbosity Command::getVerbosity() const
{
return verbosity;
--- a/tool/CommandAlias.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandAlias.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -34,6 +34,7 @@
#include "CommandAlias.h"
#include "sii_crc.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -75,7 +76,7 @@
/** Writes the Secondary slave address (alias) to the slave's SII.
*/
-void CommandAlias::execute(MasterDevice &m, const StringVector &args)
+void CommandAlias::execute(const StringVector &args)
{
uint16_t alias;
stringstream err, strAlias;
@@ -98,6 +99,11 @@
}
alias = number;
+ if (getMasterIndices().size() != 1) {
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
m.open(MasterDevice::ReadWrite);
slaves = selectedSlaves(m);
--- a/tool/CommandAlias.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandAlias.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandAlias();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
void writeSlaveAlias(MasterDevice &, const ec_ioctl_slave_t &,
--- a/tool/CommandCStruct.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandCStruct.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -33,6 +33,7 @@
using namespace std;
#include "CommandCStruct.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -67,7 +68,7 @@
/****************************************************************************/
-void CommandCStruct::execute(MasterDevice &m, const StringVector &args)
+void CommandCStruct::execute(const StringVector &args)
{
SlaveList slaves;
SlaveList::const_iterator si;
@@ -78,11 +79,16 @@
throwInvalidUsageException(err);
}
- m.open(MasterDevice::Read);
- slaves = selectedSlaves(m);
-
- for (si = slaves.begin(); si != slaves.end(); si++) {
- generateSlaveCStruct(m, *si);
+ MasterIndexList::const_iterator mi;
+ for (mi = getMasterIndices().begin();
+ mi != getMasterIndices().end(); mi++) {
+ MasterDevice m(*mi);
+ m.open(MasterDevice::Read);
+ slaves = selectedSlaves(m);
+
+ for (si = slaves.begin(); si != slaves.end(); si++) {
+ generateSlaveCStruct(m, *si);
+ }
}
}
--- a/tool/CommandCStruct.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandCStruct.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandCStruct();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
void generateSlaveCStruct(MasterDevice &, const ec_ioctl_slave_t &);
--- a/tool/CommandConfig.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandConfig.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -34,6 +34,7 @@
using namespace std;
#include "CommandConfig.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -101,9 +102,10 @@
/** Lists the bus configuration.
*/
-void CommandConfig::execute(MasterDevice &m, const StringVector &args)
+void CommandConfig::execute(const StringVector &args)
{
ConfigList configs;
+ bool doIndent;
if (args.size()) {
stringstream err;
@@ -111,13 +113,23 @@
throwInvalidUsageException(err);
}
- m.open(MasterDevice::Read);
- configs = selectedConfigs(m);
-
- if (getVerbosity() == Verbose) {
- showDetailedConfigs(m, configs);
- } else {
- listConfigs(m, configs);
+ doIndent = getMasterIndices().size() > 1;
+ MasterIndexList::const_iterator mi;
+ for (mi = getMasterIndices().begin();
+ mi != getMasterIndices().end(); mi++) {
+ MasterDevice m(*mi);
+ m.open(MasterDevice::Read);
+ configs = selectedConfigs(m);
+
+ if (doIndent) {
+ cout << "Master" << dec << *mi << endl;
+ }
+
+ if (getVerbosity() == Verbose) {
+ showDetailedConfigs(m, configs, doIndent);
+ } else {
+ listConfigs(m, configs, doIndent);
+ }
}
}
@@ -127,7 +139,8 @@
*/
void CommandConfig::showDetailedConfigs(
MasterDevice &m,
- const ConfigList &configList
+ const ConfigList &configList,
+ bool doIndent
)
{
ConfigList::const_iterator configIter;
@@ -136,19 +149,21 @@
ec_ioctl_config_pdo_t pdo;
ec_ioctl_config_pdo_entry_t entry;
ec_ioctl_config_sdo_t sdo;
+ string indent(doIndent ? " " : "");
for (configIter = configList.begin();
configIter != configList.end();
configIter++) {
- cout << "Alias: "
- << dec << configIter->alias << endl
- << "Position: " << configIter->position << endl
+ cout << indent
+ << "Alias: "
+ << dec << configIter->alias << endl << indent
+ << "Position: " << configIter->position << endl << indent
<< "Vendor Id: 0x"
<< hex << setfill('0')
- << setw(8) << configIter->vendor_id << endl
+ << setw(8) << configIter->vendor_id << endl << indent
<< "Product code: 0x"
- << setw(8) << configIter->product_code << endl
+ << setw(8) << configIter->product_code << endl << indent
<< "Attached slave: ";
if (configIter->slave_position != -1) {
@@ -159,13 +174,13 @@
cout << "none" << endl;
}
- cout << "Watchdog divider: ";
+ cout << indent << "Watchdog divider: ";
if (configIter->watchdog_divider) {
cout << dec << configIter->watchdog_divider;
} else {
cout << "(Default)";
}
- cout << endl
+ cout << endl << indent
<< "Watchdog intervals: ";
if (configIter->watchdog_intervals) {
cout << dec << configIter->watchdog_intervals;
@@ -176,7 +191,7 @@
for (j = 0; j < EC_MAX_SYNC_MANAGERS; j++) {
if (configIter->syncs[j].pdo_count) {
- cout << "SM" << dec << j << ", Dir: "
+ cout << indent << "SM" << dec << j << ", Dir: "
<< (configIter->syncs[j].dir == EC_DIR_INPUT
? "Input" : "Output") << ", Watchdog: ";
switch (configIter->syncs[j].watchdog_mode) {
@@ -190,14 +205,15 @@
for (k = 0; k < configIter->syncs[j].pdo_count; k++) {
m.getConfigPdo(&pdo, configIter->config_index, j, k);
- cout << " PDO 0x" << hex << setfill('0')
+ cout << indent << " PDO 0x" << hex << setfill('0')
<< setw(4) << pdo.index << endl;
for (l = 0; l < pdo.entry_count; l++) {
m.getConfigPdoEntry(&entry,
configIter->config_index, j, k, l);
- cout << " PDO entry 0x" << hex << setfill('0')
+ cout << indent << " PDO entry 0x"
+ << hex << setfill('0')
<< setw(4) << entry.index << ":"
<< setw(2) << (unsigned int) entry.subindex
<< ", " << dec << setfill(' ')
@@ -208,23 +224,23 @@
}
}
- cout << "SDO configuration:" << endl;
+ cout << indent << "SDO configuration:" << endl;
if (configIter->sdo_count) {
for (j = 0; j < configIter->sdo_count; j++) {
m.getConfigSdo(&sdo, configIter->config_index, j);
- cout << " 0x"
+ cout << indent << " 0x"
<< hex << setfill('0')
<< setw(4) << sdo.index << ":"
<< setw(2) << (unsigned int) sdo.subindex
<< ", " << dec << sdo.size << " byte" << endl;
- cout << " " << hex;
+ cout << indent << " " << hex;
for (i = 0; i < min((uint32_t) sdo.size,
(uint32_t) EC_MAX_SDO_DATA_SIZE); i++) {
cout << setw(2) << (unsigned int) sdo.data[i];
if ((i + 1) % 16 == 0 && i < sdo.size - 1) {
- cout << endl << " ";
+ cout << endl << indent << " ";
} else {
cout << " ";
}
@@ -232,23 +248,23 @@
cout << endl;
if (sdo.size > EC_MAX_SDO_DATA_SIZE) {
- cout << " ..." << endl;
+ cout << indent << " ..." << endl;
}
}
} else {
- cout << " None." << endl;
+ cout << indent << " None." << endl;
}
if (configIter->dc_assign_activate) {
int i;
- cout << "DC configuration:" << endl
- << " AssignActivate: 0x" << hex << setfill('0')
+ cout << indent << "DC configuration:" << endl
+ << indent << " AssignActivate: 0x" << hex << setfill('0')
<< setw(4) << configIter->dc_assign_activate << endl;
- cout << " Cycle [ns] Shift [ns]" << endl;
+ cout << indent << " Cycle [ns] Shift [ns]" << endl;
for (i = 0; i < EC_SYNC_SIGNAL_COUNT; i++) {
- cout << " SYNC" << dec << i << " "
+ cout << indent << " SYNC" << dec << i << " "
<< setfill(' ') << right
<< setw(11) << configIter->dc_sync[i].cycle_time
<< " "
@@ -266,7 +282,8 @@
*/
void CommandConfig::listConfigs(
MasterDevice &m,
- const ConfigList &configList
+ const ConfigList &configList,
+ bool doIndent
)
{
ConfigList::const_iterator configIter;
@@ -278,6 +295,7 @@
unsigned int maxAliasWidth = 0, maxPosWidth = 0,
maxSlavePosWidth = 0, maxStateWidth = 0;
ec_ioctl_slave_t slave;
+ string indent(doIndent ? " " : "");
for (configIter = configList.begin();
configIter != configList.end();
@@ -337,7 +355,7 @@
}
for (iter = list.begin(); iter != list.end(); iter++) {
- cout << setfill(' ') << right
+ cout << indent << setfill(' ') << right
<< setw(maxAliasWidth) << iter->alias
<< ":" << left
<< setw(maxPosWidth) << iter->pos
--- a/tool/CommandConfig.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandConfig.h Wed Feb 24 16:27:11 2010 +0100
@@ -44,7 +44,7 @@
CommandConfig();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
struct Info {
@@ -55,8 +55,8 @@
string state;
};
- void showDetailedConfigs(MasterDevice &, const ConfigList &);
- void listConfigs(MasterDevice &m, const ConfigList &);
+ void showDetailedConfigs(MasterDevice &, const ConfigList &, bool);
+ void listConfigs(MasterDevice &m, const ConfigList &, bool);
};
/****************************************************************************/
--- a/tool/CommandData.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandData.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -31,6 +31,7 @@
using namespace std;
#include "CommandData.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -63,7 +64,7 @@
/****************************************************************************/
-void CommandData::execute(MasterDevice &m, const StringVector &args)
+void CommandData::execute(const StringVector &args)
{
DomainList domains;
DomainList::const_iterator di;
@@ -74,6 +75,12 @@
throwInvalidUsageException(err);
}
+ if (getMasterIndices().size() != 1) {
+ stringstream err;
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
m.open(MasterDevice::Read);
domains = selectedDomains(m);
--- a/tool/CommandData.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandData.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandData();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
void outputDomainData(MasterDevice &, const ec_ioctl_domain_t &);
--- a/tool/CommandDebug.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandDebug.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandDebug.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -65,7 +66,7 @@
/****************************************************************************/
-void CommandDebug::execute(MasterDevice &m, const StringVector &args)
+void CommandDebug::execute(const StringVector &args)
{
stringstream str;
int debugLevel;
@@ -86,8 +87,13 @@
throwInvalidUsageException(err);
}
- m.open(MasterDevice::ReadWrite);
- m.setDebug(debugLevel);
+ MasterIndexList::const_iterator mi;
+ for (mi = getMasterIndices().begin();
+ mi != getMasterIndices().end(); mi++) {
+ MasterDevice m(*mi);
+ m.open(MasterDevice::ReadWrite);
+ m.setDebug(debugLevel);
+ }
}
/*****************************************************************************/
--- a/tool/CommandDebug.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandDebug.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandDebug();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
};
/****************************************************************************/
--- a/tool/CommandDomains.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandDomains.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandDomains.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -89,10 +90,11 @@
/****************************************************************************/
-void CommandDomains::execute(MasterDevice &m, const StringVector &args)
+void CommandDomains::execute(const StringVector &args)
{
DomainList domains;
DomainList::const_iterator di;
+ bool doIndent;
if (args.size()) {
stringstream err;
@@ -100,11 +102,21 @@
throwInvalidUsageException(err);
}
- m.open(MasterDevice::Read);
- domains = selectedDomains(m);
+ doIndent = getMasterIndices().size() > 1;
+ MasterIndexList::const_iterator mi;
+ for (mi = getMasterIndices().begin();
+ mi != getMasterIndices().end(); mi++) {
+ MasterDevice m(*mi);
+ m.open(MasterDevice::Read);
+ domains = selectedDomains(m);
- for (di = domains.begin(); di != domains.end(); di++) {
- showDomain(m, *di);
+ if (doIndent) {
+ cout << "Master" << dec << *mi << endl;
+ }
+
+ for (di = domains.begin(); di != domains.end(); di++) {
+ showDomain(m, *di, doIndent);
+ }
}
}
@@ -112,7 +124,8 @@
void CommandDomains::showDomain(
MasterDevice &m,
- const ec_ioctl_domain_t &domain
+ const ec_ioctl_domain_t &domain,
+ bool doIndent
)
{
unsigned char *processData;
@@ -120,8 +133,9 @@
unsigned int i, j;
ec_ioctl_domain_fmmu_t fmmu;
unsigned int dataOffset;
+ string indent(doIndent ? " " : "");
- cout << "Domain" << dec << domain.index << ":"
+ cout << indent << "Domain" << dec << domain.index << ":"
<< " LogBaseAddr 0x"
<< hex << setfill('0')
<< setw(8) << domain.logical_base_address
@@ -146,7 +160,7 @@
for (i = 0; i < domain.fmmu_count; i++) {
m.getFmmu(&fmmu, domain.index, i);
- cout << " SlaveConfig "
+ cout << indent << " SlaveConfig "
<< dec << fmmu.slave_config_alias
<< ":" << fmmu.slave_config_position
<< ", SM" << (unsigned int) fmmu.sync_index << " ("
@@ -165,10 +179,10 @@
throwCommandException(err);
}
- cout << " " << hex << setfill('0');
+ cout << indent << " " << hex << setfill('0');
for (j = 0; j < fmmu.data_size; j++) {
if (j && !(j % BreakAfterBytes))
- cout << endl << " ";
+ cout << endl << indent << " ";
cout << "0x" << setw(2)
<< (unsigned int) *(processData + dataOffset + j) << " ";
}
--- a/tool/CommandDomains.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandDomains.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,10 +41,10 @@
CommandDomains();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
- void showDomain(MasterDevice &, const ec_ioctl_domain_t &);
+ void showDomain(MasterDevice &, const ec_ioctl_domain_t &, bool);
};
/****************************************************************************/
--- a/tool/CommandDownload.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandDownload.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandDownload.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -83,7 +84,7 @@
/****************************************************************************/
-void CommandDownload::execute(MasterDevice &m, const StringVector &args)
+void CommandDownload::execute(const StringVector &args)
{
stringstream strIndex, strSubIndex, strValue, err;
ec_ioctl_slave_sdo_download_t data;
@@ -115,6 +116,11 @@
}
data.sdo_entry_subindex = number;
+ if (getMasterIndices().size() != 1) {
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
m.open(MasterDevice::ReadWrite);
slaves = selectedSlaves(m);
if (slaves.size() != 1) {
--- a/tool/CommandDownload.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandDownload.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandDownload();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
enum {DefaultBufferSize = 1024};
--- a/tool/CommandEoe.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandEoe.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -34,6 +34,7 @@
using namespace std;
#include "CommandEoe.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -60,11 +61,13 @@
/****************************************************************************/
-void CommandEoe::execute(MasterDevice &m, const StringVector &args)
+void CommandEoe::execute(const StringVector &args)
{
ec_ioctl_master_t master;
unsigned int i;
ec_ioctl_eoe_handler_t eoe;
+ bool doIndent;
+ string indent;
if (args.size()) {
stringstream err;
@@ -72,31 +75,42 @@
throwInvalidUsageException(err);
}
- m.open(MasterDevice::Read);
- m.getMaster(&master);
+ doIndent = getMasterIndices().size();
+ indent = doIndent ? " " : "";
+ MasterIndexList::const_iterator mi;
+ for (mi = getMasterIndices().begin();
+ mi != getMasterIndices().end(); mi++) {
+ MasterDevice m(*mi);
+ m.open(MasterDevice::Read);
+ m.getMaster(&master);
- cout << "Interface Slave State "
- << "RxBytes RxRate "
- << "TxBytes TxRate TxQueue"
- << endl;
+ if (doIndent) {
+ cout << "Master" << dec << *mi << endl;
+ }
- for (i = 0; i < master.eoe_handler_count; i++) {
- stringstream queue;
+ cout << indent << "Interface Slave State "
+ << "RxBytes RxRate "
+ << "TxBytes TxRate TxQueue"
+ << endl;
- m.getEoeHandler(&eoe, i);
+ for (i = 0; i < master.eoe_handler_count; i++) {
+ stringstream queue;
- queue << eoe.tx_queued_frames << "/" << eoe.tx_queue_size;
+ m.getEoeHandler(&eoe, i);
- cout
- << setw(9) << eoe.name << " "
- << setw(5) << dec << eoe.slave_position << " "
- << setw(5) << (eoe.open ? "up" : "down") << " "
- << setw(7) << eoe.rx_bytes << " "
- << setw(6) << eoe.rx_rate << " "
- << setw(7) << eoe.tx_bytes << " "
- << setw(6) << eoe.tx_rate << " "
- << setw(7) << queue.str()
- << endl;
+ queue << eoe.tx_queued_frames << "/" << eoe.tx_queue_size;
+
+ cout << indent
+ << setw(9) << eoe.name << " "
+ << setw(5) << dec << eoe.slave_position << " "
+ << setw(5) << (eoe.open ? "up" : "down") << " "
+ << setw(7) << eoe.rx_bytes << " "
+ << setw(6) << eoe.rx_rate << " "
+ << setw(7) << eoe.tx_bytes << " "
+ << setw(6) << eoe.tx_rate << " "
+ << setw(7) << queue.str()
+ << endl;
+ }
}
}
--- a/tool/CommandEoe.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandEoe.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandEoe();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
};
/****************************************************************************/
--- a/tool/CommandFoeRead.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandFoeRead.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -35,6 +35,7 @@
#include "CommandFoeRead.h"
#include "foe.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -73,7 +74,7 @@
/****************************************************************************/
-void CommandFoeRead::execute(MasterDevice &m, const StringVector &args)
+void CommandFoeRead::execute(const StringVector &args)
{
SlaveList slaves;
ec_ioctl_slave_t *slave;
@@ -86,6 +87,11 @@
throwInvalidUsageException(err);
}
+ if (getMasterIndices().size() != 1) {
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
m.open(MasterDevice::Read);
slaves = selectedSlaves(m);
--- a/tool/CommandFoeRead.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandFoeRead.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandFoeRead();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
};
/****************************************************************************/
--- a/tool/CommandFoeWrite.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandFoeWrite.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -37,6 +37,7 @@
#include "CommandFoeWrite.h"
#include "foe.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -79,7 +80,7 @@
/****************************************************************************/
-void CommandFoeWrite::execute(MasterDevice &m, const StringVector &args)
+void CommandFoeWrite::execute(const StringVector &args)
{
stringstream err;
ec_ioctl_slave_foe_t data;
@@ -92,6 +93,12 @@
throwInvalidUsageException(err);
}
+ if (getMasterIndices().size() != 1) {
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
+
if (args[0] == "-") {
loadFoeData(&data, cin);
if (getOutputFile().empty()) {
--- a/tool/CommandFoeWrite.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandFoeWrite.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandFoeWrite();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
void loadFoeData(ec_ioctl_slave_foe_t *, const istream &);
--- a/tool/CommandGraph.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandGraph.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandGraph.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -64,7 +65,7 @@
/****************************************************************************/
-void CommandGraph::execute(MasterDevice &m, const StringVector &args)
+void CommandGraph::execute(const StringVector &args)
{
ec_ioctl_master_t master;
unsigned int i;
@@ -89,6 +90,12 @@
throwInvalidUsageException(err);
}
+ if (getMasterIndices().size() != 1) {
+ stringstream err;
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
m.open(MasterDevice::Read);
m.getMaster(&master);
--- a/tool/CommandGraph.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandGraph.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandGraph();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
};
/****************************************************************************/
--- a/tool/CommandMaster.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandMaster.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandMaster.h"
+#include "MasterDevice.h"
#define MAX_TIME_STR_SIZE 50
@@ -53,7 +54,9 @@
<< getBriefDescription() << endl
<< endl
<< "Command-specific options:" << endl
- << " --master -m <index> Index of the master to use. Default: 0."
+ << " --master -m <indices> Master indices. A comma-separated" << endl
+ << " list with ranges is supported." << endl
+ << " Example: 1,4,5,7-9. Default: - (all)."
<< endl << endl
<< numericInfo();
@@ -62,7 +65,7 @@
/****************************************************************************/
-void CommandMaster::execute(MasterDevice &m, const StringVector &args)
+void CommandMaster::execute(const StringVector &args)
{
ec_ioctl_master_t data;
stringstream err;
@@ -76,67 +79,79 @@
throwInvalidUsageException(err);
}
- m.open(MasterDevice::Read);
- m.getMaster(&data);
+ MasterIndexList::const_iterator mi;
+ for (mi = getMasterIndices().begin();
+ mi != getMasterIndices().end(); mi++) {
+ MasterDevice m(*mi);
+ m.open(MasterDevice::Read);
+ m.getMaster(&data);
- cout
- << "Master" << m.getIndex() << endl
- << " Phase: ";
+ cout
+ << "Master" << m.getIndex() << endl
+ << " Phase: ";
- switch (data.phase) {
- case 0: cout << "Waiting for device..."; break;
- case 1: cout << "Idle"; break;
- case 2: cout << "Operation"; break;
- default: cout << "???";
+ switch (data.phase) {
+ case 0: cout << "Waiting for device..."; break;
+ case 1: cout << "Idle"; break;
+ case 2: cout << "Operation"; break;
+ default: cout << "???";
+ }
+
+ cout << endl
+ << " Active: " << (data.active ? "yes" : "no") << endl
+ << " Slaves: " << data.slave_count << endl
+ << " Ethernet devices:" << endl;
+
+ for (i = 0; i < 2; i++) {
+ cout << " " << (i == 0 ? "Main" : "Backup") << ": ";
+ 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
+ << " Link: "
+ << (data.devices[i].link_state ? "UP" : "DOWN") << endl
+ << " Tx count: " << data.devices[i].tx_count << endl
+ << " Rx count: " << data.devices[i].rx_count;
+ }
+ cout << endl;
+ }
+
+ cout << " Distributed clocks:" << endl
+ << " Reference clock: ";
+ if (data.ref_clock != 0xffff) {
+ cout << "Slave " << dec << data.ref_clock;
+ } else {
+ cout << "None";
+ }
+ cout << endl
+ << " Application time: " << data.app_time << endl
+ << " ";
+
+ epoch = data.app_time / 1000000000 + 946684800ULL;
+ time_str_size = strftime(time_str, MAX_TIME_STR_SIZE,
+ "%Y-%m-%d %H:%M:%S", gmtime(&epoch));
+ cout << string(time_str, time_str_size) << "."
+ << setfill('0') << setw(9) << data.app_time % 1000000000 << endl;
}
-
- cout << endl
- << " Active: " << (data.active ? "yes" : "no") << endl
- << " Slaves: " << data.slave_count << endl
- << " Ethernet devices:" << endl;
-
- for (i = 0; i < 2; i++) {
- cout << " " << (i == 0 ? "Main" : "Backup") << ": ";
- 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
- << " Link: " << (data.devices[i].link_state ? "UP" : "DOWN") << endl
- << " Tx count: " << data.devices[i].tx_count << endl
- << " Rx count: " << data.devices[i].rx_count;
- }
- cout << endl;
- }
-
- cout << " Distributed clocks:" << endl
- << " Reference clock: ";
- if (data.ref_clock != 0xffff) {
- cout << "Slave " << dec << data.ref_clock;
- } else {
- cout << "None";
- }
- cout << endl
- << " Application time: " << data.app_time << endl
- << " ";
-
- epoch = data.app_time / 1000000000 + 946684800ULL;
- time_str_size = strftime(time_str, MAX_TIME_STR_SIZE,
- "%Y-%m-%d %H:%M:%S", gmtime(&epoch));
- cout << string(time_str, time_str_size) << "."
- << setfill('0') << setw(9) << data.app_time % 1000000000 << endl;
}
/*****************************************************************************/
--- a/tool/CommandMaster.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandMaster.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandMaster();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
};
/****************************************************************************/
--- a/tool/CommandPdos.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandPdos.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandPdos.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -88,11 +89,11 @@
/****************************************************************************/
-void CommandPdos::execute(MasterDevice &m, const StringVector &args)
+void CommandPdos::execute(const StringVector &args)
{
SlaveList slaves;
SlaveList::const_iterator si;
- bool showHeader;
+ bool showHeader, multiMaster;
if (args.size()) {
stringstream err;
@@ -100,12 +101,18 @@
throwInvalidUsageException(err);
}
- m.open(MasterDevice::Read);
- slaves = selectedSlaves(m);
- showHeader = slaves.size() > 1;
+ multiMaster = getMasterIndices().size() > 1;
+ MasterIndexList::const_iterator mi;
+ for (mi = getMasterIndices().begin();
+ mi != getMasterIndices().end(); mi++) {
+ MasterDevice m(*mi);
+ m.open(MasterDevice::Read);
+ slaves = selectedSlaves(m);
+ showHeader = multiMaster || slaves.size() > 1;
- for (si = slaves.begin(); si != slaves.end(); si++) {
- listSlavePdos(m, *si, showHeader);
+ for (si = slaves.begin(); si != slaves.end(); si++) {
+ listSlavePdos(m, *si, showHeader);
+ }
}
}
@@ -123,7 +130,8 @@
unsigned int i, j, k;
if (showHeader)
- cout << "=== Slave " << slave.position << " ===" << endl;
+ cout << "=== Master " << m.getIndex()
+ << ", Slave " << slave.position << " ===" << endl;
for (i = 0; i < slave.sync_count; i++) {
m.getSync(&sync, slave.position, i);
--- a/tool/CommandPdos.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandPdos.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandPdos();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
void listSlavePdos(MasterDevice &, const ec_ioctl_slave_t &, bool);
--- a/tool/CommandRegRead.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandRegRead.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandRegRead.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -78,7 +79,7 @@
/****************************************************************************/
-void CommandRegRead::execute(MasterDevice &m, const StringVector &args)
+void CommandRegRead::execute(const StringVector &args)
{
SlaveList slaves;
ec_ioctl_slave_reg_t data;
@@ -141,6 +142,11 @@
throwInvalidUsageException(err);
}
+ if (getMasterIndices().size() != 1) {
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
m.open(MasterDevice::Read);
slaves = selectedSlaves(m);
--- a/tool/CommandRegRead.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandRegRead.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandRegRead();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
};
/****************************************************************************/
--- a/tool/CommandRegWrite.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandRegWrite.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -34,6 +34,7 @@
#include "CommandRegWrite.h"
#include "sii_crc.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -80,7 +81,7 @@
/****************************************************************************/
-void CommandRegWrite::execute(MasterDevice &m, const StringVector &args)
+void CommandRegWrite::execute(const StringVector &args)
{
stringstream strOffset, err;
ec_ioctl_slave_reg_t data;
@@ -100,6 +101,12 @@
err << "Invalid offset '" << args[0] << "'!";
throwInvalidUsageException(err);
}
+
+ if (getMasterIndices().size() != 1) {
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
if (getDataType().empty()) {
if (args[1] == "-") {
--- a/tool/CommandRegWrite.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandRegWrite.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandRegWrite();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
private:
void loadRegData(ec_ioctl_slave_reg_t *, const istream &);
--- a/tool/CommandSdos.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandSdos.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandSdos.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -86,11 +87,11 @@
/****************************************************************************/
-void CommandSdos::execute(MasterDevice &m, const StringVector &args)
+void CommandSdos::execute(const StringVector &args)
{
SlaveList slaves;
SlaveList::const_iterator si;
- bool showHeader;
+ bool showHeader, multiMaster;
if (args.size()) {
stringstream err;
@@ -98,12 +99,18 @@
throwInvalidUsageException(err);
}
- m.open(MasterDevice::Read);
- slaves = selectedSlaves(m);
- showHeader = slaves.size() > 1;
+ multiMaster = getMasterIndices().size() > 1;
+ MasterIndexList::const_iterator mi;
+ for (mi = getMasterIndices().begin();
+ mi != getMasterIndices().end(); mi++) {
+ MasterDevice m(*mi);
+ m.open(MasterDevice::Read);
+ slaves = selectedSlaves(m);
+ showHeader = multiMaster || slaves.size() > 1;
- for (si = slaves.begin(); si != slaves.end(); si++) {
- listSlaveSdos(m, *si, showHeader);
+ for (si = slaves.begin(); si != slaves.end(); si++) {
+ listSlaveSdos(m, *si, showHeader);
+ }
}
}
@@ -121,7 +128,8 @@
const DataType *d;
if (showHeader)
- cout << "=== Slave " << slave.position << " ===" << endl;
+ cout << "=== Master " << m.getIndex()
+ << ", Slave " << slave.position << " ===" << endl;
for (i = 0; i < slave.sdo_count; i++) {
m.getSdo(&sdo, slave.position, i);
--- a/tool/CommandSdos.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandSdos.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandSdos();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
void listSlaveSdos(MasterDevice &, const ec_ioctl_slave_t &, bool);
--- a/tool/CommandSiiRead.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandSiiRead.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandSiiRead.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -73,7 +74,7 @@
/****************************************************************************/
-void CommandSiiRead::execute(MasterDevice &m, const StringVector &args)
+void CommandSiiRead::execute(const StringVector &args)
{
SlaveList slaves;
ec_ioctl_slave_t *slave;
@@ -88,6 +89,11 @@
throwInvalidUsageException(err);
}
+ if (getMasterIndices().size() != 1) {
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
m.open(MasterDevice::Read);
slaves = selectedSlaves(m);
--- a/tool/CommandSiiRead.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandSiiRead.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandSiiRead();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
struct CategoryName {
--- a/tool/CommandSiiWrite.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandSiiWrite.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -34,6 +34,7 @@
#include "CommandSiiWrite.h"
#include "sii_crc.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -75,7 +76,7 @@
/****************************************************************************/
-void CommandSiiWrite::execute(MasterDevice &m, const StringVector &args)
+void CommandSiiWrite::execute(const StringVector &args)
{
stringstream err;
ec_ioctl_slave_sii_t data;
@@ -87,6 +88,12 @@
throwInvalidUsageException(err);
}
+ if (getMasterIndices().size() != 1) {
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
+
if (args[0] == "-") {
loadSiiData(&data, cin);
} else {
--- a/tool/CommandSiiWrite.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandSiiWrite.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandSiiWrite();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
void loadSiiData(ec_ioctl_slave_sii_t *, const istream &);
--- a/tool/CommandSlaves.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandSlaves.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -34,6 +34,7 @@
using namespace std;
#include "CommandSlaves.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -105,9 +106,10 @@
/****************************************************************************/
-void CommandSlaves::execute(MasterDevice &m, const StringVector &args)
+void CommandSlaves::execute(const StringVector &args)
{
SlaveList slaves;
+ bool doIndent;
if (args.size()) {
stringstream err;
@@ -115,13 +117,23 @@
throwInvalidUsageException(err);
}
- m.open(MasterDevice::Read);
- slaves = selectedSlaves(m);
-
- if (getVerbosity() == Verbose) {
- showSlaves(m, slaves);
- } else {
- listSlaves(m, slaves);
+ doIndent = getMasterIndices().size() > 1;
+ MasterIndexList::const_iterator mi;
+ for (mi = getMasterIndices().begin();
+ mi != getMasterIndices().end(); mi++) {
+ MasterDevice m(*mi);
+ m.open(MasterDevice::Read);
+ slaves = selectedSlaves(m);
+
+ if (doIndent) {
+ cout << "Master" << dec << *mi << endl;
+ }
+
+ if (getVerbosity() == Verbose) {
+ showSlaves(m, slaves);
+ } else {
+ listSlaves(m, slaves, doIndent);
+ }
}
}
@@ -129,7 +141,8 @@
void CommandSlaves::listSlaves(
MasterDevice &m,
- const SlaveList &slaves
+ const SlaveList &slaves,
+ bool doIndent
)
{
ec_ioctl_master_t master;
@@ -143,6 +156,7 @@
stringstream str;
unsigned int maxPosWidth = 0, maxAliasWidth = 0,
maxRelPosWidth = 0, maxStateWidth = 0;
+ string indent(doIndent ? " " : "");
m.getMaster(&master);
@@ -200,7 +214,7 @@
}
for (iter = infoList.begin(); iter != infoList.end(); iter++) {
- cout << setfill(' ') << right
+ cout << indent << setfill(' ') << right
<< setw(maxPosWidth) << iter->pos << " "
<< setw(maxAliasWidth) << iter->alias
<< ":" << left
@@ -222,7 +236,8 @@
int i;
for (si = slaves.begin(); si != slaves.end(); si++) {
- cout << "=== Slave " << dec << si->position << " ===" << endl;
+ cout << "=== Master " << dec << m.getIndex()
+ << ", Slave " << dec << si->position << " ===" << endl;
if (si->alias)
cout << "Alias: " << si->alias << endl;
--- a/tool/CommandSlaves.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandSlaves.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandSlaves();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
struct Info {
@@ -53,7 +53,7 @@
string name;
};
- void listSlaves(MasterDevice &, const SlaveList &);
+ void listSlaves(MasterDevice &, const SlaveList &, bool);
void showSlaves(MasterDevice &, const SlaveList &);
static bool slaveInList( const ec_ioctl_slave_t &, const SlaveList &);
--- a/tool/CommandStates.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandStates.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandStates.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -65,7 +66,7 @@
/****************************************************************************/
-void CommandStates::execute(MasterDevice &m, const StringVector &args)
+void CommandStates::execute(const StringVector &args)
{
SlaveList slaves;
SlaveList::const_iterator si;
@@ -97,15 +98,16 @@
throwInvalidUsageException(err);
}
- m.open(MasterDevice::ReadWrite);
- slaves = selectedSlaves(m);
+ MasterIndexList::const_iterator mi;
+ for (mi = getMasterIndices().begin();
+ mi != getMasterIndices().end(); mi++) {
+ MasterDevice m(*mi);
+ m.open(MasterDevice::ReadWrite);
+ slaves = selectedSlaves(m);
- if (!slaves.size() && getVerbosity() != Quiet) {
- cerr << "Warning: Selection matches no slaves!" << endl;
- }
-
- for (si = slaves.begin(); si != slaves.end(); si++) {
- m.requestState(si->position, state);
+ for (si = slaves.begin(); si != slaves.end(); si++) {
+ m.requestState(si->position, state);
+ }
}
}
--- a/tool/CommandStates.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandStates.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandStates();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
};
/****************************************************************************/
--- a/tool/CommandUpload.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandUpload.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -32,6 +32,7 @@
using namespace std;
#include "CommandUpload.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -81,7 +82,7 @@
/****************************************************************************/
-void CommandUpload::execute(MasterDevice &m, const StringVector &args)
+void CommandUpload::execute(const StringVector &args)
{
SlaveList slaves;
stringstream err, strIndex, strSubIndex;
@@ -113,6 +114,11 @@
}
data.sdo_entry_subindex = uval;
+ if (getMasterIndices().size() != 1) {
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
m.open(MasterDevice::Read);
slaves = selectedSlaves(m);
if (slaves.size() != 1) {
--- a/tool/CommandUpload.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandUpload.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandUpload();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
enum {DefaultBufferSize = 64 * 1024};
--- a/tool/CommandVersion.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandVersion.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -54,7 +54,7 @@
/****************************************************************************/
-void CommandVersion::execute(MasterDevice &m, const StringVector &args)
+void CommandVersion::execute(const StringVector &args)
{
if (args.size()) {
stringstream err;
--- a/tool/CommandVersion.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandVersion.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandVersion();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
};
/****************************************************************************/
--- a/tool/CommandXml.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandXml.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -33,6 +33,7 @@
using namespace std;
#include "CommandXml.h"
+#include "MasterDevice.h"
/*****************************************************************************/
@@ -68,7 +69,7 @@
/****************************************************************************/
-void CommandXml::execute(MasterDevice &m, const StringVector &args)
+void CommandXml::execute(const StringVector &args)
{
SlaveList slaves;
SlaveList::const_iterator si;
@@ -79,6 +80,12 @@
throwInvalidUsageException(err);
}
+ if (getMasterIndices().size() != 1) {
+ stringstream err;
+ err << getName() << " requires to select a single master!";
+ throwInvalidUsageException(err);
+ }
+ MasterDevice m(getMasterIndices().front());
m.open(MasterDevice::Read);
slaves = selectedSlaves(m);
--- a/tool/CommandXml.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/CommandXml.h Wed Feb 24 16:27:11 2010 +0100
@@ -41,7 +41,7 @@
CommandXml();
string helpString() const;
- void execute(MasterDevice &, const StringVector &);
+ void execute(const StringVector &);
protected:
void generateSlaveXml(MasterDevice &, const ec_ioctl_slave_t &,
--- a/tool/Makefile.am Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/Makefile.am Wed Feb 24 16:27:11 2010 +0100
@@ -38,8 +38,8 @@
ethercat_SOURCES = \
Command.cpp \
CommandAlias.cpp \
+ CommandCStruct.cpp \
CommandConfig.cpp \
- CommandCStruct.cpp \
CommandData.cpp \
CommandDebug.cpp \
CommandDomains.cpp \
@@ -62,6 +62,7 @@
CommandXml.cpp \
FoeCommand.cpp \
MasterDevice.cpp \
+ NumberListParser.cpp \
SdoCommand.cpp \
main.cpp \
sii_crc.cpp
@@ -75,8 +76,8 @@
noinst_HEADERS = \
Command.h \
CommandAlias.h \
+ CommandCStruct.h \
CommandConfig.h \
- CommandCStruct.h \
CommandData.h \
CommandDebug.h \
CommandDomains.h \
@@ -99,6 +100,7 @@
CommandXml.h \
FoeCommand.h \
MasterDevice.h \
+ NumberListParser.h \
SdoCommand.h \
sii_crc.h
--- a/tool/MasterDevice.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/MasterDevice.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -42,10 +42,11 @@
/****************************************************************************/
-MasterDevice::MasterDevice()
-{
- index = 0;
- fd = -1;
+MasterDevice::MasterDevice(unsigned int index):
+ index(index),
+ masterCount(0U),
+ fd(-1)
+{
}
/****************************************************************************/
@@ -69,6 +70,7 @@
stringstream deviceName;
if (fd == -1) { // not already open
+ ec_ioctl_module_t module_data;
deviceName << "/dev/EtherCAT" << index;
if ((fd = ::open(deviceName.str().c_str(),
@@ -78,6 +80,16 @@
<< strerror(errno);
throw MasterDeviceException(err);
}
+
+ getModule(&module_data);
+ if (module_data.ioctl_version_magic != EC_IOCTL_VERSION_MAGIC) {
+ stringstream err;
+ err << "ioctl() version magic is differing: "
+ << deviceName << ": " << module_data.ioctl_version_magic
+ << ", ethercat tool: " << EC_IOCTL_VERSION_MAGIC;
+ throw MasterDeviceException(err);
+ }
+ masterCount = module_data.master_count;
}
}
@@ -93,6 +105,17 @@
/****************************************************************************/
+void MasterDevice::getModule(ec_ioctl_module_t *data)
+{
+ if (ioctl(fd, EC_IOCTL_MODULE, data) < 0) {
+ stringstream err;
+ err << "Failed to get module information: " << strerror(errno);
+ throw MasterDeviceException(err);
+ }
+}
+
+/****************************************************************************/
+
void MasterDevice::getMaster(ec_ioctl_master_t *data)
{
if (ioctl(fd, EC_IOCTL_MASTER, data) < 0) {
--- a/tool/MasterDevice.h Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/MasterDevice.h Wed Feb 24 16:27:11 2010 +0100
@@ -79,7 +79,7 @@
class MasterDevice
{
public:
- MasterDevice();
+ MasterDevice(unsigned int = 0U);
~MasterDevice();
void setIndex(unsigned int);
@@ -89,6 +89,8 @@
void open(Permissions);
void close();
+ void getModule(ec_ioctl_module_t *);
+
void getMaster(ec_ioctl_master_t *);
void getConfig(ec_ioctl_config_t *, unsigned int);
void getConfigPdo(ec_ioctl_config_pdo_t *, unsigned int, uint8_t,
@@ -121,8 +123,11 @@
void getEoeHandler(ec_ioctl_eoe_handler_t *, uint16_t);
#endif
+ unsigned int getMasterCount() const {return masterCount;}
+
private:
unsigned int index;
+ unsigned int masterCount;
int fd;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/NumberListParser.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -0,0 +1,230 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH
+ *
+ * This file is part of the IgH EtherCAT Master.
+ *
+ * The IgH EtherCAT Master is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * The IgH EtherCAT Master is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with the IgH EtherCAT Master; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * ---
+ *
+ * The license mentioned above concerns the source code only. Using the
+ * EtherCAT technology and brand is only permitted in compliance with the
+ * industrial property and similar rights of Beckhoff Automation GmbH.
+ *
+ ****************************************************************************/
+
+#include <cstring>
+#include <sstream>
+#include <stdexcept>
+using namespace std;
+
+#include "NumberListParser.h"
+
+/*****************************************************************************/
+
+NumberListParser::NumberListParser():
+ max(0U),
+ hasMax(false)
+{
+}
+
+/*****************************************************************************/
+
+NumberListParser::~NumberListParser()
+{
+}
+
+/*****************************************************************************/
+
+NumberListParser::NumberList NumberListParser::parse(const char *data)
+{
+ NumberList ret;
+ unsigned int i = 0, size = strlen(data), firstNum = 0U, secondNum = 0U;
+ typedef enum {
+ SectionStart,
+ FirstNumber,
+ Range,
+ SecondNumber,
+ Finished
+ } State;
+ State state = SectionStart;
+
+ while (state != Finished) {
+ switch (state) {
+ case SectionStart:
+ if (i >= size) {
+ state = Finished;
+ } else if (isNumeric(data[i])) {
+ firstNum = parseNumber(data, &i, size);
+ state = FirstNumber;
+ } else if (data[i] == '-') {
+ firstNum = 0U;
+ i++;
+ state = Range;
+ } else if (data[i] == ',') {
+ i++;
+ } else {
+ stringstream err;
+ err << "Invalid character " << data[i]
+ << " at position " << i << "in state "
+ << state << "." << endl;
+ throw runtime_error(err.str());
+ }
+ break;
+
+ case FirstNumber:
+ if (i >= size) {
+ ret.push_back(firstNum);
+ state = Finished;
+ } else if (data[i] == '-') {
+ i++;
+ state = Range;
+ } else if (data[i] == ',') {
+ i++;
+ ret.push_back(firstNum);
+ state = SectionStart;
+ } else {
+ stringstream err;
+ err << "Invalid character " << data[i]
+ << " at position " << i << "in state "
+ << state << "." << endl;
+ throw runtime_error(err.str());
+ }
+ break;
+
+ case Range:
+ if (i >= size) {
+ secondNum = maximum();
+ NumberList r = range(firstNum, secondNum);
+ ret.splice(ret.end(), r);
+ state = Finished;
+ } else if (isNumeric(data[i])) {
+ secondNum = parseNumber(data, &i, size);
+ state = SecondNumber;
+ } else if (data[i] == ',') {
+ i++;
+ secondNum = maximum();
+ NumberList r = range(firstNum, secondNum);
+ ret.splice(ret.end(), r);
+ state = SectionStart;
+ } else {
+ stringstream err;
+ err << "Invalid character " << data[i]
+ << " at position " << i << "in state "
+ << state << "." << endl;
+ throw runtime_error(err.str());
+ }
+ break;
+
+ case SecondNumber:
+ if (i >= size) {
+ NumberList r = range(firstNum, secondNum);
+ ret.splice(ret.end(), r);
+ state = Finished;
+ } else if (data[i] == ',') {
+ i++;
+ NumberList r = range(firstNum, secondNum);
+ ret.splice(ret.end(), r);
+ state = SectionStart;
+ } else {
+ stringstream err;
+ err << "Invalid character " << data[i]
+ << " at position " << i << "in state "
+ << state << "." << endl;
+ throw runtime_error(err.str());
+ }
+ break;
+
+ default:
+ {
+ stringstream err;
+ err << "Invalid state " << state << ".";
+ throw runtime_error(err.str());
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+
+unsigned int NumberListParser::maximum()
+{
+ if (!hasMax) {
+ max = getMax();
+ }
+
+ return max;
+}
+
+/*****************************************************************************/
+
+bool NumberListParser::isNumeric(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+/*****************************************************************************/
+
+unsigned int NumberListParser::parseNumber(
+ const char *data,
+ unsigned int *i,
+ unsigned int size
+ )
+{
+ unsigned int numSize = 0U, ret;
+
+ while (*i + numSize < size && isNumeric(data[*i + numSize])) {
+ numSize++;
+ }
+
+ if (numSize) {
+ stringstream str;
+ str << string(data + *i, numSize);
+ str >> ret;
+ } else {
+ throw runtime_error("EOF");
+ }
+
+ *i = *i + numSize;
+ return ret;
+}
+
+/****************************************************************************/
+
+NumberListParser::NumberList NumberListParser::range(
+ unsigned int i,
+ unsigned int j
+ )
+{
+ NumberList ret;
+
+ if (i <= j) {
+ for (; i <= j; i++) {
+ ret.push_back(i);
+ }
+ } else {
+ for (; i >= j; i--) {
+ ret.push_back(i);
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/NumberListParser.h Wed Feb 24 16:27:11 2010 +0100
@@ -0,0 +1,59 @@
+/*****************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH
+ *
+ * This file is part of the IgH EtherCAT Master.
+ *
+ * The IgH EtherCAT Master is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * The IgH EtherCAT Master is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with the IgH EtherCAT Master; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * ---
+ *
+ * The license mentioned above concerns the source code only. Using the
+ * EtherCAT technology and brand is only permitted in compliance with the
+ * industrial property and similar rights of Beckhoff Automation GmbH.
+ *
+ ****************************************************************************/
+
+#include <list>
+using namespace std;
+
+/*****************************************************************************/
+
+class NumberListParser
+{
+ public:
+ NumberListParser();
+ ~NumberListParser();
+
+ typedef list<unsigned int> NumberList;
+
+ NumberList parse(const char *);
+
+ virtual unsigned int getMax() = 0;
+
+ private:
+ unsigned int max;
+ bool hasMax;
+
+ unsigned int maximum();
+
+ static bool isNumeric(char);
+ static unsigned int parseNumber(const char *, unsigned int *,
+ unsigned int);
+ static NumberList range(unsigned int, unsigned int);
+};
+
+/****************************************************************************/
--- a/tool/main.cpp Tue Feb 23 17:40:46 2010 +0100
+++ b/tool/main.cpp Wed Feb 24 16:27:11 2010 +0100
@@ -61,19 +61,21 @@
#include "CommandVersion.h"
#include "CommandXml.h"
+#include "NumberListParser.h"
+#include "MasterDevice.h"
+
/*****************************************************************************/
typedef list<Command *> CommandList;
CommandList commandList;
-MasterDevice masterDev;
-
string binaryBaseName;
string commandName;
Command::StringVector commandArgs;
// option variables
-unsigned int masterIndex = 0;
+list<unsigned int> masterIndices;
+string masterIndexList = "-"; // all masters
int slavePosition = -1;
int slaveAlias = -1;
int domainIndex = -1;
@@ -128,6 +130,20 @@
/*****************************************************************************/
+class MasterIndexParser:
+ public NumberListParser
+{
+ unsigned int getMax()
+ {
+ MasterDevice dev;
+ dev.setIndex(0U);
+ dev.open(MasterDevice::Read);
+ return dev.getMasterCount() - 1;
+ };
+};
+
+/*****************************************************************************/
+
void getOptions(int argc, char **argv)
{
int c, argCount;
@@ -153,16 +169,7 @@
switch (c) {
case 'm':
- str.clear();
- str.str("");
- str << optarg;
- str >> resetiosflags(ios::basefield) // guess base from prefix
- >> masterIndex;
- if (str.fail() || masterIndex < 0) {
- cerr << "Invalid master number " << optarg << "!" << endl
- << endl << usage();
- exit(1);
- }
+ masterIndexList = optarg;
break;
case 'a':
@@ -252,6 +259,19 @@
}
}
+ try {
+ MasterIndexParser p;
+ masterIndices = p.parse(masterIndexList.c_str());
+ } catch (MasterDeviceException &e) {
+ cerr << "Failed to obtain number of masters: " << e.what() << endl;
+ exit(1);
+ } catch (runtime_error &e) {
+ cerr << "Invalid master argument " << masterIndexList
+ << ": " << e.what() << endl
+ << endl << usage();
+ exit(1);
+ }
+
commandName = argv[optind];
while (++optind < argc)
commandArgs.push_back(string(argv[optind]));
@@ -323,13 +343,19 @@
getOptions(argc, argv);
matchingCommands = getMatchingCommands(commandName);
- masterDev.setIndex(masterIndex);
+
+ if (masterIndices.empty()) {
+ cerr << "List of master indices may not be empty!" << endl
+ << endl << usage();
+ exit(1);
+ }
if (matchingCommands.size()) {
if (matchingCommands.size() == 1) {
cmd = matchingCommands.front();
if (!helpRequested) {
try {
+ cmd->setMasterIndices(masterIndices);
cmd->setVerbosity(verbosity);
cmd->setAlias(slaveAlias);
cmd->setPosition(slavePosition);
@@ -337,7 +363,7 @@
cmd->setDataType(dataTypeStr);
cmd->setOutputFile(outputFile);
cmd->setForce(force);
- cmd->execute(masterDev, commandArgs);
+ cmd->execute(commandArgs);
} catch (InvalidUsageException &e) {
cerr << e.what() << endl << endl;
cerr << binaryBaseName << " " << cmd->helpString();