IgH EtherCAT Master  1.6.1
pdo.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
4  *
5  * This file is part of the IgH EtherCAT Master.
6  *
7  * The IgH EtherCAT Master is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License version 2, as
9  * published by the Free Software Foundation.
10  *
11  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with the IgH EtherCAT Master; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  ****************************************************************************/
21 
27 /****************************************************************************/
28 
29 #include <linux/slab.h>
30 #include <linux/err.h>
31 
32 #include "pdo.h"
33 
34 /****************************************************************************/
35 
39  ec_pdo_t *pdo
40  )
41 {
42  pdo->sync_index = -1; // not assigned
43  pdo->name = NULL;
44  INIT_LIST_HEAD(&pdo->entries);
45 }
46 
47 /****************************************************************************/
48 
55  ec_pdo_t *pdo,
56  const ec_pdo_t *other_pdo
57  )
58 {
59  int ret = 0;
60 
61  pdo->index = other_pdo->index;
62  pdo->sync_index = other_pdo->sync_index;
63  pdo->name = NULL;
64  INIT_LIST_HEAD(&pdo->entries);
65 
66  ret = ec_pdo_set_name(pdo, other_pdo->name);
67  if (ret < 0)
68  goto out_return;
69 
70  ret = ec_pdo_copy_entries(pdo, other_pdo);
71  if (ret < 0)
72  goto out_clear;
73 
74  return 0;
75 
76 out_clear:
77  ec_pdo_clear(pdo);
78 out_return:
79  return ret;
80 }
81 
82 /****************************************************************************/
83 
87 {
88  if (pdo->name)
89  kfree(pdo->name);
90 
92 }
93 
94 /****************************************************************************/
95 
99 {
100  ec_pdo_entry_t *entry, *next;
101 
102  // free all PDO entries
103  list_for_each_entry_safe(entry, next, &pdo->entries, list) {
104  list_del(&entry->list);
105  ec_pdo_entry_clear(entry);
106  kfree(entry);
107  }
108 }
109 
110 /****************************************************************************/
111 
118  ec_pdo_t *pdo,
119  const char *name
120  )
121 {
122  unsigned int len;
123 
124  if (pdo->name && name && !strcmp(pdo->name, name))
125  return 0;
126 
127  if (pdo->name)
128  kfree(pdo->name);
129 
130  if (name && (len = strlen(name))) {
131  if (!(pdo->name = (char *) kmalloc(len + 1, GFP_KERNEL))) {
132  EC_ERR("Failed to allocate PDO name.\n");
133  return -ENOMEM;
134  }
135  memcpy(pdo->name, name, len + 1);
136  } else {
137  pdo->name = NULL;
138  }
139 
140  return 0;
141 }
142 
143 /****************************************************************************/
144 
150  ec_pdo_t *pdo,
151  uint16_t index,
152  uint8_t subindex,
153  uint8_t bit_length
154  )
155 {
156  ec_pdo_entry_t *entry;
157 
158  if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
159  EC_ERR("Failed to allocate memory for PDO entry.\n");
160  return ERR_PTR(-ENOMEM);
161  }
162 
163  ec_pdo_entry_init(entry);
164  entry->index = index;
165  entry->subindex = subindex;
166  entry->bit_length = bit_length;
167  list_add_tail(&entry->list, &pdo->entries);
168  return entry;
169 }
170 
171 /****************************************************************************/
172 
179  ec_pdo_t *pdo,
180  const ec_pdo_t *other
181  )
182 {
183  ec_pdo_entry_t *entry, *other_entry;
184  int ret;
185 
187 
188  list_for_each_entry(other_entry, &other->entries, list) {
189  if (!(entry = (ec_pdo_entry_t *)
190  kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
191  EC_ERR("Failed to allocate memory for PDO entry copy.\n");
192  return -ENOMEM;
193  }
194 
195  ret = ec_pdo_entry_init_copy(entry, other_entry);
196  if (ret < 0) {
197  kfree(entry);
198  return ret;
199  }
200 
201  list_add_tail(&entry->list, &pdo->entries);
202  }
203 
204  return 0;
205 }
206 
207 /****************************************************************************/
208 
215  const ec_pdo_t *pdo1,
216  const ec_pdo_t *pdo2
217  )
218 {
219  const struct list_head *head1, *head2, *item1, *item2;
220  const ec_pdo_entry_t *entry1, *entry2;
221 
222  head1 = item1 = &pdo1->entries;
223  head2 = item2 = &pdo2->entries;
224 
225  while (1) {
226  item1 = item1->next;
227  item2 = item2->next;
228 
229  if ((item1 == head1) ^ (item2 == head2)) // unequal lengths
230  return 0;
231  if (item1 == head1) // both finished
232  break;
233 
234  entry1 = list_entry(item1, ec_pdo_entry_t, list);
235  entry2 = list_entry(item2, ec_pdo_entry_t, list);
236  if (!ec_pdo_entry_equal(entry1, entry2))
237  return 0;
238  }
239 
240  return 1;
241 }
242 
243 /****************************************************************************/
244 
249 unsigned int ec_pdo_entry_count(
250  const ec_pdo_t *pdo
251  )
252 {
253  const ec_pdo_entry_t *entry;
254  unsigned int num = 0;
255 
256  list_for_each_entry(entry, &pdo->entries, list) {
257  num++;
258  }
259 
260  return num;
261 }
262 
263 /****************************************************************************/
264 
272  const ec_pdo_t *pdo,
273  unsigned int pos
274  )
275 {
276  const ec_pdo_entry_t *entry;
277 
278  list_for_each_entry(entry, &pdo->entries, list) {
279  if (pos--)
280  continue;
281  return entry;
282  }
283 
284  return NULL;
285 }
286 
287 /****************************************************************************/
288 
292  const ec_pdo_t *pdo
293  )
294 {
295  const ec_pdo_entry_t *entry;
296 
297  if (list_empty(&pdo->entries)) {
298  printk(KERN_CONT "(none)");
299  } else {
300  list_for_each_entry(entry, &pdo->entries, list) {
301  printk(KERN_CONT "0x%04X:%02X/%u",
302  entry->index, entry->subindex, entry->bit_length);
303  if (entry->list.next != &pdo->entries)
304  printk(KERN_CONT " ");
305  }
306  }
307 }
308 
309 /****************************************************************************/
int ec_pdo_set_name(ec_pdo_t *pdo, const char *name)
Set PDO name.
Definition: pdo.c:117
void ec_pdo_clear_entries(ec_pdo_t *pdo)
Clear PDO entry list.
Definition: pdo.c:98
void ec_pdo_init(ec_pdo_t *pdo)
PDO constructor.
Definition: pdo.c:38
PDO entry description.
Definition: pdo_entry.h:40
ec_pdo_entry_t * ec_pdo_add_entry(ec_pdo_t *pdo, uint16_t index, uint8_t subindex, uint8_t bit_length)
Add a new PDO entry to the configuration.
Definition: pdo.c:149
void ec_pdo_clear(ec_pdo_t *pdo)
PDO destructor.
Definition: pdo.c:86
uint16_t index
PDO index.
Definition: pdo.h:43
int8_t sync_index
Assigned sync manager.
Definition: pdo.h:44
const ec_pdo_entry_t * ec_pdo_find_entry_by_pos_const(const ec_pdo_t *pdo, unsigned int pos)
Finds a PDO entry via its position in the list.
Definition: pdo.c:271
uint16_t index
PDO entry index.
Definition: pdo_entry.h:42
unsigned int ec_pdo_entry_count(const ec_pdo_t *pdo)
Get the number of PDO entries.
Definition: pdo.c:249
int ec_pdo_init_copy(ec_pdo_t *pdo, const ec_pdo_t *other_pdo)
PDO copy constructor.
Definition: pdo.c:54
void ec_pdo_entry_clear(ec_pdo_entry_t *entry)
PDO entry destructor.
Definition: pdo_entry.c:68
int ec_pdo_entry_equal(const ec_pdo_entry_t *entry1, const ec_pdo_entry_t *entry2)
Compares two PDO entries.
Definition: pdo_entry.c:114
PDO description.
Definition: pdo.h:41
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:45
int ec_pdo_entry_init_copy(ec_pdo_entry_t *entry, const ec_pdo_entry_t *other)
PDO entry copy constructor.
Definition: pdo_entry.c:51
int ec_pdo_equal_entries(const ec_pdo_t *pdo1, const ec_pdo_t *pdo2)
Compares the entries of two PDOs.
Definition: pdo.c:214
struct list_head entries
List of PDO entries.
Definition: pdo.h:46
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition: pdo_entry.c:37
uint8_t subindex
PDO entry subindex.
Definition: pdo_entry.h:43
char * name
PDO name.
Definition: pdo.h:45
int ec_pdo_copy_entries(ec_pdo_t *pdo, const ec_pdo_t *other)
Copy PDO entries from another PDO.
Definition: pdo.c:178
#define EC_ERR(fmt, args...)
Convenience macro for printing EtherCAT-specific errors to syslog.
Definition: globals.h:224
void ec_pdo_print_entries(const ec_pdo_t *pdo)
Outputs the PDOs in the list.
Definition: pdo.c:291
struct list_head list
list item
Definition: pdo_entry.h:41
EtherCAT Process data object structure.