Alias/Position selection.
authorFlorian Pose <fp@igh-essen.com>
Fri, 25 Jul 2008 14:19:29 +0000
changeset 1151 1fc1535dec29
parent 1150 c589b54ade01
child 1152 30f168c7f74f
Alias/Position selection.
TODO
tool/Command.cpp
tool/Command.h
tool/CommandAlias.cpp
tool/CommandAlias.h
tool/CommandDownload.cpp
tool/CommandPdos.cpp
tool/CommandPdos.h
tool/CommandSdos.cpp
tool/CommandSdos.h
tool/CommandSiiRead.cpp
tool/CommandSiiWrite.cpp
tool/CommandSlaves.cpp
tool/CommandSlaves.h
tool/CommandStates.cpp
tool/CommandUpload.cpp
tool/CommandXml.cpp
tool/CommandXml.h
tool/main.cpp
--- a/TODO	Fri Jul 25 14:14:47 2008 +0000
+++ b/TODO	Fri Jul 25 14:19:29 2008 +0000
@@ -14,8 +14,9 @@
 * Get original driver for r8169.
 * Race in jiffies frame timeout?
 * ethercat tool:
-    - Replace --slave by --position.
-    - Add --alias option.
+    - Single message for unambiguous slave in SiiRead/Write and Up/Download.
+    - Implement Alias/Position selection for configs.
+    - Update help for --alias and --position.
     - Show Pdos in 'ethercat slave -v'.
     - Accept files from stdin.
     - Display attached device's MAC address instead of ff's.
--- a/tool/Command.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/Command.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -28,6 +28,20 @@
 	verbosity = v;
 };
 
+/*****************************************************************************/
+
+void Command::setAlias(int a)
+{
+	alias = a;
+};
+
+/*****************************************************************************/
+
+void Command::setPosition(int p)
+{
+	position = p;
+};
+
 /****************************************************************************/
 
 bool Command::matchesSubstr(const string &cmd) const
@@ -78,6 +92,61 @@
     throw CommandException(s);
 }
 
+/*****************************************************************************/
+
+Command::SlaveList Command::selectedSlaves(MasterDevice &m)
+{
+    unsigned int numSlaves = m.slaveCount(), i, aliasIndex;
+    uint16_t lastAlias;
+    ec_ioctl_slave_t slave;
+    SlaveList list;
+
+    if (alias == -1) { // no alias given
+        if (position == -1) { // no alias and position given
+            // all items
+            for (i = 0; i < numSlaves; i++) {
+                m.getSlave(&slave, i);
+                list.push_back(slave);
+            }
+        } else { // no alias, but position given
+            // one item by position
+            m.getSlave(&slave, position);
+            list.push_back(slave);
+        }
+    } else { // alias given
+        if (position == -1) { // alias, but no position given
+            // take all items with a given alias
+            lastAlias = 0;
+            for (i = 0; i < numSlaves; i++) {
+                m.getSlave(&slave, i);
+                if (slave.alias) {
+                    lastAlias = slave.alias;
+                }
+                if (lastAlias == (uint16_t) alias) {
+                    list.push_back(slave);
+                }
+            }
+        } else { // alias and position given
+            lastAlias = 0;
+            aliasIndex = 0;
+            for (i = 0; i < numSlaves; i++) {
+                m.getSlave(&slave, i);
+                if (slave.alias) { // FIXME 'lock' first alias
+                    lastAlias = slave.alias;
+                    aliasIndex = 0;
+                }
+                if (lastAlias == (uint16_t) alias
+                        && aliasIndex == (unsigned int) position) {
+                    list.push_back(slave);
+                }
+                aliasIndex++;
+            }
+        }
+    }
+
+    return list;
+}
+
 /****************************************************************************/
 
 string Command::alStateString(uint8_t state)
--- a/tool/Command.h	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/Command.h	Fri Jul 25 14:19:29 2008 +0000
@@ -9,6 +9,7 @@
 
 #include <stdexcept>
 #include <vector>
+#include <list>
 using namespace std;
 
 #include "MasterDevice.h"
@@ -16,7 +17,6 @@
 /*****************************************************************************/
 
 extern unsigned int masterIndex;
-extern int slavePosition;
 extern int domainIndex;
 extern string dataTypeStr;
 extern bool force;
@@ -57,16 +57,20 @@
         Command(const string &, const string &);
 		virtual ~Command();
 
+        const string &getName() const;
+        const string &getBriefDescription() const;
+
         enum Verbosity {
             Quiet,
             Normal,
             Verbose
         };
         void setVerbosity(Verbosity);
-
-        const string &getName() const;
-        const string &getBriefDescription() const;
 		Verbosity getVerbosity() const;
+        void setAlias(int);
+        int getAlias() const;
+        void setPosition(int);
+        int getPosition() const;
 
         bool matchesSubstr(const string &) const;
         bool matchesAbbrev(const string &) const;
@@ -79,17 +83,22 @@
         static string numericInfo();
 
     protected:
+		enum {BreakAfterBytes = 16};
+
         void throwInvalidUsageException(const stringstream &);
         void throwCommandException(const stringstream &);
 
-		enum {BreakAfterBytes = 16};
-        
+        typedef list<ec_ioctl_slave_t> SlaveList;
+        SlaveList selectedSlaves(MasterDevice &);
+
         static string alStateString(uint8_t);
 
     private:
 		string name;
         string briefDesc;
         Verbosity verbosity;
+        int alias;
+        int position;
 
         Command();
 };
@@ -117,4 +126,18 @@
 
 /****************************************************************************/
 
+inline int Command::getAlias() const
+{
+    return alias;
+}
+
+/****************************************************************************/
+
+inline int Command::getPosition() const
+{
+    return position;
+}
+
+/****************************************************************************/
+
 #endif
--- a/tool/CommandAlias.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandAlias.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -57,7 +57,8 @@
     uint16_t alias;
     stringstream err, strAlias;
     int number;
-    unsigned int numSlaves, i;
+    SlaveList slaves;
+    SlaveList::const_iterator si;
 
     if (args.size() != 1) {
         err << "'" << getName() << "' takes exactly one argument!";
@@ -74,22 +75,18 @@
     }
     alias = number;
 
-    if (slavePosition == -1) {
-        if (!force) {
-            err << "This will write the alias addresses of all slaves to "
-                << alias << "! Please specify --force to proceed.";
-            throwCommandException(err);
-        }
+    m.open(MasterDevice::ReadWrite);
+    slaves = selectedSlaves(m);
+    
+    if (slaves.size() > 1 && !force) {
+        err << "This will write the alias addresses of "
+            << slaves.size() << " slaves to " << alias
+            << "! Please specify --force to proceed.";
+        throwCommandException(err);
+    }
 
-        m.open(MasterDevice::ReadWrite);
-        numSlaves = m.slaveCount();
-
-        for (i = 0; i < numSlaves; i++) {
-            writeSlaveAlias(m, i, alias);
-        }
-    } else {
-        m.open(MasterDevice::ReadWrite);
-        writeSlaveAlias(m, slavePosition, alias);
+    for (si = slaves.begin(); si != slaves.end(); si++) {
+        writeSlaveAlias(m, *si, alias);
     }
 }
 
@@ -99,17 +96,14 @@
  */
 void CommandAlias::writeSlaveAlias(
         MasterDevice &m,
-        uint16_t slavePosition,
+        const ec_ioctl_slave_t &slave,
         uint16_t alias
         )
 {
     ec_ioctl_slave_sii_t data;
-    ec_ioctl_slave_t slave;
     stringstream err;
     uint8_t crc;
 
-    m.getSlave(&slave, slavePosition);
-
     if (slave.sii_nwords < 8) {
         err << "Current SII contents are too small to set an alias "
             << "(" << slave.sii_nwords << " words)!";
@@ -117,7 +111,7 @@
     }
 
     // read first 8 SII words
-    data.slave_position = slavePosition;
+    data.slave_position = slave.position;
     data.offset = 0;
     data.nwords = 8;
     data.words = new uint16_t[data.nwords];
--- a/tool/CommandAlias.h	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandAlias.h	Fri Jul 25 14:19:29 2008 +0000
@@ -21,7 +21,8 @@
         void execute(MasterDevice &, const StringVector &);
 
     protected:
-        void writeSlaveAlias(MasterDevice &, uint16_t, uint16_t);
+        void writeSlaveAlias(MasterDevice &, const ec_ioctl_slave_t &,
+                uint16_t);
 };
 
 /****************************************************************************/
--- a/tool/CommandDownload.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandDownload.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -64,13 +64,7 @@
     ec_ioctl_slave_sdo_download_t data;
     unsigned int number;
     const CoEDataType *dataType = NULL;
-
-    if (slavePosition < 0) {
-        err << "'" << getName() << "' requires a slave! "
-            << "Please specify --slave.";
-        throwInvalidUsageException(err);
-    }
-    data.slave_position = slavePosition;
+    SlaveList slaves;
 
     if (args.size() != 3) {
         err << "'" << getName() << "' takes 3 arguments!";
@@ -96,6 +90,14 @@
     }
     data.sdo_entry_subindex = number;
 
+    m.open(MasterDevice::ReadWrite);
+    slaves = selectedSlaves(m);
+    if (slaves.size() != 1) {
+        err << slaves.size() << " slaves selected, single slave required!";
+        throwInvalidUsageException(err);
+    }
+    data.slave_position = slaves.front().position;
+
     if (dataTypeStr != "") { // data type specified
         if (!(dataType = findDataType(dataTypeStr))) {
             err << "Invalid data type '" << dataTypeStr << "'!";
@@ -104,10 +106,8 @@
     } else { // no data type specified: fetch from dictionary
         ec_ioctl_slave_sdo_entry_t entry;
 
-        m.open(MasterDevice::ReadWrite);
-
         try {
-            m.getSdoEntry(&entry, slavePosition,
+            m.getSdoEntry(&entry, data.slave_position,
                     data.sdo_index, data.sdo_entry_subindex);
         } catch (MasterDeviceException &e) {
             err << "Failed to determine Sdo entry data type. "
@@ -203,10 +203,8 @@
         throwInvalidUsageException(err);
     }
 
-    m.open(MasterDevice::ReadWrite);
-
 	try {
-			m.sdoDownload(&data);
+        m.sdoDownload(&data);
 	} catch(MasterDeviceException &e) {
         delete [] data.data;
         throw e;
--- a/tool/CommandPdos.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandPdos.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -67,16 +67,16 @@
 
 void CommandPdos::execute(MasterDevice &m, const StringVector &args)
 {
+    SlaveList slaves;
+    SlaveList::const_iterator si;
+    bool showHeader;
+    
     m.open(MasterDevice::Read);
+    slaves = selectedSlaves(m);
+    showHeader = slaves.size() > 1;
 
-    if (slavePosition == -1) {
-        unsigned int numSlaves = m.slaveCount(), i;
-
-        for (i = 0; i < numSlaves; i++) {
-            listSlavePdos(m, i, true);
-        }
-    } else {
-        listSlavePdos(m, slavePosition, false);
+    for (si = slaves.begin(); si != slaves.end(); si++) {
+        listSlavePdos(m, *si, showHeader);
     }
 }
 
@@ -84,23 +84,20 @@
 
 void CommandPdos::listSlavePdos(
 		MasterDevice &m,
-		uint16_t slavePosition,
-		bool withHeader
+        const ec_ioctl_slave_t &slave,
+		bool showHeader
 		)
 {
-    ec_ioctl_slave_t slave;
     ec_ioctl_slave_sync_t sync;
     ec_ioctl_slave_sync_pdo_t pdo;
     ec_ioctl_slave_sync_pdo_entry_t entry;
     unsigned int i, j, k;
     
-    m.getSlave(&slave, slavePosition);
-
-    if (withHeader)
-        cout << "=== Slave " << slavePosition << " ===" << endl;
+    if (showHeader)
+        cout << "=== Slave " << slave.position << " ===" << endl;
 
     for (i = 0; i < slave.sync_count; i++) {
-        m.getSync(&sync, slavePosition, i);
+        m.getSync(&sync, slave.position, i);
 
         cout << "SM" << i << ":"
             << " PhysAddr 0x"
@@ -115,7 +112,7 @@
             << endl;
 
         for (j = 0; j < sync.pdo_count; j++) {
-            m.getPdo(&pdo, slavePosition, i, j);
+            m.getPdo(&pdo, slave.position, i, j);
 
             cout << "  " << (sync.control_register & 0x04 ? "R" : "T")
                 << "xPdo 0x"
@@ -127,7 +124,7 @@
                 continue;
 
             for (k = 0; k < pdo.entry_count; k++) {
-                m.getPdoEntry(&entry, slavePosition, i, j, k);
+                m.getPdoEntry(&entry, slave.position, i, j, k);
 
                 cout << "    Pdo entry 0x"
                     << hex << setfill('0')
--- a/tool/CommandPdos.h	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandPdos.h	Fri Jul 25 14:19:29 2008 +0000
@@ -21,7 +21,7 @@
         void execute(MasterDevice &, const StringVector &);
 
     protected:
-		void listSlavePdos(MasterDevice &, uint16_t, bool);
+		void listSlavePdos(MasterDevice &, const ec_ioctl_slave_t &, bool);
 };
 
 /****************************************************************************/
--- a/tool/CommandSdos.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandSdos.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -58,16 +58,16 @@
 
 void CommandSdos::execute(MasterDevice &m, const StringVector &args)
 {
+    SlaveList slaves;
+    SlaveList::const_iterator si;
+    bool showHeader;
+
     m.open(MasterDevice::Read);
+    slaves = selectedSlaves(m);
+    showHeader = slaves.size() > 1;
 
-    if (slavePosition == -1) {
-        unsigned int numSlaves = m.slaveCount(), i;
-
-        for (i = 0; i < numSlaves; i++) {
-            listSlaveSdos(m, i, true);
-        }
-    } else {
-        listSlaveSdos(m, slavePosition, false);
+    for (si = slaves.begin(); si != slaves.end(); si++) {
+        listSlaveSdos(m, *si, showHeader);
     }
 }
 
@@ -75,23 +75,20 @@
 
 void CommandSdos::listSlaveSdos(
 		MasterDevice &m,
-		uint16_t slavePosition,
-		bool withHeader
+        const ec_ioctl_slave_t &slave,
+		bool showHeader
 		)
 {
-    ec_ioctl_slave_t slave;
     ec_ioctl_slave_sdo_t sdo;
     ec_ioctl_slave_sdo_entry_t entry;
     unsigned int i, j;
     const CoEDataType *d;
     
-    m.getSlave(&slave, slavePosition);
-
-    if (withHeader)
-        cout << "=== Slave " << slavePosition << " ===" << endl;
+    if (showHeader)
+        cout << "=== Slave " << slave.position << " ===" << endl;
 
     for (i = 0; i < slave.sdo_count; i++) {
-        m.getSdo(&sdo, slavePosition, i);
+        m.getSdo(&sdo, slave.position, i);
 
         cout << "Sdo 0x"
             << hex << setfill('0')
@@ -102,7 +99,7 @@
             continue;
 
         for (j = 0; j <= sdo.max_subindex; j++) {
-            m.getSdoEntry(&entry, slavePosition, -i, j);
+            m.getSdoEntry(&entry, slave.position, -i, j);
 
             cout << "  0x" << hex << setfill('0')
                 << setw(4) << sdo.sdo_index << ":"
--- a/tool/CommandSdos.h	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandSdos.h	Fri Jul 25 14:19:29 2008 +0000
@@ -21,7 +21,7 @@
         void execute(MasterDevice &, const StringVector &);
 
     protected:
-		void listSlaveSdos(MasterDevice &, uint16_t, bool);
+		void listSlaveSdos(MasterDevice &, const ec_ioctl_slave_t &, bool);
 };
 
 /****************************************************************************/
--- a/tool/CommandSiiRead.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandSiiRead.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -50,29 +50,30 @@
 
 void CommandSiiRead::execute(MasterDevice &m, const StringVector &args)
 {
+    SlaveList slaves;
+    ec_ioctl_slave_t *slave;
     ec_ioctl_slave_sii_t data;
-    ec_ioctl_slave_t slave;
     unsigned int i;
     const uint16_t *categoryHeader;
     uint16_t categoryType, categorySize;
     stringstream err;
 
-    if (slavePosition < 0) {
-        err << "'" << getName() << "' requires a slave! "
-            << "Please specify --slave.";
+    m.open(MasterDevice::Read);
+    slaves = selectedSlaves(m);
+
+    if (slaves.size() != 1) {
+        err << "'" << getName() << "' requires a single slave ("
+            << slaves.size() << " selected).";
         throwInvalidUsageException(err);
     }
-    data.slave_position = slavePosition;
+    slave = &slaves.front();
+    data.slave_position = slave->position;
 
-    m.open(MasterDevice::Read);
-
-    m.getSlave(&slave, slavePosition);
-
-    if (!slave.sii_nwords)
+    if (!slave->sii_nwords)
         return;
 
     data.offset = 0;
-    data.nwords = slave.sii_nwords;
+    data.nwords = slave->sii_nwords;
     data.words = new uint16_t[data.nwords];
 
 	try {
--- a/tool/CommandSiiWrite.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandSiiWrite.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -51,6 +51,7 @@
 
 void CommandSiiWrite::execute(MasterDevice &m, const StringVector &args)
 {
+    SlaveList slaves;
     stringstream err;
     ec_ioctl_slave_sii_t data;
     ifstream file;
@@ -59,12 +60,14 @@
     uint16_t categoryType, categorySize;
     uint8_t crc;
 
-    if (slavePosition < 0) {
-        err << "'" << getName() << "' requires a slave! "
-            << "Please specify --slave.";
+    slaves = selectedSlaves(m);
+
+    if (slaves.size() != 1) {
+        err << "'" << getName() << "' requires a single slave ("
+            << slaves.size() << " selected).";
         throwInvalidUsageException(err);
     }
-    data.slave_position = slavePosition;
+    data.slave_position = slaves.front().position;
 
     if (args.size() != 1) {
         err << "'" << getName() << "' takes exactly one argument!";
--- a/tool/CommandSlaves.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandSlaves.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -65,20 +65,15 @@
 
 void CommandSlaves::execute(MasterDevice &m, const StringVector &args)
 {
+    SlaveList slaves;
+    
     m.open(MasterDevice::Read);
+    slaves = selectedSlaves(m);
 
     if (getVerbosity() == Verbose) {
-        if (slavePosition == -1) {
-            unsigned int numSlaves = m.slaveCount(), i;
-
-            for (i = 0; i < numSlaves; i++) {
-                showSlave(m, i);
-            }
-        } else {
-            showSlave(m, slavePosition);
-        }
+        showSlaves(m, slaves);
     } else {
-        listSlaves(m, slavePosition);
+        listSlaves(m, slaves);
     }
 }
 
@@ -86,7 +81,7 @@
 
 void CommandSlaves::listSlaves(
         MasterDevice &m,
-        int slavePosition
+        const SlaveList &slaves
         )
 {
     unsigned int numSlaves, i;
@@ -112,7 +107,7 @@
             aliasIndex = 0;
         }
 
-        if (slavePosition == -1 || i == (unsigned int) slavePosition) {
+        if (slaveInList(slave, slaves)) {
             str << dec << i;
             info.pos = str.str();
             str.clear();
@@ -169,109 +164,127 @@
 
 /****************************************************************************/
 
-void CommandSlaves::showSlave(
+void CommandSlaves::showSlaves(
         MasterDevice &m,
-        uint16_t slavePosition
+        const SlaveList &slaves
         )
 {
-    ec_ioctl_slave_t slave;
+    SlaveList::const_iterator si;
     list<string> protoList;
     list<string>::const_iterator protoIter;
-    
-    m.getSlave(&slave, slavePosition);
-        
-    cout << "=== Slave " << dec << slavePosition << " ===" << endl;
-    
-    if (slave.alias)
-        cout << "Alias: " << slave.alias << endl;
-
-    cout
-        << "State: " << alStateString(slave.al_state) << endl
-        << "Flag: " << (slave.error_flag ? 'E' : '+') << endl
-        << "Identity:" << endl
-        << "  Vendor Id:       0x"
-        << hex << setfill('0')
-        << setw(8) << slave.vendor_id << endl
-        << "  Product code:    0x"
-        << setw(8) << slave.product_code << endl
-        << "  Revision number: 0x"
-        << setw(8) << slave.revision_number << endl
-        << "  Serial number:   0x"
-        << setw(8) << slave.serial_number << endl;
-
-    if (slave.mailbox_protocols) {
-        cout << "Mailboxes:" << endl
-        << "  RX: 0x"
-        << hex << setw(4) << slave.rx_mailbox_offset << "/"
-        << dec << slave.rx_mailbox_size
-        << ", TX: 0x"
-        << hex << setw(4) << slave.tx_mailbox_offset << "/"
-        << dec << slave.tx_mailbox_size << endl
-        << "  Supported protocols: ";
-
-        if (slave.mailbox_protocols & EC_MBOX_AOE) {
-            protoList.push_back("AoE");
-        }
-        if (slave.mailbox_protocols & EC_MBOX_EOE) {
-            protoList.push_back("EoE");
-        }
-        if (slave.mailbox_protocols & EC_MBOX_COE) {
-            protoList.push_back("CoE");
-        }
-        if (slave.mailbox_protocols & EC_MBOX_FOE) {
-            protoList.push_back("FoE");
-        }
-        if (slave.mailbox_protocols & EC_MBOX_SOE) {
-            protoList.push_back("SoE");
-        }
-        if (slave.mailbox_protocols & EC_MBOX_VOE) {
-            protoList.push_back("VoE");
-        }
-
-        for (protoIter = protoList.begin(); protoIter != protoList.end();
-                protoIter++) {
-            if (protoIter != protoList.begin())
-                cout << ", ";
-            cout << *protoIter;
-        }
-        cout << endl;
-    }
-
-    if (slave.has_general_category) {
-        cout << "General:" << endl
-            << "  Group: " << slave.group << endl
-            << "  Image name: " << slave.image << endl
-            << "  Order number: " << slave.order << endl
-            << "  Device name: " << slave.name << endl;
-
-        if (slave.mailbox_protocols & EC_MBOX_COE) {
-            cout << "  CoE details:" << endl
-                << "    Enable Sdo: "
-                << (slave.coe_details.enable_sdo ? "yes" : "no") << endl
-                << "    Enable Sdo Info: "
-                << (slave.coe_details.enable_sdo_info ? "yes" : "no") << endl
-                << "    Enable Pdo Assign: "
-                << (slave.coe_details.enable_pdo_assign
-                        ? "yes" : "no") << endl
-                << "    Enable Pdo Configuration: "
-                << (slave.coe_details.enable_pdo_configuration
-                        ? "yes" : "no") << endl
-                << "    Enable Upload at startup: "
-                << (slave.coe_details.enable_upload_at_startup
-                        ? "yes" : "no") << endl
-                << "    Enable Sdo complete access: "
-                << (slave.coe_details.enable_sdo_complete_access
-                        ? "yes" : "no") << endl;
-        }
-
-        cout << "  Flags:" << endl
-            << "    Enable SafeOp: "
-            << (slave.general_flags.enable_safeop ? "yes" : "no") << endl
-            << "    Enable notLRW: "
-            << (slave.general_flags.enable_not_lrw ? "yes" : "no") << endl
-            << "  Current consumption: "
-            << dec << slave.current_on_ebus << " mA" << endl;
-    }
+
+    for (si = slaves.begin(); si != slaves.end(); si++) {
+        cout << "=== Slave " << dec << si->position << " ===" << endl;
+
+        if (si->alias)
+            cout << "Alias: " << si->alias << endl;
+
+        cout
+            << "State: " << alStateString(si->al_state) << endl
+            << "Flag: " << (si->error_flag ? 'E' : '+') << endl
+            << "Identity:" << endl
+            << "  Vendor Id:       0x"
+            << hex << setfill('0')
+            << setw(8) << si->vendor_id << endl
+            << "  Product code:    0x"
+            << setw(8) << si->product_code << endl
+            << "  Revision number: 0x"
+            << setw(8) << si->revision_number << endl
+            << "  Serial number:   0x"
+            << setw(8) << si->serial_number << endl;
+
+        if (si->mailbox_protocols) {
+            cout << "Mailboxes:" << endl
+                << "  RX: 0x"
+                << hex << setw(4) << si->rx_mailbox_offset << "/"
+                << dec << si->rx_mailbox_size
+                << ", TX: 0x"
+                << hex << setw(4) << si->tx_mailbox_offset << "/"
+                << dec << si->tx_mailbox_size << endl
+                << "  Supported protocols: ";
+
+            if (si->mailbox_protocols & EC_MBOX_AOE) {
+                protoList.push_back("AoE");
+            }
+            if (si->mailbox_protocols & EC_MBOX_EOE) {
+                protoList.push_back("EoE");
+            }
+            if (si->mailbox_protocols & EC_MBOX_COE) {
+                protoList.push_back("CoE");
+            }
+            if (si->mailbox_protocols & EC_MBOX_FOE) {
+                protoList.push_back("FoE");
+            }
+            if (si->mailbox_protocols & EC_MBOX_SOE) {
+                protoList.push_back("SoE");
+            }
+            if (si->mailbox_protocols & EC_MBOX_VOE) {
+                protoList.push_back("VoE");
+            }
+
+            for (protoIter = protoList.begin(); protoIter != protoList.end();
+                    protoIter++) {
+                if (protoIter != protoList.begin())
+                    cout << ", ";
+                cout << *protoIter;
+            }
+            cout << endl;
+        }
+
+        if (si->has_general_category) {
+            cout << "General:" << endl
+                << "  Group: " << si->group << endl
+                << "  Image name: " << si->image << endl
+                << "  Order number: " << si->order << endl
+                << "  Device name: " << si->name << endl;
+
+            if (si->mailbox_protocols & EC_MBOX_COE) {
+                cout << "  CoE details:" << endl
+                    << "    Enable Sdo: "
+                    << (si->coe_details.enable_sdo ? "yes" : "no") << endl
+                    << "    Enable Sdo Info: "
+                    << (si->coe_details.enable_sdo_info ? "yes" : "no") << endl
+                    << "    Enable Pdo Assign: "
+                    << (si->coe_details.enable_pdo_assign
+                            ? "yes" : "no") << endl
+                    << "    Enable Pdo Configuration: "
+                    << (si->coe_details.enable_pdo_configuration
+                            ? "yes" : "no") << endl
+                    << "    Enable Upload at startup: "
+                    << (si->coe_details.enable_upload_at_startup
+                            ? "yes" : "no") << endl
+                    << "    Enable Sdo complete access: "
+                    << (si->coe_details.enable_sdo_complete_access
+                            ? "yes" : "no") << endl;
+            }
+
+            cout << "  Flags:" << endl
+                << "    Enable SafeOp: "
+                << (si->general_flags.enable_safeop ? "yes" : "no") << endl
+                << "    Enable notLRW: "
+                << (si->general_flags.enable_not_lrw ? "yes" : "no") << endl
+                << "  Current consumption: "
+                << dec << si->current_on_ebus << " mA" << endl;
+        }
+    }
+}
+
+/****************************************************************************/
+
+bool CommandSlaves::slaveInList(
+        const ec_ioctl_slave_t &slave,
+        const SlaveList &slaves
+        )
+{
+    SlaveList::const_iterator si;
+
+    for (si = slaves.begin(); si != slaves.end(); si++) {
+        if (si->position == slave.position) {
+            return true;
+        }
+    }
+
+    return false;
 }
 
 /*****************************************************************************/
--- a/tool/CommandSlaves.h	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandSlaves.h	Fri Jul 25 14:19:29 2008 +0000
@@ -30,8 +30,10 @@
             string name;
         };
 
-        void listSlaves(MasterDevice &, int);
-        void showSlave(MasterDevice &, uint16_t);
+        void listSlaves(MasterDevice &, const SlaveList &);
+        void showSlaves(MasterDevice &, const SlaveList &);
+        
+        static bool slaveInList( const ec_ioctl_slave_t &, const SlaveList &);
 };
 
 /****************************************************************************/
--- a/tool/CommandStates.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandStates.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -42,6 +42,8 @@
 
 void CommandStates::execute(MasterDevice &m, const StringVector &args)
 {
+    SlaveList slaves;
+    SlaveList::const_iterator si;
     stringstream err;
     string stateStr;
     uint8_t state = 0x00;
@@ -69,13 +71,10 @@
     }
 
     m.open(MasterDevice::ReadWrite);
+    slaves = selectedSlaves(m);
 
-    if (slavePosition == -1) {
-        unsigned int i, numSlaves = m.slaveCount();
-        for (i = 0; i < numSlaves; i++)
-            m.requestState(i, state);
-    } else {
-        m.requestState(slavePosition, state);
+    for (si = slaves.begin(); si != slaves.end(); si++) {
+        m.requestState(si->position, state);
     }
 }
 
--- a/tool/CommandUpload.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandUpload.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -58,19 +58,13 @@
 
 void CommandUpload::execute(MasterDevice &m, const StringVector &args)
 {
+    SlaveList slaves;
     stringstream err, strIndex, strSubIndex;
     int sval;
     ec_ioctl_slave_sdo_upload_t data;
     unsigned int uval;
     const CoEDataType *dataType = NULL;
 
-    if (slavePosition < 0) {
-        err << "'" << getName() << "' requires a slave! "
-            << "Please specify --slave.";
-        throwInvalidUsageException(err);
-    }
-    data.slave_position = slavePosition;
-
     if (args.size() != 2) {
         err << "'" << getName() << "' takes two arguments!";
         throwInvalidUsageException(err);
@@ -95,6 +89,14 @@
     }
     data.sdo_entry_subindex = uval;
 
+    m.open(MasterDevice::Read);
+    slaves = selectedSlaves(m);
+    if (slaves.size() != 1) {
+        err << slaves.size() << " slaves selected, single slave required!";
+        throwInvalidUsageException(err);
+    }
+    data.slave_position = slaves.front().position;
+
     if (dataTypeStr != "") { // data type specified
         if (!(dataType = findDataType(dataTypeStr))) {
             err << "Invalid data type '" << dataTypeStr << "'!";
@@ -103,10 +105,8 @@
     } else { // no data type specified: fetch from dictionary
         ec_ioctl_slave_sdo_entry_t entry;
 
-        m.open(MasterDevice::Read);
-
         try {
-            m.getSdoEntry(&entry, slavePosition,
+            m.getSdoEntry(&entry, data.slave_position,
                     data.sdo_index, data.sdo_entry_subindex);
         } catch (MasterDeviceException &e) {
             err << "Failed to determine Sdo entry data type. "
@@ -129,8 +129,6 @@
 
     data.target = new uint8_t[data.target_size + 1];
 
-    m.open(MasterDevice::Read);
-
 	try {
 		m.sdoUpload(&data);
 	} catch (MasterDeviceException &e) {
--- a/tool/CommandXml.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandXml.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -45,32 +45,30 @@
 
 void CommandXml::execute(MasterDevice &m, const StringVector &args)
 {
+    SlaveList slaves;
+    SlaveList::const_iterator si;
+
     m.open(MasterDevice::Read);
+    slaves = selectedSlaves(m);
 
-    if (slavePosition == -1) {
-        unsigned int numSlaves = m.slaveCount(), i;
-
-        for (i = 0; i < numSlaves; i++) {
-            generateSlaveXml(m, i);
-        }
-    } else {
-        generateSlaveXml(m, slavePosition);
+    for (si = slaves.begin(); si != slaves.end(); si++) {
+        generateSlaveXml(m, *si);
     }
 }
 
 /****************************************************************************/
 
-void CommandXml::generateSlaveXml(MasterDevice &m, uint16_t slavePosition)
+void CommandXml::generateSlaveXml(
+        MasterDevice &m,
+        const ec_ioctl_slave_t &slave
+        )
 {
-    ec_ioctl_slave_t slave;
     ec_ioctl_slave_sync_t sync;
     ec_ioctl_slave_sync_pdo_t pdo;
     string pdoType;
     ec_ioctl_slave_sync_pdo_entry_t entry;
     unsigned int i, j, k;
     
-    m.getSlave(&slave, slavePosition);
-
     cout
         << "<?xml version=\"1.0\" ?>" << endl
         << "  <EtherCATInfo>" << endl
@@ -95,7 +93,7 @@
     }
 
     for (i = 0; i < slave.sync_count; i++) {
-        m.getSync(&sync, slavePosition, i);
+        m.getSync(&sync, slave.position, i);
 
         cout
             << "          <Sm Enable=\"" << dec << (unsigned int) sync.enable
@@ -106,10 +104,10 @@
     }
 
     for (i = 0; i < slave.sync_count; i++) {
-        m.getSync(&sync, slavePosition, i);
+        m.getSync(&sync, slave.position, i);
 
         for (j = 0; j < sync.pdo_count; j++) {
-            m.getPdo(&pdo, slavePosition, i, j);
+            m.getPdo(&pdo, slave.position, i, j);
             pdoType = (sync.control_register & 0x04 ? "R" : "T");
             pdoType += "xPdo";
 
@@ -122,7 +120,7 @@
                 << "            <Name>" << pdo.name << "</Name>" << endl;
 
             for (k = 0; k < pdo.entry_count; k++) {
-                m.getPdoEntry(&entry, slavePosition, i, j, k);
+                m.getPdoEntry(&entry, slave.position, i, j, k);
 
                 cout
                     << "            <Entry>" << endl
--- a/tool/CommandXml.h	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/CommandXml.h	Fri Jul 25 14:19:29 2008 +0000
@@ -21,7 +21,7 @@
         void execute(MasterDevice &, const StringVector &);
 
     protected:
-        void generateSlaveXml(MasterDevice &, uint16_t);
+        void generateSlaveXml(MasterDevice &, const ec_ioctl_slave_t &);
 };
 
 /****************************************************************************/
--- a/tool/main.cpp	Fri Jul 25 14:14:47 2008 +0000
+++ b/tool/main.cpp	Fri Jul 25 14:19:29 2008 +0000
@@ -41,6 +41,7 @@
 // option variables
 unsigned int masterIndex = 0;
 int slavePosition = -1;
+int slaveAlias = -1;
 int domainIndex = -1;
 string dataTypeStr;
 Command::Verbosity verbosity = Command::Normal;
@@ -98,20 +99,22 @@
 	char *remainder;
 
     static struct option longOptions[] = {
-        //name,     has_arg,           flag, val
-        {"master",  required_argument, NULL, 'm'},
-        {"slave",   required_argument, NULL, 's'},
-        {"domain",  required_argument, NULL, 'd'},
-        {"type",    required_argument, NULL, 't'},
-        {"force",   no_argument,       NULL, 'f'},
-        {"quiet",   no_argument,       NULL, 'q'},
-        {"verbose", no_argument,       NULL, 'v'},
-        {"help",    no_argument,       NULL, 'h'},
+        //name,      has_arg,           flag, val
+        {"master",   required_argument, NULL, 'm'},
+        {"alias",    required_argument, NULL, 'a'},
+        {"position", required_argument, NULL, 'p'},
+        {"domain",   required_argument, NULL, 'd'},
+        {"type",     required_argument, NULL, 't'},
+        {"force",    no_argument,       NULL, 'f'},
+        {"quiet",    no_argument,       NULL, 'q'},
+        {"verbose",  no_argument,       NULL, 'v'},
+        {"help",     no_argument,       NULL, 'h'},
         {}
     };
 
     do {
-        c = getopt_long(argc, argv, "m:s:d:t:fqvh", longOptions, &optionIndex);
+        c = getopt_long(argc, argv, "m:a:p:d:t:fqvh",
+                longOptions, &optionIndex);
 
         switch (c) {
             case 'm':
@@ -124,7 +127,22 @@
 				masterIndex = number;
                 break;
 
-            case 's':
+            case 'a':
+                if (!strcmp(optarg, "all")) {
+                    slaveAlias = -1;
+                } else {
+                    number = strtoul(optarg, &remainder, 0);
+                    if (remainder == optarg || *remainder
+                            || number < 0 || number > 0xFFFF) {
+                        cerr << "Invalid slave alias " << optarg << "!"
+                            << endl << endl << usage();
+                        exit(1);
+                    }
+                    slaveAlias = number;
+                }
+                break;
+
+            case 'p':
                 if (!strcmp(optarg, "all")) {
                     slavePosition = -1;
                 } else {
@@ -265,6 +283,8 @@
             if (!helpRequested) {
                 try {
                     cmd->setVerbosity(verbosity);
+                    cmd->setAlias(slaveAlias);
+                    cmd->setPosition(slavePosition);
                     cmd->execute(masterDev, commandArgs);
                 } catch (InvalidUsageException &e) {
                     cerr << e.what() << endl << endl;