00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00035
00036
00037 #include <linux/slab.h>
00038 #include <linux/err.h>
00039
00040 #include "pdo.h"
00041
00042
00043
00046 void ec_pdo_init(
00047 ec_pdo_t *pdo
00048 )
00049 {
00050 pdo->sync_index = -1;
00051 pdo->name = NULL;
00052 INIT_LIST_HEAD(&pdo->entries);
00053 }
00054
00055
00056
00062 int ec_pdo_init_copy(
00063 ec_pdo_t *pdo,
00064 const ec_pdo_t *other_pdo
00065 )
00066 {
00067 int ret = 0;
00068
00069 pdo->index = other_pdo->index;
00070 pdo->sync_index = other_pdo->sync_index;
00071 pdo->name = NULL;
00072 INIT_LIST_HEAD(&pdo->entries);
00073
00074 ret = ec_pdo_set_name(pdo, other_pdo->name);
00075 if (ret < 0)
00076 goto out_return;
00077
00078 ret = ec_pdo_copy_entries(pdo, other_pdo);
00079 if (ret < 0)
00080 goto out_clear;
00081
00082 return 0;
00083
00084 out_clear:
00085 ec_pdo_clear(pdo);
00086 out_return:
00087 return ret;
00088 }
00089
00090
00091
00094 void ec_pdo_clear(ec_pdo_t *pdo )
00095 {
00096 if (pdo->name)
00097 kfree(pdo->name);
00098
00099 ec_pdo_clear_entries(pdo);
00100 }
00101
00102
00103
00106 void ec_pdo_clear_entries(ec_pdo_t *pdo )
00107 {
00108 ec_pdo_entry_t *entry, *next;
00109
00110
00111 list_for_each_entry_safe(entry, next, &pdo->entries, list) {
00112 list_del(&entry->list);
00113 ec_pdo_entry_clear(entry);
00114 kfree(entry);
00115 }
00116 }
00117
00118
00119
00125 int ec_pdo_set_name(
00126 ec_pdo_t *pdo,
00127 const char *name
00128 )
00129 {
00130 unsigned int len;
00131
00132 if (pdo->name && name && !strcmp(pdo->name, name))
00133 return 0;
00134
00135 if (pdo->name)
00136 kfree(pdo->name);
00137
00138 if (name && (len = strlen(name))) {
00139 if (!(pdo->name = (char *) kmalloc(len + 1, GFP_KERNEL))) {
00140 EC_ERR("Failed to allocate PDO name.\n");
00141 return -ENOMEM;
00142 }
00143 memcpy(pdo->name, name, len + 1);
00144 } else {
00145 pdo->name = NULL;
00146 }
00147
00148 return 0;
00149 }
00150
00151
00152
00157 ec_pdo_entry_t *ec_pdo_add_entry(
00158 ec_pdo_t *pdo,
00159 uint16_t index,
00160 uint8_t subindex,
00161 uint8_t bit_length
00162 )
00163 {
00164 ec_pdo_entry_t *entry;
00165
00166 if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
00167 EC_ERR("Failed to allocate memory for PDO entry.\n");
00168 return ERR_PTR(-ENOMEM);
00169 }
00170
00171 ec_pdo_entry_init(entry);
00172 entry->index = index;
00173 entry->subindex = subindex;
00174 entry->bit_length = bit_length;
00175 list_add_tail(&entry->list, &pdo->entries);
00176 return entry;
00177 }
00178
00179
00180
00186 int ec_pdo_copy_entries(
00187 ec_pdo_t *pdo,
00188 const ec_pdo_t *other
00189 )
00190 {
00191 ec_pdo_entry_t *entry, *other_entry;
00192 int ret;
00193
00194 ec_pdo_clear_entries(pdo);
00195
00196 list_for_each_entry(other_entry, &other->entries, list) {
00197 if (!(entry = (ec_pdo_entry_t *)
00198 kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
00199 EC_ERR("Failed to allocate memory for PDO entry copy.\n");
00200 return -ENOMEM;
00201 }
00202
00203 ret = ec_pdo_entry_init_copy(entry, other_entry);
00204 if (ret < 0) {
00205 kfree(entry);
00206 return ret;
00207 }
00208
00209 list_add_tail(&entry->list, &pdo->entries);
00210 }
00211
00212 return 0;
00213 }
00214
00215
00216
00222 int ec_pdo_equal_entries(
00223 const ec_pdo_t *pdo1,
00224 const ec_pdo_t *pdo2
00225 )
00226 {
00227 const struct list_head *head1, *head2, *item1, *item2;
00228 const ec_pdo_entry_t *entry1, *entry2;
00229
00230 head1 = item1 = &pdo1->entries;
00231 head2 = item2 = &pdo2->entries;
00232
00233 while (1) {
00234 item1 = item1->next;
00235 item2 = item2->next;
00236
00237 if ((item1 == head1) ^ (item2 == head2))
00238 return 0;
00239 if (item1 == head1)
00240 break;
00241
00242 entry1 = list_entry(item1, ec_pdo_entry_t, list);
00243 entry2 = list_entry(item2, ec_pdo_entry_t, list);
00244 if (!ec_pdo_entry_equal(entry1, entry2))
00245 return 0;
00246 }
00247
00248 return 1;
00249 }
00250
00251
00252
00257 unsigned int ec_pdo_entry_count(
00258 const ec_pdo_t *pdo
00259 )
00260 {
00261 const ec_pdo_entry_t *entry;
00262 unsigned int num = 0;
00263
00264 list_for_each_entry(entry, &pdo->entries, list) {
00265 num++;
00266 }
00267
00268 return num;
00269 }
00270
00271
00272
00279 const ec_pdo_entry_t *ec_pdo_find_entry_by_pos_const(
00280 const ec_pdo_t *pdo,
00281 unsigned int pos
00282 )
00283 {
00284 const ec_pdo_entry_t *entry;
00285
00286 list_for_each_entry(entry, &pdo->entries, list) {
00287 if (pos--)
00288 continue;
00289 return entry;
00290 }
00291
00292 return NULL;
00293 }
00294
00295
00296
00299 void ec_pdo_print_entries(
00300 const ec_pdo_t *pdo
00301 )
00302 {
00303 const ec_pdo_entry_t *entry;
00304
00305 if (list_empty(&pdo->entries)) {
00306 printk("(none)");
00307 } else {
00308 list_for_each_entry(entry, &pdo->entries, list) {
00309 printk("0x%04X:%02X/%u",
00310 entry->index, entry->subindex, entry->bit_length);
00311 if (entry->list.next != &pdo->entries)
00312 printk(" ");
00313 }
00314 }
00315 }
00316
00317