Request slave state(s) with 'ethercat state'; removed sysfs state file.
authorFlorian Pose <fp@igh-essen.com>
Fri, 06 Jun 2008 08:12:34 +0000
changeset 960 36e460ffbb5e
parent 959 676e15bc5f27
child 961 8aa60dd6cbc7
Request slave state(s) with 'ethercat state'; removed sysfs state file.
TODO
master/cdev.c
master/ioctl.h
master/slave.c
tools/Master.cpp
tools/Master.h
tools/main.cpp
--- a/TODO	Thu Jun 05 15:58:25 2008 +0000
+++ b/TODO	Fri Jun 06 08:12:34 2008 +0000
@@ -8,6 +8,7 @@
 
 Version 1.4.0:
 
+* Slaves as array.
 * Replace all Sysfs files via the new ethercat tool.
     - Sdo info
     - Sdo entry info
@@ -15,7 +16,6 @@
     - Sdo entry value write
     - Slave alias write
     - Slave SII write
-    - Slave state request
     - Slave info (flags, mailbox, general) 
     - Config info (alias, position, type, Pdos, Sdos)
 * Remove the end state of the master state machine.
--- a/master/cdev.c	Thu Jun 05 15:58:25 2008 +0000
+++ b/master/cdev.c	Fri Jun 06 08:12:34 2008 +0000
@@ -478,6 +478,27 @@
             }
             break;
 
+        case EC_IOCTL_SLAVE_STATE:
+            {
+                ec_ioctl_slave_state_t data;
+                ec_slave_t *slave;
+
+                if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
+                    retval = -EFAULT;
+                    break;
+                }
+                
+                if (!(slave = ec_master_find_slave(
+                                master, 0, data.slave_position))) {
+                    EC_ERR("Slave %u does not exist!\n", data.slave_position);
+                    retval = -EINVAL;
+                    break;
+                }
+
+                ec_slave_request_state(slave, data.requested_state);
+                break;
+            }
+
         default:
             retval = -ENOIOCTLCMD;
     }
--- a/master/ioctl.h	Thu Jun 05 15:58:25 2008 +0000
+++ b/master/ioctl.h	Fri Jun 06 08:12:34 2008 +0000
@@ -54,6 +54,7 @@
 	EC_IOCTL_DOMAIN_FMMU,
 	EC_IOCTL_DATA,
     EC_IOCTL_SET_DEBUG,
+    EC_IOCTL_SLAVE_STATE,
 };
 
 /*****************************************************************************/
@@ -179,4 +180,12 @@
 
 /*****************************************************************************/
 
+typedef struct {
+    // inputs
+	uint16_t slave_position;
+    uint8_t requested_state;
+} ec_ioctl_slave_state_t;
+
+/*****************************************************************************/
+
 #endif
--- a/master/slave.c	Thu Jun 05 15:58:25 2008 +0000
+++ b/master/slave.c	Fri Jun 06 08:12:34 2008 +0000
@@ -66,13 +66,11 @@
 /** \cond */
 
 EC_SYSFS_READ_ATTR(info);
-EC_SYSFS_READ_WRITE_ATTR(state);
 EC_SYSFS_READ_WRITE_ATTR(sii);
 EC_SYSFS_READ_WRITE_ATTR(alias);
 
 static struct attribute *def_attrs[] = {
     &attr_info,
-    &attr_state,
     &attr_sii,
     &attr_alias,
     NULL,
@@ -1082,22 +1080,7 @@
 
     if (attr == &attr_info) {
         return ec_slave_info(slave, buffer);
-    }
-    else if (attr == &attr_state) {
-        switch (slave->current_state) {
-            case EC_SLAVE_STATE_INIT:
-                return sprintf(buffer, "INIT\n");
-            case EC_SLAVE_STATE_PREOP:
-                return sprintf(buffer, "PREOP\n");
-            case EC_SLAVE_STATE_SAFEOP:
-                return sprintf(buffer, "SAFEOP\n");
-            case EC_SLAVE_STATE_OP:
-                return sprintf(buffer, "OP\n");
-            default:
-                return sprintf(buffer, "UNKNOWN\n");
-        }
-    }
-    else if (attr == &attr_sii) {
+    } else if (attr == &attr_sii) {
         if (slave->sii_data) {
             if (slave->sii_size > PAGE_SIZE) {
                 EC_ERR("SII contents of slave %u exceed 1 page (%u/%u).\n",
@@ -1109,8 +1092,7 @@
                 return slave->sii_size;
             }
         }
-    }
-    else if (attr == &attr_alias) {
+    } else if (attr == &attr_alias) {
         return sprintf(buffer, "%u\n", slave->sii.alias);
     }
 
@@ -1132,30 +1114,9 @@
 {
     ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
 
-    if (attr == &attr_state) {
-        char state[EC_STATE_STRING_SIZE];
-        if (!strcmp(buffer, "INIT\n"))
-            ec_slave_request_state(slave, EC_SLAVE_STATE_INIT);
-        else if (!strcmp(buffer, "PREOP\n"))
-            ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
-        else if (!strcmp(buffer, "SAFEOP\n"))
-            ec_slave_request_state(slave, EC_SLAVE_STATE_SAFEOP);
-        else if (!strcmp(buffer, "OP\n"))
-            ec_slave_request_state(slave, EC_SLAVE_STATE_OP);
-        else {
-            EC_ERR("Invalid slave state \"%s\"!\n", buffer);
-            return -EINVAL;
-        }
-
-        ec_state_string(slave->requested_state, state);
-        EC_INFO("Accepted new state %s for slave %u.\n",
-                state, slave->ring_position);
-        return size;
-    }
-    else if (attr == &attr_sii) {
+    if (attr == &attr_sii) {
         return ec_slave_write_sii(slave, buffer, size);
-    }
-    else if (attr == &attr_alias) {
+    } else if (attr == &attr_alias) {
         return ec_slave_write_alias(slave, buffer, size);
     }
 
--- a/tools/Master.cpp	Thu Jun 05 15:58:25 2008 +0000
+++ b/tools/Master.cpp	Fri Jun 06 08:12:34 2008 +0000
@@ -13,6 +13,7 @@
 #include <iostream>
 #include <iomanip>
 #include <sstream>
+#include <cctype> // toupper()
 using namespace std;
 
 #include "Master.h"
@@ -223,6 +224,49 @@
 
 /****************************************************************************/
 
+void Master::requestStates(
+        int slavePosition,
+        const vector<string> &commandArgs
+        )
+{
+    string stateStr;
+    uint8_t state;
+    
+    if (commandArgs.size() != 1) {
+        stringstream err;
+        err << "'state' takes exactly one argument!";
+        throw MasterException(err.str());
+    }
+
+    stateStr = commandArgs[0];
+    transform(stateStr.begin(), stateStr.end(),
+            stateStr.begin(), (int (*) (int)) std::toupper);
+
+    if (stateStr == "INIT") {
+        state = 0x01;
+    } else if (stateStr == "PREOP") {
+        state = 0x02;
+    } else if (stateStr == "SAFEOP") {
+        state = 0x04;
+    } else if (stateStr == "OP") {
+        state = 0x08;
+    } else {
+        stringstream err;
+        err << "Invalid state '" << commandArgs[0] << "'!";
+        throw MasterException(err.str());
+    }
+
+    if (slavePosition == -1) {
+        unsigned int i, numSlaves = slaveCount();
+        for (i = 0; i < numSlaves; i++)
+            requestState(i, state);
+    } else {
+        requestState(slavePosition, state);
+    }
+}
+
+/****************************************************************************/
+
 void Master::generateXml(int slavePosition)
 {
     if (slavePosition == -1) {
@@ -673,6 +717,29 @@
 
 /****************************************************************************/
 
+void Master::requestState(
+        uint16_t slavePosition,
+        uint8_t state
+        )
+{
+    ec_ioctl_slave_state_t data;
+
+    data.slave_position = slavePosition;
+    data.requested_state = state;
+    
+    if (ioctl(fd, EC_IOCTL_SLAVE_STATE, &data)) {
+        stringstream err;
+        err << "Failed to request slave state: ";
+        if (errno == EINVAL)
+            err << "Slave " << slavePosition << " does not exist!";
+        else
+            err << strerror(errno);
+        throw MasterException(err.str());
+    }
+}
+
+/****************************************************************************/
+
 string Master::slaveState(uint8_t state)
 {
     switch (state) {
--- a/tools/Master.h	Thu Jun 05 15:58:25 2008 +0000
+++ b/tools/Master.h	Fri Jun 06 08:12:34 2008 +0000
@@ -48,6 +48,7 @@
         void listSlaves();
         void showMaster();
         void listPdos(int);
+        void requestStates(int, const vector<string> &);
         void generateXml(int);
 
     protected:
@@ -68,6 +69,7 @@
         void getPdo(ec_ioctl_pdo_t *, uint16_t, uint8_t, uint8_t);
         void getPdoEntry(ec_ioctl_pdo_entry_t *, uint16_t, uint8_t, uint8_t,
                 uint8_t);
+        void requestState(uint16_t, uint8_t);
 
         static string slaveState(uint8_t);
         
--- a/tools/main.cpp	Thu Jun 05 15:58:25 2008 +0000
+++ b/tools/main.cpp	Fri Jun 06 08:12:34 2008 +0000
@@ -39,6 +39,7 @@
         << "  list (ls, slaves)  List all slaves (former 'lsec')." << endl
         << "  master             Show master information." << endl
         << "  pdos               List Pdo mapping of given slaves." << endl
+        << "  state              Request slave state(s)." << endl
         << "  xml                Generate slave information xml." << endl
 		<< "Global options:" << endl
         << "  --master  -m <master>  Index of the master to use. Default: "
@@ -162,6 +163,8 @@
             master.showMaster();
         } else if (command == "pdos") {
             master.listPdos(slavePosition);
+        } else if (command == "state") {
+            master.requestStates(slavePosition, commandArgs);
         } else if (command == "xml") {
             master.generateXml(slavePosition);
         } else {