Simplified handling of EEPROM strings.
authorFlorian Pose <fp@igh-essen.com>
Wed, 07 Mar 2007 11:11:17 +0000
changeset 624 11332ad89f47
parent 623 4d64368f3a1e
child 625 ec69acbbd156
Simplified handling of EEPROM strings.
master/slave.c
master/slave.h
--- a/master/slave.c	Tue Mar 06 15:11:44 2007 +0000
+++ b/master/slave.c	Wed Mar 07 11:11:17 2007 +0000
@@ -57,6 +57,7 @@
 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *);
 ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *,
                                  const char *, size_t);
+char *ec_slave_sii_string(ec_slave_t *, unsigned int);
 
 /*****************************************************************************/
 
@@ -147,7 +148,8 @@
     slave->sii_name = NULL;
     slave->sii_current_on_ebus = 0;
 
-    INIT_LIST_HEAD(&slave->sii_strings);
+    slave->sii_strings = NULL;
+    slave->sii_string_count = 0;
     slave->sii_syncs = NULL;
     slave->sii_sync_count = 0;
     INIT_LIST_HEAD(&slave->sii_pdos);
@@ -239,17 +241,18 @@
 void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
 {
     ec_slave_t *slave;
-    ec_sii_string_t *string, *next_str;
     ec_sii_pdo_t *pdo, *next_pdo;
     ec_sii_pdo_entry_t *entry, *next_ent;
     ec_sdo_data_t *sdodata, *next_sdodata;
+    unsigned int i;
 
     slave = container_of(kobj, ec_slave_t, kobj);
 
-    // free all string objects
-    list_for_each_entry_safe(string, next_str, &slave->sii_strings, list) {
-        list_del(&string->list);
-        kfree(string);
+    // free all strings
+    if (slave->sii_strings) {
+        for (i = 0; i < slave->sii_string_count; i++)
+            kfree(slave->sii_strings[i]);
+        kfree(slave->sii_strings);
     }
 
     // free all sync managers
@@ -258,23 +261,16 @@
     // free all PDOs
     list_for_each_entry_safe(pdo, next_pdo, &slave->sii_pdos, list) {
         list_del(&pdo->list);
-        if (pdo->name) kfree(pdo->name);
 
         // free all PDO entries
         list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) {
             list_del(&entry->list);
-            if (entry->name) kfree(entry->name);
             kfree(entry);
         }
 
         kfree(pdo);
     }
 
-    if (slave->sii_group) kfree(slave->sii_group);
-    if (slave->sii_image) kfree(slave->sii_image);
-    if (slave->sii_order) kfree(slave->sii_order);
-    if (slave->sii_name) kfree(slave->sii_name);
-
     // free all SDO configurations
     list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) {
         list_del(&sdodata->list);
@@ -405,31 +401,45 @@
         const uint8_t *data /**< category data */
         )
 {
-    unsigned int string_count, i;
+    int i;
     size_t size;
     off_t offset;
-    ec_sii_string_t *string;
-
-    string_count = data[0];
+
+    slave->sii_string_count = data[0];
+
+    if (!slave->sii_string_count)
+        return 0;
+
+    if (!(slave->sii_strings =
+                kmalloc(sizeof(char *) * slave->sii_string_count,
+                    GFP_KERNEL))) {
+        EC_ERR("Failed to allocate string array memory.\n");
+        goto out_zero;
+    }
+
     offset = 1;
-    for (i = 0; i < string_count; i++) {
+    for (i = 0; i < slave->sii_string_count; i++) {
         size = data[offset];
         // allocate memory for string structure and data at a single blow
-        if (!(string = (ec_sii_string_t *)
-              kmalloc(sizeof(ec_sii_string_t) + size + 1, GFP_ATOMIC))) {
+        if (!(slave->sii_strings[i] =
+                    kmalloc(sizeof(char) * size + 1, GFP_KERNEL))) {
             EC_ERR("Failed to allocate string memory.\n");
-            return -1;
-        }
-        string->size = size;
-        // string memory appended to string structure
-        string->data = (char *) string + sizeof(ec_sii_string_t);
-        memcpy(string->data, data + offset + 1, size);
-        string->data[size] = 0x00;
-        list_add_tail(&string->list, &slave->sii_strings);
+            goto out_free;
+        }
+        memcpy(slave->sii_strings[i], data + offset + 1, size);
+        slave->sii_strings[i][size] = 0x00; // append binary zero
         offset += 1 + size;
     }
 
     return 0;
+
+out_free:
+    for (i--; i >= 0; i--) kfree(slave->sii_strings[i]);
+    kfree(slave->sii_strings);
+    slave->sii_strings = NULL;
+out_zero:
+    slave->sii_string_count = 0;
+    return -1;
 }
 
 /*****************************************************************************/
@@ -446,10 +456,10 @@
 {
     unsigned int i;
 
-    ec_slave_locate_sii_string(slave, data[0], &slave->sii_group);
-    ec_slave_locate_sii_string(slave, data[1], &slave->sii_image);
-    ec_slave_locate_sii_string(slave, data[2], &slave->sii_order);
-    ec_slave_locate_sii_string(slave, data[3], &slave->sii_name);
+    slave->sii_group = ec_slave_sii_string(slave, data[0]);
+    slave->sii_image = ec_slave_sii_string(slave, data[1]);
+    slave->sii_order = ec_slave_sii_string(slave, data[2]);
+    slave->sii_name = ec_slave_sii_string(slave, data[3]);
 
     for (i = 0; i < 4; i++)
         slave->sii_physical_layer[i] =
@@ -529,8 +539,7 @@
         pdo->index = EC_READ_U16(data);
         entry_count = EC_READ_U8(data + 2);
         pdo->sync_index = EC_READ_U8(data + 3);
-        pdo->name = NULL;
-        ec_slave_locate_sii_string(slave, EC_READ_U8(data + 5), &pdo->name);
+        pdo->name = ec_slave_sii_string(slave, EC_READ_U8(data + 5));
 
         list_add_tail(&pdo->list, &slave->sii_pdos);
 
@@ -546,9 +555,7 @@
 
             entry->index = EC_READ_U16(data);
             entry->subindex = EC_READ_U8(data + 2);
-            entry->name = NULL;
-            ec_slave_locate_sii_string(
-                    slave, EC_READ_U8(data + 3), &entry->name);
+            entry->name = ec_slave_sii_string(slave, EC_READ_U8(data + 3));
             entry->bit_length = EC_READ_U8(data + 5);
 
             list_add_tail(&entry->list, &pdo->entries);
@@ -569,49 +576,22 @@
    \todo documentation
 */
 
-int ec_slave_locate_sii_string(
+char *ec_slave_sii_string(
         ec_slave_t *slave, /**< EtherCAT slave */
-        unsigned int index, /**< string index */
-        char **ptr /**< Address of the string pointer */
+        unsigned int index /**< string index */
         )
 {
-    ec_sii_string_t *string;
-    char *err_string;
-
-    // Erst alten Speicher freigeben
-    if (*ptr) {
-        kfree(*ptr);
-        *ptr = NULL;
-    }
-
-    // Index 0 bedeutet "nicht belegt"
-    if (!index) return 0;
-
-    // EEPROM-String mit Index finden und kopieren
-    list_for_each_entry(string, &slave->sii_strings, list) {
-        if (--index) continue;
-
-        if (!(*ptr = (char *) kmalloc(string->size + 1, GFP_ATOMIC))) {
-            EC_ERR("Unable to allocate string memory.\n");
-            return -1;
-        }
-        memcpy(*ptr, string->data, string->size + 1);
-        return 0;
-    }
-
-    if (slave->master->debug_level)
-        EC_WARN("String %i not found in slave %i.\n",
-                index, slave->ring_position);
-
-    err_string = "(string not found)";
-
-    if (!(*ptr = (char *) kmalloc(strlen(err_string) + 1, GFP_ATOMIC))) {
-        EC_WARN("Unable to allocate string memory.\n");
-        return -1;
-    }
-
-    memcpy(*ptr, err_string, strlen(err_string) + 1);
-    return 0;
+    if (!index--) 
+        return NULL;
+
+    if (index >= slave->sii_string_count) {
+        if (slave->master->debug_level)
+            EC_WARN("String %i not found in slave %i.\n",
+                    index, slave->ring_position);
+        return NULL;
+    }
+
+    return slave->sii_strings[index];
 }
 
 /*****************************************************************************/
--- a/master/slave.h	Tue Mar 06 15:11:44 2007 +0000
+++ b/master/slave.h	Wed Mar 07 11:11:17 2007 +0000
@@ -97,20 +97,6 @@
 /*****************************************************************************/
 
 /**
-   String object (EEPROM).
-*/
-
-typedef struct
-{
-    struct list_head list; /**< list item */
-    size_t size; /**< size in bytes */
-    char *data; /**< string data */
-}
-ec_sii_string_t;
-
-/*****************************************************************************/
-
-/**
    Sync manager configuration (EEPROM).
 */
 
@@ -240,7 +226,8 @@
     uint16_t sii_tx_mailbox_size; /**< mailbox size (slave to master) */
     uint16_t sii_mailbox_protocols; /**< supported mailbox protocols */
     uint8_t sii_physical_layer[4]; /**< port media */
-    struct list_head sii_strings; /**< EEPROM STRING categories */
+    char **sii_strings; /**< strings in EEPROM categories */
+    unsigned int sii_string_count; /**< number of EEPROM strings */
     ec_sii_sync_t *sii_syncs; /**< EEPROM SYNC MANAGER categories */
     unsigned int sii_sync_count; /**< number of sync managers in EEPROM */
     struct list_head sii_pdos; /**< EEPROM [RT]XPDO categories */
@@ -283,7 +270,6 @@
         ec_sii_pdo_type_t);
 
 // misc.
-int ec_slave_locate_sii_string(ec_slave_t *, unsigned int, char **);
 ec_sii_sync_t *ec_slave_get_pdo_sync(ec_slave_t *, ec_direction_t); 
 void ec_slave_sync_config(const ec_slave_t *, const ec_sii_sync_t *,
         uint8_t *);