From 7a341066cf8a99f0b7fb166cdb8976dfae090c9d Mon Sep 17 00:00:00 2001 From: Florian Pose <fp@igh-essen.com> Date: Fri, 6 Jun 2008 08:12:34 +0000 Subject: [PATCH] Request slave state(s) with 'ethercat state'; removed sysfs state file. --- TODO | 2 +- master/cdev.c | 21 +++++++++++++++ master/ioctl.h | 9 +++++++ master/slave.c | 47 +++------------------------------ tools/Master.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/Master.h | 2 ++ tools/main.cpp | 3 +++ 7 files changed, 107 insertions(+), 44 deletions(-) diff --git a/TODO b/TODO index 459a3338..02a6507d 100644 --- a/TODO +++ b/TODO @@ -8,6 +8,7 @@ $Id$ 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 @@ Version 1.4.0: - 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. diff --git a/master/cdev.c b/master/cdev.c index 3d2f00a2..021ed9a0 100644 --- a/master/cdev.c +++ b/master/cdev.c @@ -478,6 +478,27 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } 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; } diff --git a/master/ioctl.h b/master/ioctl.h index 8e574721..1e433d74 100644 --- a/master/ioctl.h +++ b/master/ioctl.h @@ -54,6 +54,7 @@ enum { EC_IOCTL_DOMAIN_FMMU, EC_IOCTL_DATA, EC_IOCTL_SET_DEBUG, + EC_IOCTL_SLAVE_STATE, }; /*****************************************************************************/ @@ -179,4 +180,12 @@ typedef struct { /*****************************************************************************/ +typedef struct { + // inputs + uint16_t slave_position; + uint8_t requested_state; +} ec_ioctl_slave_state_t; + +/*****************************************************************************/ + #endif diff --git a/master/slave.c b/master/slave.c index 7d6050d4..39525938 100644 --- a/master/slave.c +++ b/master/slave.c @@ -66,13 +66,11 @@ char *ec_slave_sii_string(ec_slave_t *, unsigned int); /** \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 @@ ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */ 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 @@ ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */ 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 @@ ssize_t ec_store_slave_attribute(struct kobject *kobj, /**< slave's kobject */ { 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); } diff --git a/tools/Master.cpp b/tools/Master.cpp index 9b1130cb..4f61f1a3 100644 --- a/tools/Master.cpp +++ b/tools/Master.cpp @@ -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::listPdos(int slavePosition) /****************************************************************************/ +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::getPdoEntry( /****************************************************************************/ +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) { diff --git a/tools/Master.h b/tools/Master.h index 0938819d..7a6df136 100644 --- a/tools/Master.h +++ b/tools/Master.h @@ -48,6 +48,7 @@ class Master void listSlaves(); void showMaster(); void listPdos(int); + void requestStates(int, const vector<string> &); void generateXml(int); protected: @@ -68,6 +69,7 @@ class Master 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); diff --git a/tools/main.cpp b/tools/main.cpp index 4c5eed54..a3f07d5a 100644 --- a/tools/main.cpp +++ b/tools/main.cpp @@ -39,6 +39,7 @@ void printUsage() << " 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 @@ int main(int argc, char **argv) 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 { -- GitLab