--- 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 *);