From 184f068ad38b2fe11e093512baf4b985dea88caa Mon Sep 17 00:00:00 2001
From: Florian Pose <fp@igh-essen.com>
Date: Tue, 9 Mar 2010 12:01:29 +0100
Subject: [PATCH] Implemented ecrt_slave_config_idn() for user-space library.

---
 TODO               |  1 -
 lib/slave_config.c | 20 +++++++++++++++++
 master/cdev.c      | 55 ++++++++++++++++++++++++++++++++++++++++++++++
 master/ioctl.h     | 47 ++++++++++++++++++++++++---------------
 4 files changed, 104 insertions(+), 19 deletions(-)

diff --git a/TODO b/TODO
index 12d29fc4..6d3dcbc2 100644
--- a/TODO
+++ b/TODO
@@ -24,7 +24,6 @@ Version 1.5.0:
 * Output warning when send_ext() is called in illegal context.
 * Add master index to log messages.
 * Implement SoE fragmenting.
-* User-space implementation for SoE.
 * Implement CompleteAccess for SDO uploads.
 * Check for Enable SDO Complete Access flag.
 * Remove allow_scanning flag.
diff --git a/lib/slave_config.c b/lib/slave_config.c
index bbbc63e6..d73e238e 100644
--- a/lib/slave_config.c
+++ b/lib/slave_config.c
@@ -471,3 +471,23 @@ void ecrt_slave_config_state(const ec_slave_config_t *sc,
 }
 
 /*****************************************************************************/
+
+int ecrt_slave_config_idn(ec_slave_config_t *sc, uint16_t idn,
+        const uint8_t *data, size_t size)
+{
+    ec_ioctl_sc_idn_t io;
+
+    io.config_index = sc->index;
+    io.idn = idn;
+    io.data = data;
+    io.size = size;
+
+    if (ioctl(sc->master->fd, EC_IOCTL_SC_IDN, &io) == -1) {
+        fprintf(stderr, "Failed to configure IDN.\n");
+        return -1; // FIXME
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
diff --git a/master/cdev.c b/master/cdev.c
index aa81c01c..0ca0e99a 100644
--- a/master/cdev.c
+++ b/master/cdev.c
@@ -2417,6 +2417,57 @@ int ec_cdev_ioctl_sc_state(
 
 /*****************************************************************************/
 
+/** Configures an IDN.
+ */
+int ec_cdev_ioctl_sc_idn(
+        ec_master_t *master, /**< EtherCAT master. */
+        unsigned long arg, /**< ioctl() argument. */
+        ec_cdev_priv_t *priv /**< Private data structure of file handle. */
+        )
+{
+    ec_ioctl_sc_idn_t ioctl;
+    ec_slave_config_t *sc;
+    uint8_t *data = NULL;
+    int ret;
+
+    if (unlikely(!priv->requested))
+        return -EPERM;
+
+    if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl)))
+        return -EFAULT;
+
+    if (!ioctl.size)
+        return -EINVAL;
+
+    if (!(data = kmalloc(ioctl.size, GFP_KERNEL))) {
+        return -ENOMEM;
+    }
+
+    if (copy_from_user(data, (void __user *) ioctl.data, ioctl.size)) {
+        kfree(data);
+        return -EFAULT;
+    }
+
+    if (down_interruptible(&master->master_sem)) {
+        kfree(data);
+        return -EINTR;
+    }
+
+    if (!(sc = ec_master_get_config(master, ioctl.config_index))) {
+        up(&master->master_sem);
+        kfree(data);
+        return -ENOENT;
+    }
+
+    up(&master->master_sem); // FIXME
+
+    ret = ecrt_slave_config_idn(sc, ioctl.idn, data, ioctl.size);
+    kfree(data);
+    return ret;
+}
+
+/*****************************************************************************/
+
 /** Gets the domain's offset in the total process data.
  */
 int ec_cdev_ioctl_domain_offset(
@@ -3687,6 +3738,10 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
             return ec_cdev_ioctl_sc_create_voe_handler(master, arg, priv);
         case EC_IOCTL_SC_STATE:
             return ec_cdev_ioctl_sc_state(master, arg, priv);
+        case EC_IOCTL_SC_IDN:
+            if (!(filp->f_mode & FMODE_WRITE))
+                return -EPERM;
+            return ec_cdev_ioctl_sc_idn(master, arg, priv);
         case EC_IOCTL_DOMAIN_OFFSET:
             return ec_cdev_ioctl_domain_offset(master, arg, priv);
         case EC_IOCTL_DOMAIN_PROCESS:
diff --git a/master/ioctl.h b/master/ioctl.h
index e93328f9..2eae8d17 100644
--- a/master/ioctl.h
+++ b/master/ioctl.h
@@ -56,7 +56,7 @@
  *
  * Increment this when changing the ioctl interface!
  */
-#define EC_IOCTL_VERSION_MAGIC 4
+#define EC_IOCTL_VERSION_MAGIC 5
 
 // Command-line tool
 #define EC_IOCTL_MODULE                EC_IOR(0x00, ec_ioctl_module_t)
@@ -116,23 +116,24 @@
 #define EC_IOCTL_SC_SDO_REQUEST       EC_IOWR(0x32, ec_ioctl_sdo_request_t)
 #define EC_IOCTL_SC_VOE               EC_IOWR(0x33, ec_ioctl_voe_t)
 #define EC_IOCTL_SC_STATE             EC_IOWR(0x34, ec_ioctl_sc_state_t)
-#define EC_IOCTL_DOMAIN_OFFSET          EC_IO(0x35)
-#define EC_IOCTL_DOMAIN_PROCESS         EC_IO(0x36)
-#define EC_IOCTL_DOMAIN_QUEUE           EC_IO(0x37)
-#define EC_IOCTL_DOMAIN_STATE         EC_IOWR(0x38, ec_ioctl_domain_state_t)
-#define EC_IOCTL_SDO_REQUEST_TIMEOUT  EC_IOWR(0x39, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_STATE    EC_IOWR(0x3a, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_READ     EC_IOWR(0x3b, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_WRITE    EC_IOWR(0x3c, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_SDO_REQUEST_DATA     EC_IOWR(0x3d, ec_ioctl_sdo_request_t)
-#define EC_IOCTL_VOE_SEND_HEADER       EC_IOW(0x3e, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_REC_HEADER       EC_IOWR(0x3f, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_READ              EC_IOW(0x40, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_READ_NOSYNC       EC_IOW(0x41, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_WRITE            EC_IOWR(0x42, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_EXEC             EC_IOWR(0x43, ec_ioctl_voe_t)
-#define EC_IOCTL_VOE_DATA             EC_IOWR(0x44, ec_ioctl_voe_t)
-#define EC_IOCTL_SET_SEND_INTERVAL     EC_IOW(0x45, size_t)
+#define EC_IOCTL_SC_IDN                EC_IOW(0x35, ec_ioctl_sc_idn_t)
+#define EC_IOCTL_DOMAIN_OFFSET          EC_IO(0x36)
+#define EC_IOCTL_DOMAIN_PROCESS         EC_IO(0x37)
+#define EC_IOCTL_DOMAIN_QUEUE           EC_IO(0x38)
+#define EC_IOCTL_DOMAIN_STATE         EC_IOWR(0x39, ec_ioctl_domain_state_t)
+#define EC_IOCTL_SDO_REQUEST_TIMEOUT  EC_IOWR(0x3a, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_STATE    EC_IOWR(0x3b, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_READ     EC_IOWR(0x3c, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_WRITE    EC_IOWR(0x3d, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_SDO_REQUEST_DATA     EC_IOWR(0x3e, ec_ioctl_sdo_request_t)
+#define EC_IOCTL_VOE_SEND_HEADER       EC_IOW(0x3f, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_REC_HEADER       EC_IOWR(0x40, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_READ              EC_IOW(0x41, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_READ_NOSYNC       EC_IOW(0x42, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_WRITE            EC_IOWR(0x43, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_EXEC             EC_IOWR(0x44, ec_ioctl_voe_t)
+#define EC_IOCTL_VOE_DATA             EC_IOWR(0x45, ec_ioctl_voe_t)
+#define EC_IOCTL_SET_SEND_INTERVAL     EC_IOW(0x46, size_t)
 
 /*****************************************************************************/
 
@@ -578,6 +579,16 @@ typedef struct {
 
 /*****************************************************************************/
 
+typedef struct {
+    // inputs
+    uint32_t config_index;
+    uint16_t idn;
+    const uint8_t *data;
+    size_t size;
+} ec_ioctl_sc_idn_t;
+
+/*****************************************************************************/
+
 typedef struct {
     // inputs
     uint32_t domain_index;
-- 
GitLab