# HG changeset patch # User Florian Pose # Date 1267025231 -3600 # Node ID ec6223c3b7ec413a94012045d03b559b6e844166 # Parent 65781b048a4729d991de0415d4905ad6e7e2dd48 Multi-master support for command-line tool. The --master option supports ranges like '1-3,6,7-9'. The ioctl() interface version is checked. diff -r 65781b048a47 -r ec6223c3b7ec NEWS --- 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: diff -r 65781b048a47 -r ec6223c3b7ec TODO --- 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). diff -r 65781b048a47 -r ec6223c3b7ec lib/common.c --- 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; } /*****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec master/cdev.c --- 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: diff -r 65781b048a47 -r ec6223c3b7ec master/globals.h --- 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); diff -r 65781b048a47 -r ec6223c3b7ec master/ioctl.h --- 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; diff -r 65781b048a47 -r ec6223c3b7ec master/module.c --- 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 ****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/Command.cpp --- 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; diff -r 65781b048a47 -r ec6223c3b7ec tool/Command.h --- 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 #include #include +#include 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 MasterIndexList; + void setMasterIndices(const MasterIndexList &); + const MasterIndexList &getMasterIndices() const; enum Verbosity { Quiet, Normal, @@ -102,7 +108,7 @@ virtual string helpString() const = 0; typedef vector 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; diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandAlias.cpp --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandAlias.h --- 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 &, diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandCStruct.cpp --- 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); + } } } diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandCStruct.h --- 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 &); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandConfig.cpp --- 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 diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandConfig.h --- 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); }; /****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandData.cpp --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandData.h --- 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 &); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandDebug.cpp --- 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); + } } /*****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandDebug.h --- 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 &); }; /****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandDomains.cpp --- 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) << " "; } diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandDomains.h --- 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); }; /****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandDownload.cpp --- 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) { diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandDownload.h --- 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}; diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandEoe.cpp --- 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; + } } } diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandEoe.h --- 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 &); }; /****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandFoeRead.cpp --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandFoeRead.h --- 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 &); }; /****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandFoeWrite.cpp --- 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()) { diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandFoeWrite.h --- 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 &); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandGraph.cpp --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandGraph.h --- 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 &); }; /****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandMaster.cpp --- 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 of the master to use. Default: 0." + << " --master -m 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; } /*****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandMaster.h --- 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 &); }; /****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandPdos.cpp --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandPdos.h --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandRegRead.cpp --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandRegRead.h --- 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 &); }; /****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandRegWrite.cpp --- 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] == "-") { diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandRegWrite.h --- 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 &); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandSdos.cpp --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandSdos.h --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandSiiRead.cpp --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandSiiRead.h --- 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 { diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandSiiWrite.cpp --- 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 { diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandSiiWrite.h --- 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 &); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandSlaves.cpp --- 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; diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandSlaves.h --- 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 &); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandStates.cpp --- 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); + } } } diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandStates.h --- 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 &); }; /****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandUpload.cpp --- 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) { diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandUpload.h --- 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}; diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandVersion.cpp --- 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; diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandVersion.h --- 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 &); }; /****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandXml.cpp --- 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); diff -r 65781b048a47 -r ec6223c3b7ec tool/CommandXml.h --- 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 &, diff -r 65781b048a47 -r ec6223c3b7ec tool/Makefile.am --- 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 diff -r 65781b048a47 -r ec6223c3b7ec tool/MasterDevice.cpp --- 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) { diff -r 65781b048a47 -r ec6223c3b7ec tool/MasterDevice.h --- 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; }; diff -r 65781b048a47 -r ec6223c3b7ec tool/NumberListParser.cpp --- /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 +#include +#include +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; +} + +/****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/NumberListParser.h --- /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 +using namespace std; + +/*****************************************************************************/ + +class NumberListParser +{ + public: + NumberListParser(); + ~NumberListParser(); + + typedef list 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); +}; + +/****************************************************************************/ diff -r 65781b048a47 -r ec6223c3b7ec tool/main.cpp --- 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 CommandList; CommandList commandList; -MasterDevice masterDev; - string binaryBaseName; string commandName; Command::StringVector commandArgs; // option variables -unsigned int masterIndex = 0; +list 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();