master/pdo.c
changeset 792 3778920f61e4
parent 627 4793ca94f082
child 799 068a58b96965
--- a/master/pdo.c	Thu Feb 14 09:18:55 2008 +0000
+++ b/master/pdo.c	Tue Feb 19 08:22:20 2008 +0000
@@ -44,66 +44,196 @@
 
 /*****************************************************************************/
 
-/**
- * PDO constructor.
- */
-
-void ec_pdo_init(ec_pdo_t *pdo /**< EtherCAT PDO */)
-{
+void ec_pdo_clear_entries(ec_pdo_t *);
+
+/*****************************************************************************/
+
+/** PDO constructor.
+ */
+void ec_pdo_init(
+        ec_pdo_t *pdo /**< EtherCAT PDO */
+        )
+{
+    pdo->sync_index = -1; // not assigned 
     pdo->name = NULL;
     INIT_LIST_HEAD(&pdo->entries);
 }
 
 /*****************************************************************************/
 
-/**
- * PDO destructor.
- */
-
+/** Pdo copy constructor.
+ */
+int ec_pdo_init_copy(ec_pdo_t *pdo, const ec_pdo_t *other_pdo)
+{
+    pdo->dir = other_pdo->dir;
+    pdo->index = other_pdo->index;
+    pdo->sync_index = other_pdo->sync_index;
+    pdo->name = NULL;
+    INIT_LIST_HEAD(&pdo->entries);
+
+    if (ec_pdo_set_name(pdo, other_pdo->name))
+        goto out_return;
+
+    if (ec_pdo_copy_entries(pdo, other_pdo))
+        goto out_clear;
+
+    return 0;
+
+out_clear:
+    ec_pdo_clear(pdo);
+out_return:
+    return -1;
+}
+
+/*****************************************************************************/
+
+/** PDO destructor.
+ */
 void ec_pdo_clear(ec_pdo_t *pdo /**< EtherCAT PDO */)
 {
+    if (pdo->name)
+        kfree(pdo->name);
+
+    ec_pdo_clear_entries(pdo);
+}
+
+/*****************************************************************************/
+
+/** Clear Pdo entry list.
+ */
+void ec_pdo_clear_entries(ec_pdo_t *pdo /**< EtherCAT PDO */)
+{
     ec_pdo_entry_t *entry, *next;
 
     // free all PDO entries
     list_for_each_entry_safe(entry, next, &pdo->entries, list) {
         list_del(&entry->list);
+        ec_pdo_entry_clear(entry);
         kfree(entry);
     }
 }
 
 /*****************************************************************************/
 
-/**
- * Makes a deep copy of a PDO.
- */
-
-int ec_pdo_copy(ec_pdo_t *pdo, const ec_pdo_t *other_pdo)
-{
-    ec_pdo_entry_t *entry, *other_entry, *next;
-
-    // make flat copy
-    *pdo = *other_pdo;
-
-    INIT_LIST_HEAD(&pdo->entries);
-    list_for_each_entry(other_entry, &other_pdo->entries, list) {
+/** Set Pdo name.
+ */
+int ec_pdo_set_name(
+        ec_pdo_t *pdo, /**< Pdo. */
+        const char *name /**< New name. */
+        )
+{
+    unsigned int len;
+
+    if (pdo->name)
+        kfree(pdo->name);
+
+    if (name && (len = strlen(name))) {
+        if (!(pdo->name = (char *) kmalloc(len + 1, GFP_KERNEL))) {
+            EC_ERR("Failed to allocate PDO name.\n");
+            return -1;
+        }
+        memcpy(pdo->name, name, len + 1);
+    } else {
+        pdo->name = NULL;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Copy Pdo entries from another Pdo.
+ */
+int ec_pdo_copy_entries(ec_pdo_t *pdo, const ec_pdo_t *other)
+{
+    ec_pdo_entry_t *entry, *other_entry;
+
+    ec_pdo_clear_entries(pdo);
+
+    list_for_each_entry(other_entry, &other->entries, list) {
         if (!(entry = (ec_pdo_entry_t *)
                     kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
             EC_ERR("Failed to allocate memory for PDO entry copy.\n");
-            goto out_free;
-        }
-
-        *entry = *other_entry; // flat copy is sufficient
+            return -1;
+        }
+
+        if (ec_pdo_entry_init_copy(entry, other_entry)) {
+            kfree(entry);
+            return -1;
+        }
+
         list_add_tail(&entry->list, &pdo->entries);
     }
 
     return 0;
-
-out_free:
-    list_for_each_entry_safe(entry, next, &pdo->entries, list) {
-        list_del(&entry->list);
-        kfree(entry);
-    }
-    return -1;
-}
-
-/*****************************************************************************/
+}
+
+/*****************************************************************************/
+
+/** Pdo entry constructor.
+ */
+void ec_pdo_entry_init(
+        ec_pdo_entry_t *entry /**< Pdo entry. */
+        )
+{
+    entry->name = NULL;
+}
+
+/*****************************************************************************/
+
+/** Pdo entry copy constructor.
+ */
+int ec_pdo_entry_init_copy(
+        ec_pdo_entry_t *entry, /**< Pdo entry. */
+        const ec_pdo_entry_t *other /**< Pdo entry to copy from. */
+        )
+{
+    entry->index = other->index;
+    entry->subindex = other->subindex;
+    entry->name = NULL;
+    entry->bit_length = other->bit_length;
+
+    if (ec_pdo_entry_set_name(entry, other->name))
+        return -1;
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Pdo entry destructor.
+ */
+void ec_pdo_entry_clear(ec_pdo_entry_t *entry /**< Pdo entry. */)
+{
+    if (entry->name)
+        kfree(entry->name);
+}
+
+/*****************************************************************************/
+
+/** Set Pdo entry name.
+ */
+int ec_pdo_entry_set_name(
+        ec_pdo_entry_t *entry, /**< Pdo entry. */
+        const char *name /**< New name. */
+        )
+{
+    unsigned int len;
+
+    if (entry->name)
+        kfree(entry->name);
+
+    if (name && (len = strlen(name))) {
+        if (!(entry->name = (char *) kmalloc(len + 1, GFP_KERNEL))) {
+            EC_ERR("Failed to allocate PDO entry name.\n");
+            return -1;
+        }
+        memcpy(entry->name, name, len + 1);
+    } else {
+        entry->name = NULL;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/