Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

canopen.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: canopen.c 682 2006-11-07 12:13:30Z fp $
00004  *
00005  *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
00006  *
00007  *  This file is part of the IgH EtherCAT Master.
00008  *
00009  *  The IgH EtherCAT Master is free software; you can redistribute it
00010  *  and/or modify it under the terms of the GNU General Public License
00011  *  as published by the Free Software Foundation; either version 2 of the
00012  *  License, or (at your option) any later version.
00013  *
00014  *  The IgH EtherCAT Master is distributed in the hope that it will be
00015  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with the IgH EtherCAT Master; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  *  The right to use EtherCAT Technology is granted and comes free of
00024  *  charge under condition of compatibility of product made by
00025  *  Licensee. People intending to distribute/sell products based on the
00026  *  code, have to sign an agreement to guarantee that products using
00027  *  software based on IgH EtherCAT master stay compatible with the actual
00028  *  EtherCAT specification (which are released themselves as an open
00029  *  standard) as the (only) precondition to have the right to use EtherCAT
00030  *  Technology, IP and trade marks.
00031  *
00032  *****************************************************************************/
00033 
00039 /*****************************************************************************/
00040 
00041 #include <linux/module.h>
00042 
00043 #include "canopen.h"
00044 #include "master.h"
00045 
00046 /*****************************************************************************/
00047 
00048 ssize_t ec_show_sdo_attribute(struct kobject *, struct attribute *, char *);
00049 ssize_t ec_show_sdo_entry_attribute(struct kobject *, struct attribute *,
00050                                     char *);
00051 void ec_sdo_clear(struct kobject *);
00052 void ec_sdo_entry_clear(struct kobject *);
00053 
00054 void ec_sdo_request_init_read(ec_sdo_request_t *, ec_sdo_t *,
00055                               ec_sdo_entry_t *);
00056 void ec_sdo_request_clear(ec_sdo_request_t *);
00057 
00058 /*****************************************************************************/
00059 
00062 EC_SYSFS_READ_ATTR(info);
00063 EC_SYSFS_READ_ATTR(value);
00064 
00065 static struct attribute *sdo_def_attrs[] = {
00066     &attr_info,
00067     NULL,
00068 };
00069 
00070 static struct sysfs_ops sdo_sysfs_ops = {
00071     .show = &ec_show_sdo_attribute,
00072     .store = NULL
00073 };
00074 
00075 static struct kobj_type ktype_ec_sdo = {
00076     .release = ec_sdo_clear,
00077     .sysfs_ops = &sdo_sysfs_ops,
00078     .default_attrs = sdo_def_attrs
00079 };
00080 
00081 static struct attribute *sdo_entry_def_attrs[] = {
00082     &attr_info,
00083     &attr_value,
00084     NULL,
00085 };
00086 
00087 static struct sysfs_ops sdo_entry_sysfs_ops = {
00088     .show = &ec_show_sdo_entry_attribute,
00089     .store = NULL
00090 };
00091 
00092 static struct kobj_type ktype_ec_sdo_entry = {
00093     .release = ec_sdo_entry_clear,
00094     .sysfs_ops = &sdo_entry_sysfs_ops,
00095     .default_attrs = sdo_entry_def_attrs
00096 };
00097 
00100 /*****************************************************************************/
00101 
00106 int ec_sdo_init(ec_sdo_t *sdo, 
00107                 uint16_t index, 
00108                 ec_slave_t *slave 
00109                 )
00110 {
00111     sdo->slave = slave;
00112     sdo->index = index;
00113     sdo->object_code = 0x00;
00114     sdo->name = NULL;
00115     sdo->subindices = 0;
00116     INIT_LIST_HEAD(&sdo->entries);
00117 
00118     // init kobject and add it to the hierarchy
00119     memset(&sdo->kobj, 0x00, sizeof(struct kobject));
00120     kobject_init(&sdo->kobj);
00121     sdo->kobj.ktype = &ktype_ec_sdo;
00122     sdo->kobj.parent = &slave->sdo_kobj;
00123     if (kobject_set_name(&sdo->kobj, "%4X", sdo->index)) {
00124         EC_ERR("Failed to set kobj name.\n");
00125         kobject_put(&sdo->kobj);
00126         return -1;
00127     }
00128     if (kobject_add(&sdo->kobj)) {
00129         EC_ERR("Failed to add SDO kobject.\n");
00130         kobject_put(&sdo->kobj);
00131         return -1;
00132     }
00133 
00134     return 0;
00135 }
00136 
00137 /*****************************************************************************/
00138 
00144 void ec_sdo_destroy(ec_sdo_t *sdo )
00145 {
00146     ec_sdo_entry_t *entry, *next;
00147 
00148     // free all entries
00149     list_for_each_entry_safe(entry, next, &sdo->entries, list) {
00150         list_del(&entry->list);
00151         ec_sdo_entry_destroy(entry);
00152     }
00153 
00154     // destroy self
00155     kobject_del(&sdo->kobj);
00156     kobject_put(&sdo->kobj);
00157 }
00158 
00159 /*****************************************************************************/
00160 
00167 void ec_sdo_clear(struct kobject *kobj )
00168 {
00169     ec_sdo_t *sdo = container_of(kobj, ec_sdo_t, kobj);
00170 
00171     if (sdo->name) kfree(sdo->name);
00172 
00173     kfree(sdo);
00174 }
00175 
00176 /*****************************************************************************/
00177 
00178 ssize_t ec_sdo_info(ec_sdo_t *sdo, 
00179                     char *buffer 
00180                     )
00181 {
00182     off_t off = 0;
00183 
00184     off += sprintf(buffer + off, "Index: 0x%04X\n", sdo->index);
00185     off += sprintf(buffer + off, "Name: %s\n", sdo->name ? sdo->name : "");
00186     off += sprintf(buffer + off, "Subindices: %i\n", sdo->subindices);
00187 
00188     return off;
00189 }
00190 
00191 /*****************************************************************************/
00192 
00193 ssize_t ec_show_sdo_attribute(struct kobject *kobj, 
00194                               struct attribute *attr,
00195                               char *buffer
00196                               )
00197 {
00198     ec_sdo_t *sdo = container_of(kobj, ec_sdo_t, kobj);
00199 
00200     if (attr == &attr_info) {
00201         return ec_sdo_info(sdo, buffer);
00202     }
00203 
00204     return 0;
00205 }
00206 
00207 /*****************************************************************************/
00208 
00213 int ec_sdo_entry_init(ec_sdo_entry_t *entry, 
00214                       uint8_t subindex, 
00215                       ec_sdo_t *sdo 
00216                       )
00217 {
00218     entry->sdo = sdo;
00219     entry->subindex = subindex;
00220     entry->data_type = 0x0000;
00221     entry->bit_length = 0;
00222     entry->description = NULL;
00223 
00224     // init kobject and add it to the hierarchy
00225     memset(&entry->kobj, 0x00, sizeof(struct kobject));
00226     kobject_init(&entry->kobj);
00227     entry->kobj.ktype = &ktype_ec_sdo_entry;
00228     entry->kobj.parent = &sdo->kobj;
00229     if (kobject_set_name(&entry->kobj, "%i", entry->subindex)) {
00230         EC_ERR("Failed to set kobj name.\n");
00231         kobject_put(&entry->kobj);
00232         return -1;
00233     }
00234     if (kobject_add(&entry->kobj)) {
00235         EC_ERR("Failed to add entry kobject.\n");
00236         kobject_put(&entry->kobj);
00237         return -1;
00238     }
00239 
00240     return 0;
00241 }
00242 
00243 /*****************************************************************************/
00244 
00250 void ec_sdo_entry_destroy(ec_sdo_entry_t *entry )
00251 {
00252     // destroy self
00253     kobject_del(&entry->kobj);
00254     kobject_put(&entry->kobj);
00255 }
00256 
00257 /*****************************************************************************/
00258 
00265 void ec_sdo_entry_clear(struct kobject *kobj )
00266 {
00267     ec_sdo_entry_t *entry = container_of(kobj, ec_sdo_entry_t, kobj);
00268 
00269     if (entry->description) kfree(entry->description);
00270 
00271     kfree(entry);
00272 }
00273 
00274 /*****************************************************************************/
00275 
00276 ssize_t ec_sdo_entry_info(ec_sdo_entry_t *entry, 
00277                           char *buffer 
00278                           )
00279 {
00280     off_t off = 0;
00281 
00282     off += sprintf(buffer + off, "Subindex: 0x%02X\n", entry->subindex);
00283     off += sprintf(buffer + off, "Description: %s\n",
00284                    entry->description ? entry->description : "");
00285     off += sprintf(buffer + off, "Data type: 0x%04X\n", entry->data_type);
00286     off += sprintf(buffer + off, "Bit length: %i\n", entry->bit_length);
00287 
00288     return off;
00289 }
00290 
00291 /*****************************************************************************/
00292 
00293 ssize_t ec_sdo_entry_format_data(ec_sdo_entry_t *entry, 
00294                                  ec_sdo_request_t *request, 
00295                                  char *buffer 
00296                                  )
00297 {
00298     off_t off = 0;
00299     unsigned int i;
00300 
00301     if (entry->data_type == 0x0002 && entry->bit_length == 8) { // int8
00302         off += sprintf(buffer + off, "%i\n", *((int8_t *) request->data));
00303     }
00304     else if (entry->data_type == 0x0003 && entry->bit_length == 16) { // int16
00305         off += sprintf(buffer + off, "%i\n", *((int16_t *) request->data));
00306     }
00307     else if (entry->data_type == 0x0004 && entry->bit_length == 32) { // int32
00308         off += sprintf(buffer + off, "%i\n", *((int32_t *) request->data));
00309     }
00310     else if (entry->data_type == 0x0005 && entry->bit_length == 8) { // uint8
00311         off += sprintf(buffer + off, "%i\n", *((uint8_t *) request->data));
00312     }
00313     else if (entry->data_type == 0x0006 && entry->bit_length == 16) { // uint16
00314         off += sprintf(buffer + off, "%i\n", *((uint16_t *) request->data));
00315     }
00316     else if (entry->data_type == 0x0007 && entry->bit_length == 32) { // uint32
00317         off += sprintf(buffer + off, "%i\n", *((uint32_t *) request->data));
00318     }
00319     else if (entry->data_type == 0x0009) { // string
00320         off += sprintf(buffer + off, "%s\n", request->data);
00321     }
00322     else {
00323         for (i = 0; i < request->size; i++)
00324             off += sprintf(buffer + off, "%02X (%c)\n",
00325                            request->data[i], request->data[i]);
00326     }
00327 
00328     return off;
00329 }
00330 
00331 /*****************************************************************************/
00332 
00333 ssize_t ec_sdo_entry_read_value(ec_sdo_entry_t *entry, 
00334                                 char *buffer 
00335                                 )
00336 {
00337     ec_sdo_t *sdo = entry->sdo;
00338     ec_master_t *master = sdo->slave->master;
00339     off_t off = 0;
00340     ec_sdo_request_t request;
00341 
00342     if (down_interruptible(&master->sdo_sem)) {
00343         // interrupted by signal
00344         return -ERESTARTSYS;
00345     }
00346 
00347     ec_sdo_request_init_read(&request, sdo, entry);
00348 
00349     // this is necessary, because the completion object
00350     // is completed by the ec_master_flush_sdo_requests() function.
00351     INIT_COMPLETION(master->sdo_complete);
00352 
00353     master->sdo_request = &request;
00354     master->sdo_seq_user++;
00355     master->sdo_timer.expires = jiffies + 10;
00356     add_timer(&master->sdo_timer);
00357 
00358     wait_for_completion(&master->sdo_complete);
00359 
00360     master->sdo_request = NULL;
00361     up(&master->sdo_sem);
00362 
00363     if (request.return_code == 1 && request.data) {
00364         off += ec_sdo_entry_format_data(entry, &request, buffer);
00365     }
00366     else {
00367         off = -EINVAL;
00368     }
00369 
00370     ec_sdo_request_clear(&request);
00371     return off;
00372 }
00373 
00374 /*****************************************************************************/
00375 
00376 ssize_t ec_show_sdo_entry_attribute(struct kobject *kobj, 
00377                                     struct attribute *attr,
00378                                     char *buffer
00379                                     )
00380 {
00381     ec_sdo_entry_t *entry = container_of(kobj, ec_sdo_entry_t, kobj);
00382 
00383     if (attr == &attr_info) {
00384         return ec_sdo_entry_info(entry, buffer);
00385     }
00386     else if (attr == &attr_value) {
00387         return ec_sdo_entry_read_value(entry, buffer);
00388     }
00389 
00390     return 0;
00391 }
00392 
00393 /*****************************************************************************/
00394 
00399 void ec_sdo_request_init_read(ec_sdo_request_t *req, 
00400                               ec_sdo_t *sdo, 
00401                               ec_sdo_entry_t *entry 
00402                               )
00403 {
00404     req->sdo = sdo;
00405     req->entry = entry;
00406     req->data = NULL;
00407     req->size = 0;
00408     req->return_code = 0;
00409 }
00410 
00411 /*****************************************************************************/
00412 
00417 void ec_sdo_request_clear(ec_sdo_request_t *req )
00418 {
00419     if (req->data) kfree(req->data);
00420 }
00421 
00422 /*****************************************************************************/

Generated on Tue Nov 7 15:03:35 2006 for IgH EtherCAT master by  doxygen 1.4.4