/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool

« back to all changes in this revision

Viewing changes to pcilib/property.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-10-18 01:47:47 UTC
  • Revision ID: csa@suren.me-20151018014747-9ji2ygdhz1l9wnt5
Support properties of arbitrary type

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define _GNU_SOURCE
 
2
#include <stdio.h>
 
3
#include <string.h>
 
4
#include <strings.h>
 
5
#include <stdlib.h>
 
6
 
 
7
#include <views/register.h>
 
8
 
 
9
#include "pci.h"
 
10
#include "bank.h"
 
11
#include "view.h"
 
12
#include "register.h"
 
13
#include "property.h"
 
14
 
 
15
#include "tools.h"
 
16
#include "error.h"
 
17
 
 
18
int pcilib_add_register_properties(pcilib_t *ctx, size_t n, const pcilib_register_bank_t *banks, const pcilib_register_description_t *registers) {
 
19
    int err;
 
20
 
 
21
    pcilib_register_t i;
 
22
    pcilib_view_t cur_view = ctx->num_views;
 
23
    pcilib_view_context_t *view_ctx;
 
24
 
 
25
    if (!n) 
 
26
        return PCILIB_ERROR_INVALID_ARGUMENT;
 
27
 
 
28
 
 
29
    for (i = 0; i < n; i++) {
 
30
        pcilib_access_mode_t mode = 0;
 
31
 
 
32
        pcilib_register_view_description_t v;
 
33
        pcilib_register_bank_description_t *b = &ctx->banks[banks[i]];
 
34
 
 
35
        char *view_name = malloc(strlen(registers[i].name) + strlen(b->name) + 13);
 
36
        if (!view_name) {
 
37
            pcilib_clean_views(ctx, cur_view);
 
38
            return PCILIB_ERROR_MEMORY;
 
39
        }
 
40
 
 
41
        sprintf(view_name, "/registers/%s/%s", b->name, registers[i].name);
 
42
 
 
43
        if ((registers[i].views)&&(registers[i].views[0].view)) {
 
44
            pcilib_view_t view = pcilib_find_view_by_name(ctx, registers[i].views[0].view);
 
45
            if (view == PCILIB_VIEW_INVALID) return PCILIB_ERROR_NOTFOUND;
 
46
 
 
47
            memcpy(&v, ctx->views[view], sizeof(pcilib_view_description_t));
 
48
            v.view = registers[i].views[0].name;
 
49
 
 
50
            if (ctx->views[view]->api->read_from_reg) mode |= PCILIB_ACCESS_R;
 
51
            if (ctx->views[view]->api->write_to_reg) mode |= PCILIB_ACCESS_W;
 
52
            mode &= ctx->views[view]->mode;
 
53
        } else {
 
54
            v.base.type = PCILIB_TYPE_LONG;
 
55
            mode = PCILIB_ACCESS_RW;
 
56
        }
 
57
 
 
58
        v.base.api = &pcilib_register_view_api;
 
59
        v.base.name = view_name;
 
60
        v.base.description = registers[i].description;
 
61
        v.base.mode = registers[i].mode&mode;
 
62
        v.reg = registers[i].name;
 
63
        v.bank = b->name;
 
64
 
 
65
        err = pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&v);
 
66
        if (err) {
 
67
            free(view_name);
 
68
            pcilib_clean_views(ctx, cur_view);
 
69
            return err;
 
70
        }
 
71
 
 
72
        view_ctx = pcilib_find_view_context_by_name(ctx, v.base.name);
 
73
        view_ctx->flags |= PCILIB_VIEW_FLAG_PROPERTY;
 
74
    }
 
75
 
 
76
    return 0;
 
77
}
 
78
 
 
79
pcilib_property_info_t *pcilib_get_property_list(pcilib_t *ctx, const char *branch, pcilib_list_flags_t flags) {
 
80
    int err = 0;
 
81
 
 
82
    size_t pos = 0;
 
83
    size_t name_offset = 0;
 
84
    pcilib_view_context_t *view_ctx, *view_tmp;
 
85
    pcilib_property_info_t *info = (pcilib_property_info_t*)malloc((ctx->num_views + 1) * sizeof(pcilib_property_info_t));
 
86
 
 
87
    struct dir_hash_s {
 
88
        char *name;
 
89
        UT_hash_handle hh;
 
90
    } *dir_hash = NULL, *dir, *dir_tmp;
 
91
 
 
92
    if (branch) {
 
93
        name_offset = strlen(branch);
 
94
        if (branch[name_offset - 1] != '/') name_offset++;
 
95
    }
 
96
 
 
97
        // Find all folders
 
98
    HASH_ITER(hh, ctx->view_hash, view_ctx, view_tmp) {
 
99
        const pcilib_view_description_t *v = ctx->views[view_ctx->view];
 
100
        const char *subname = v->name + name_offset;
 
101
        const char *suffix;
 
102
 
 
103
        if (!(view_ctx->flags&PCILIB_VIEW_FLAG_PROPERTY)) continue;
 
104
        if ((branch)&&(strncasecmp(branch, v->name, strlen(branch)))) continue;
 
105
 
 
106
        suffix = strchr(subname, '/');
 
107
        if (suffix) {
 
108
            char *name = strndup(v->name, suffix - v->name);
 
109
            if (!name) {
 
110
                err = PCILIB_ERROR_MEMORY;
 
111
                break;
 
112
            }
 
113
 
 
114
            HASH_FIND_STR(dir_hash, name + name_offset, dir);
 
115
            if (dir) {
 
116
                free(name);
 
117
                continue;
 
118
            }
 
119
 
 
120
 
 
121
            dir = (struct dir_hash_s*)malloc(sizeof(struct dir_hash_s));
 
122
            if (!dir) {
 
123
                err = PCILIB_ERROR_MEMORY;
 
124
                break;
 
125
            }
 
126
 
 
127
            dir->name = name;
 
128
 
 
129
            HASH_ADD_KEYPTR(hh, dir_hash, dir->name + name_offset, strlen(dir->name + name_offset), dir);
 
130
        }
 
131
    }
 
132
 
 
133
    HASH_ITER(hh, ctx->view_hash, view_ctx, view_tmp) {
 
134
        const pcilib_view_description_t *v = ctx->views[view_ctx->view];
 
135
        const char *subname = v->name + name_offset;
 
136
 
 
137
        if (!(view_ctx->flags&PCILIB_VIEW_FLAG_PROPERTY)) continue;
 
138
        if ((branch)&&(strncasecmp(branch, v->name, strlen(branch)))) continue;
 
139
 
 
140
        if (!strchr(subname, '/')) {
 
141
            pcilib_view_context_t *found_view;
 
142
 
 
143
            char *path = strdup(v->name);
 
144
            if (!path) {
 
145
                err = PCILIB_ERROR_MEMORY;
 
146
                break;
 
147
            }
 
148
            char *name = strrchr(v->name, '/');
 
149
            if (name) name++;
 
150
            else name = path;
 
151
 
 
152
            HASH_FIND_STR(dir_hash, name, found_view);
 
153
 
 
154
            info[pos++] = (pcilib_property_info_t) {
 
155
                .name = name,
 
156
                .path = path,
 
157
                .description = v->description,
 
158
                .type = v->type,
 
159
                .mode = v->mode,
 
160
                .unit = v->unit,
 
161
                .flags = (found_view?PCILIB_LIST_FLAG_CHILDS:0)
 
162
            };
 
163
 
 
164
            if (found_view) HASH_DEL(dir_hash, found_view);
 
165
        }
 
166
    }
 
167
 
 
168
    HASH_ITER(hh, dir_hash, dir, dir_tmp) {
 
169
        char *name = strrchr(dir->name, '/');
 
170
        if (name) name++;
 
171
        else name = dir->name;
 
172
 
 
173
        info[pos++] = (pcilib_property_info_t) {
 
174
            .name = name,
 
175
            .path = dir->name,
 
176
            .type = PCILIB_TYPE_INVALID,
 
177
            .flags = PCILIB_LIST_FLAG_CHILDS
 
178
        };
 
179
    }
 
180
 
 
181
    HASH_CLEAR(hh, dir_hash);
 
182
 
 
183
    memset(&info[pos], 0, sizeof(pcilib_property_info_t));
 
184
 
 
185
    if (err) {
 
186
        pcilib_free_property_info(ctx, info);
 
187
        return NULL;
 
188
    }
 
189
 
 
190
    return info;
 
191
}
 
192
 
 
193
void pcilib_free_property_info(pcilib_t *ctx, pcilib_property_info_t *info) {
 
194
    int i;
 
195
 
 
196
    for (i = 0; info[i].path; i++)
 
197
        free((char*)info[i].path);
 
198
    free(info);
 
199
}
 
200
 
 
201
int pcilib_get_property(pcilib_t *ctx, const char *prop, pcilib_value_t *val) {
 
202
    return pcilib_read_register_view(ctx, NULL, NULL, prop, val);
 
203
}
 
204
 
 
205
int pcilib_set_property(pcilib_t *ctx, const char *prop, const pcilib_value_t *val) {
 
206
    return pcilib_write_register_view(ctx, NULL, NULL, prop, val);
 
207
}