master/sdo.c
changeset 847 92266462d411
parent 831 ded9519c8d6e
child 962 ea83a7aab57a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/sdo.c	Fri Feb 29 12:19:48 2008 +0000
@@ -0,0 +1,218 @@
+/******************************************************************************
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
+ *
+ *  This file is part of the IgH EtherCAT Master.
+ *
+ *  The IgH EtherCAT Master is free software; you can redistribute it
+ *  and/or modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2 of the
+ *  License, or (at your option) any later version.
+ *
+ *  The IgH EtherCAT Master is distributed in the hope that it will be
+ *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with the IgH EtherCAT Master; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  The right to use EtherCAT Technology is granted and comes free of
+ *  charge under condition of compatibility of product made by
+ *  Licensee. People intending to distribute/sell products based on the
+ *  code, have to sign an agreement to guarantee that products using
+ *  software based on IgH EtherCAT master stay compatible with the actual
+ *  EtherCAT specification (which are released themselves as an open
+ *  standard) as the (only) precondition to have the right to use EtherCAT
+ *  Technology, IP and trade marks.
+ *
+ *****************************************************************************/
+
+/**
+   \file
+   CANopen Sdo functions.
+*/
+
+/*****************************************************************************/
+
+#include <linux/module.h>
+
+#include "master.h"
+
+#include "sdo.h"
+
+/*****************************************************************************/
+
+ssize_t ec_show_sdo_attribute(struct kobject *, struct attribute *, char *);
+void ec_sdo_clear(struct kobject *);
+
+/*****************************************************************************/
+
+/** \cond */
+
+EC_SYSFS_READ_ATTR(info);
+
+static struct attribute *sdo_def_attrs[] = {
+    &attr_info,
+    NULL,
+};
+
+static struct sysfs_ops sdo_sysfs_ops = {
+    .show = &ec_show_sdo_attribute,
+    .store = NULL
+};
+
+static struct kobj_type ktype_ec_sdo = {
+    .release = ec_sdo_clear,
+    .sysfs_ops = &sdo_sysfs_ops,
+    .default_attrs = sdo_def_attrs
+};
+
+/** \endcond */
+
+/*****************************************************************************/
+
+/** Sdo constructor.
+ *
+ * \todo Turn parameters.
+ */
+int ec_sdo_init(
+        ec_sdo_t *sdo, /**< Sdo. */
+        uint16_t index, /**< Sdo index. */
+        ec_slave_t *slave /**< Parent slave. */
+        )
+{
+    sdo->slave = slave;
+    sdo->index = index;
+    sdo->object_code = 0x00;
+    sdo->name = NULL;
+    sdo->subindices = 0;
+    INIT_LIST_HEAD(&sdo->entries);
+
+    // Init kobject and add it to the hierarchy
+    memset(&sdo->kobj, 0x00, sizeof(struct kobject));
+    kobject_init(&sdo->kobj);
+    sdo->kobj.ktype = &ktype_ec_sdo;
+    sdo->kobj.parent = &slave->sdo_kobj;
+    if (kobject_set_name(&sdo->kobj, "%4X", sdo->index)) {
+        EC_ERR("Failed to set kobj name.\n");
+        kobject_put(&sdo->kobj);
+        return -1;
+    }
+    if (kobject_add(&sdo->kobj)) {
+        EC_ERR("Failed to add Sdo kobject.\n");
+        kobject_put(&sdo->kobj);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Sdo destructor.
+ *
+ * Clears and frees an Sdo object.
+ */
+void ec_sdo_destroy(
+        ec_sdo_t *sdo /**< Sdo. */
+        )
+{
+    ec_sdo_entry_t *entry, *next;
+
+    // free all entries
+    list_for_each_entry_safe(entry, next, &sdo->entries, list) {
+        list_del(&entry->list);
+        ec_sdo_entry_destroy(entry);
+    }
+
+    // destroy self
+    kobject_del(&sdo->kobj);
+    kobject_put(&sdo->kobj);
+}
+
+/*****************************************************************************/
+
+/** Clear and free Sdo.
+ *
+ * This method is called by the kobject,
+ * once there are no more references to it.
+ */
+void ec_sdo_clear(
+        struct kobject *kobj /**< Sdo's kobject. */
+        )
+{
+    ec_sdo_t *sdo = container_of(kobj, ec_sdo_t, kobj);
+
+    if (sdo->name) kfree(sdo->name);
+
+    kfree(sdo);
+}
+
+/*****************************************************************************/
+
+/** Get and Sdo entry from an Sdo via its subindex.
+ * 
+ * \retval >0 Pointer to the requested Sdo entry.
+ * \retval NULL Sdo entry not found.
+ */
+ec_sdo_entry_t *ec_sdo_get_entry(
+        ec_sdo_t *sdo, /**< Sdo. */
+        uint8_t subindex /**< Entry subindex. */
+        )
+{
+    ec_sdo_entry_t *entry;
+
+    list_for_each_entry(entry, &sdo->entries, list) {
+        if (entry->subindex != subindex) continue;
+        return entry;
+    }
+
+    return NULL;
+}
+
+/*****************************************************************************/
+
+/** Print Sdo information to a buffer.
+ * 
+ * /return size of bytes written to buffer.
+ */ 
+ssize_t ec_sdo_info(
+        ec_sdo_t *sdo, /**< Sdo. */
+        char *buffer /**< Target buffer. */
+        )
+{
+    off_t off = 0;
+
+    off += sprintf(buffer + off, "Index: 0x%04X\n", sdo->index);
+    off += sprintf(buffer + off, "Name: %s\n", sdo->name ? sdo->name : "");
+    off += sprintf(buffer + off, "Subindices: %i\n", sdo->subindices);
+
+    return off;
+}
+
+/*****************************************************************************/
+
+/** Show a Sysfs attribute of an Sdo.
+ * 
+ * /return Number of bytes written to buffer.
+ */ 
+ssize_t ec_show_sdo_attribute(
+        struct kobject *kobj, /**< kobject */
+        struct attribute *attr, /**< Requested attribute. */
+        char *buffer /**< Buffer to write the data in. */
+        )
+{
+    ec_sdo_t *sdo = container_of(kobj, ec_sdo_t, kobj);
+
+    if (attr == &attr_info) {
+        return ec_sdo_info(sdo, buffer);
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/