Directory: | ./ |
---|---|
File: | pdserv/src/lib/interface.cpp |
Date: | 2024-12-15 04:08:34 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 56 | 128 | 43.8% |
Branches: | 10 | 73 | 13.7% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /***************************************************************************** | ||
2 | * | ||
3 | * $Id$ | ||
4 | * | ||
5 | * Copyright 2010 Richard Hacker (lerichi at gmx dot net) | ||
6 | * | ||
7 | * This file is part of the pdserv library. | ||
8 | * | ||
9 | * The pdserv library is free software: you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published | ||
11 | * by the Free Software Foundation, either version 3 of the License, or (at | ||
12 | * your option) any later version. | ||
13 | * | ||
14 | * The pdserv library is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | ||
17 | * License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>. | ||
21 | * | ||
22 | *****************************************************************************/ | ||
23 | |||
24 | #include "Main.h" | ||
25 | #include "Task.h" | ||
26 | #include "Signal.h" | ||
27 | #include "Event.h" | ||
28 | #include "Parameter.h" | ||
29 | #include "../DataType.h" | ||
30 | #include <pdserv.h> | ||
31 | #include <git_revision_hash.h> | ||
32 | |||
33 | typedef std::vector<PdServ::DataType*> CompoundVector; | ||
34 | 3 | CompoundVector compoundType; | |
35 | |||
36 | const char* const pdserv_version_str = QUOTE(PDSERV_VERSION_MAJOR) | ||
37 | "." QUOTE(PDSERV_VERSION_MINOR) | ||
38 | "." QUOTE(PDSERV_VERSION_PATCH); | ||
39 | const char* const pdserv_full_version = GIT_REV; | ||
40 | |||
41 | static const PdServ::DataType& getDataType(int dt); | ||
42 | |||
43 | ///////////////////////////////////////////////////////////////////////////// | ||
44 | 157 | struct pdserv* pdserv_create( const char *name, const char *version, | |
45 | int (*gettime)(struct timespec*)) | ||
46 | { | ||
47 | return reinterpret_cast<struct pdserv*>( | ||
48 |
1/2✓ Branch 3 taken 157 times.
✗ Branch 4 not taken.
|
157 | new Main(name, version, gettime)); |
49 | } | ||
50 | |||
51 | ///////////////////////////////////////////////////////////////////////////// | ||
52 | 149 | void pdserv_config_file( struct pdserv* pdserv, const char *name) | |
53 | { | ||
54 | 149 | reinterpret_cast<Main*>(pdserv)->setConfigFile(name); | |
55 | 149 | } | |
56 | |||
57 | ///////////////////////////////////////////////////////////////////////////// | ||
58 | 157 | void pdserv_set_parameter_writelock_cb(struct pdserv* pdserv, | |
59 | void (*fn)(int, void*), void* priv_data) | ||
60 | { | ||
61 | 157 | reinterpret_cast<Main*>(pdserv)->setParameterWriteLock(fn, priv_data); | |
62 | 157 | } | |
63 | |||
64 | ///////////////////////////////////////////////////////////////////////////// | ||
65 | 314 | struct pdtask* pdserv_create_task(struct pdserv* pdserv, double tsample, | |
66 | const char *name) | ||
67 | { | ||
68 | return reinterpret_cast<struct pdtask*>( | ||
69 | 314 | reinterpret_cast<Main*>(pdserv)->addTask(tsample, name)); | |
70 | } | ||
71 | |||
72 | ///////////////////////////////////////////////////////////////////////////// | ||
73 | 314 | void pdserv_set_signal_readlock_cb(struct pdtask* pdtask, | |
74 | void (*fn)(int, void*), void* priv_data) | ||
75 | { | ||
76 | 314 | reinterpret_cast<Task*>(pdtask)->setSignalReadLock(fn, priv_data); | |
77 | 314 | } | |
78 | |||
79 | ///////////////////////////////////////////////////////////////////////////// | ||
80 | ✗ | int pdserv_create_compound( const char *name, size_t size) | |
81 | { | ||
82 | ✗ | int dt = pd_datatype_end + compoundType.size(); | |
83 | ✗ | compoundType.push_back(new PdServ::DataType(name, size)); | |
84 | ✗ | return dt; | |
85 | } | ||
86 | |||
87 | ///////////////////////////////////////////////////////////////////////////// | ||
88 | ✗ | void pdserv_compound_add_field(int compound, const char *name, | |
89 | int data_type, size_t offset, size_t ndims, const size_t *dim) | ||
90 | { | ||
91 | ✗ | compoundType[compound - pd_datatype_end] | |
92 | ✗ | ->addField(name, getDataType(data_type), offset, ndims, dim); | |
93 | } | ||
94 | |||
95 | ///////////////////////////////////////////////////////////////////////////// | ||
96 | 157 | void pdserv_exit(struct pdserv* pdserv) | |
97 | { | ||
98 | 157 | for (CompoundVector::const_iterator it = compoundType.begin(); | |
99 |
1/2✗ Branch 6 not taken.
✓ Branch 7 taken 157 times.
|
157 | it != compoundType.end(); ++it) |
100 | ✗ | delete *it; | |
101 |
1/2✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
|
157 | delete reinterpret_cast<Main*>(pdserv); |
102 | 157 | } | |
103 | |||
104 | ///////////////////////////////////////////////////////////////////////////// | ||
105 | ✗ | void pdserv_update_statistics(struct pdtask* task, | |
106 | double exec_time, double cycle_time, unsigned int overrun) | ||
107 | { | ||
108 | ✗ | reinterpret_cast<Task*>(task)->updateStatistics( | |
109 | exec_time, cycle_time, overrun); | ||
110 | } | ||
111 | |||
112 | ///////////////////////////////////////////////////////////////////////////// | ||
113 | 4191 | void pdserv_update(struct pdtask* task, const struct timespec *t) | |
114 | { | ||
115 | 4191 | reinterpret_cast<Task*>(task)->rt_update(t); | |
116 | 4191 | } | |
117 | |||
118 | ///////////////////////////////////////////////////////////////////////////// | ||
119 | ✗ | static const PdServ::DataType& getExtendedDataType(int dt) | |
120 | { | ||
121 | ✗ | int size = 0; | |
122 | ✗ | switch (dt) { | |
123 | ✗ | case pd_schar_T: size = sizeof(signed char); break; // 12 | |
124 | ✗ | case pd_char_T: size = sizeof(char); break; // 13 | |
125 | ✗ | case pd_uchar_T: size = sizeof(unsigned char); break; // 14 | |
126 | ✗ | case pd_short_T: size = sizeof(short); break; // 15 | |
127 | ✗ | case pd_ushort_T: size = sizeof(unsigned short); break; // 16 | |
128 | ✗ | case pd_int_T: size = sizeof(int); break; // 17 | |
129 | ✗ | case pd_uint_T: size = sizeof(unsigned int); break; // 18 | |
130 | ✗ | case pd_long_T: size = sizeof(long); break; // 19 | |
131 | ✗ | case pd_ulong_T: size = sizeof(unsigned long); break; // 20 | |
132 | ✗ | case pd_longlong_T: size = sizeof(long long); break; // 21 | |
133 | ✗ | case pd_ulonglong_T: size = sizeof(unsigned long long); break; // 22 | |
134 | ✗ | case pd_ssize_T: size = sizeof(ssize_t); break; // 23 | |
135 | ✗ | case pd_size_T: size = sizeof(size_t); break; // 24 | |
136 | } | ||
137 | |||
138 | ✗ | int sign = 0; | |
139 | ✗ | switch (dt) { | |
140 | ✗ | case pd_uchar_T: | |
141 | case pd_ushort_T: | ||
142 | case pd_uint_T: | ||
143 | case pd_ulong_T: | ||
144 | case pd_ulonglong_T: | ||
145 | ✗ | case pd_size_T: sign = 1; break; | |
146 | } | ||
147 | |||
148 | ✗ | switch (size) { | |
149 | ✗ | case 1: return sign | |
150 | ✗ | ? PdServ::DataType::uint8 : PdServ::DataType::int8; | |
151 | ✗ | case 2: return sign | |
152 | ✗ | ? PdServ::DataType::uint16 : PdServ::DataType::int16; | |
153 | ✗ | case 4: return sign | |
154 | ✗ | ? PdServ::DataType::uint32 : PdServ::DataType::int32; | |
155 | ✗ | case 8: return sign | |
156 | ✗ | ? PdServ::DataType::uint64 : PdServ::DataType::int64; | |
157 | ✗ | default: | |
158 | ✗ | return *compoundType[dt - pd_datatype_end]; | |
159 | } | ||
160 | } | ||
161 | |||
162 | ///////////////////////////////////////////////////////////////////////////// | ||
163 | 1884 | static const PdServ::DataType& getDataType(int dt) | |
164 | { | ||
165 |
4/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 314 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 157 times.
✓ Branch 7 taken 942 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 471 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
1884 | switch (dt) { |
166 | ✗ | case pd_boolean_T: return PdServ::DataType::boolean; | |
167 | ✗ | case pd_uint8_T: return PdServ::DataType::uint8; | |
168 | ✗ | case pd_uint16_T: return PdServ::DataType::uint16; | |
169 | 314 | case pd_uint32_T: return PdServ::DataType::uint32; | |
170 | ✗ | case pd_uint64_T: return PdServ::DataType::uint64; | |
171 | ✗ | case pd_sint8_T: return PdServ::DataType::int8; | |
172 | 157 | case pd_sint16_T: return PdServ::DataType::int16; | |
173 | 942 | case pd_sint32_T: return PdServ::DataType::int32; | |
174 | ✗ | case pd_sint64_T: return PdServ::DataType::int64; | |
175 | 471 | case pd_double_T: return PdServ::DataType::float64; | |
176 | ✗ | case pd_single_T: return PdServ::DataType::float32; | |
177 | ✗ | default: | |
178 | ✗ | return getExtendedDataType(dt); | |
179 | } | ||
180 | } | ||
181 | |||
182 | ///////////////////////////////////////////////////////////////////////////// | ||
183 | 314 | struct pdevent *pdserv_event ( | |
184 | struct pdserv* pdserv, const char *path, size_t n) | ||
185 | { | ||
186 | 314 | Main *main = reinterpret_cast<Main*>(pdserv); | |
187 | |||
188 | return reinterpret_cast<struct pdevent *>( | ||
189 | 314 | main->addEvent(path, n, 0)); | |
190 | } | ||
191 | |||
192 | ///////////////////////////////////////////////////////////////////////////// | ||
193 | 314 | void pdserv_event_set_text (struct pdevent* event, const char * const *text) | |
194 | { | ||
195 | 314 | reinterpret_cast<Event*>(event)->message = text; | |
196 | 314 | } | |
197 | |||
198 | ///////////////////////////////////////////////////////////////////////////// | ||
199 | 27 | void pdserv_event_set(const struct pdevent *event, | |
200 | size_t element, int prio, const timespec *t) | ||
201 | { | ||
202 | static const Event::Priority map[] = { | ||
203 | Event::Reset, | ||
204 | Event::Emergency, | ||
205 | Event::Alert, | ||
206 | Event::Critical, | ||
207 | Event::Error, | ||
208 | Event::Warning, | ||
209 | Event::Notice, | ||
210 | Event::Info, | ||
211 | Event::Debug, | ||
212 | }; | ||
213 | |||
214 |
2/4✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
|
54 | reinterpret_cast<const Event*>(event)->set( |
215 | 27 | element, prio < 9 ? map[prio] : Event::Debug, t); | |
216 | 27 | } | |
217 | |||
218 | ///////////////////////////////////////////////////////////////////////////// | ||
219 | 11 | void pdserv_event_reset(const struct pdevent *event, | |
220 | size_t element, const timespec *t) | ||
221 | { | ||
222 | 11 | pdserv_event_set(event, element, RESET_EVENT, t); | |
223 | 11 | } | |
224 | |||
225 | ///////////////////////////////////////////////////////////////////////////// | ||
226 | ✗ | void pdserv_event_set_all(const struct pdevent *event, | |
227 | const unsigned int* prio, const timespec *t) | ||
228 | { | ||
229 | ✗ | size_t count = reinterpret_cast<const Event*>(event)->nelem; | |
230 | ✗ | for (size_t i = 0; i < count; ++i) | |
231 | ✗ | pdserv_event_set(event, i, *prio++, t); | |
232 | } | ||
233 | |||
234 | ///////////////////////////////////////////////////////////////////////////// | ||
235 | 942 | struct pdvariable *pdserv_signal( | |
236 | struct pdtask* pdtask, | ||
237 | unsigned int decimation, | ||
238 | const char *path, | ||
239 | int datatype, | ||
240 | const void *addr, | ||
241 | size_t n, | ||
242 | const size_t *dim | ||
243 | ) | ||
244 | { | ||
245 | 942 | Task *task = reinterpret_cast<Task*>(pdtask); | |
246 | |||
247 | 942 | Signal *s = task->addSignal( | |
248 | 942 | decimation, path, getDataType(datatype), addr, n, dim); | |
249 | |||
250 | return reinterpret_cast<struct pdvariable *>( | ||
251 | 942 | static_cast<PdServ::Variable*>(s)); | |
252 | } | ||
253 | |||
254 | ///////////////////////////////////////////////////////////////////////////// | ||
255 | ✗ | void pdserv_signal_set_read_cb( | |
256 | struct pdvariable* var, | ||
257 | read_signal_t read_cb, | ||
258 | void* priv_data | ||
259 | ) | ||
260 | { | ||
261 | Signal* s = | ||
262 | ✗ | static_cast<Signal*>(reinterpret_cast<PdServ::Variable*>(var)); | |
263 | |||
264 | ✗ | if (read_cb) | |
265 | ✗ | s->read_cb = read_cb; | |
266 | ✗ | s->priv_data = priv_data; | |
267 | } | ||
268 | |||
269 | ///////////////////////////////////////////////////////////////////////////// | ||
270 | ✗ | struct pdvariable *pdserv_signal_cb( | |
271 | struct pdtask* pdtask, | ||
272 | unsigned int decimation, | ||
273 | const char *path, | ||
274 | int datatype, | ||
275 | const void *addr, | ||
276 | size_t n, | ||
277 | const size_t *dim, | ||
278 | read_signal_t read_cb, | ||
279 | void* priv_data | ||
280 | ) | ||
281 | { | ||
282 | struct pdvariable* var = | ||
283 | ✗ | pdserv_signal(pdtask, decimation, path, datatype, addr, n, dim); | |
284 | ✗ | pdserv_signal_set_read_cb(var, read_cb, priv_data); | |
285 | ✗ | return var; | |
286 | } | ||
287 | |||
288 | ///////////////////////////////////////////////////////////////////////////// | ||
289 | 942 | struct pdvariable *pdserv_parameter( | |
290 | struct pdserv* pdserv, | ||
291 | const char *path, | ||
292 | unsigned int mode, | ||
293 | int datatype, | ||
294 | void *addr, | ||
295 | size_t n, | ||
296 | const size_t *dim, | ||
297 | write_parameter_t trigger = 0, | ||
298 | void *priv_data = 0 | ||
299 | ) | ||
300 | { | ||
301 | 942 | Main *main = reinterpret_cast<Main*>(pdserv); | |
302 | |||
303 | 942 | Parameter *p = main->addParameter( | |
304 | 942 | path, mode, getDataType(datatype), addr, n, dim); | |
305 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 942 times.
|
942 | if (trigger) |
306 | ✗ | p->write_cb = trigger; | |
307 | 942 | p->priv_data = priv_data; | |
308 | |||
309 | return reinterpret_cast<struct pdvariable *> | ||
310 | 942 | (static_cast<PdServ::Variable*>(p)); | |
311 | } | ||
312 | |||
313 | ///////////////////////////////////////////////////////////////////////////// | ||
314 | ✗ | void pdserv_set_alias(struct pdvariable *var, const char *alias) | |
315 | { | ||
316 | ✗ | reinterpret_cast<PdServ::Variable*>(var)->alias = alias; | |
317 | } | ||
318 | |||
319 | ///////////////////////////////////////////////////////////////////////////// | ||
320 | ✗ | void pdserv_set_unit(struct pdvariable *var, const char *unit) | |
321 | { | ||
322 | ✗ | reinterpret_cast<PdServ::Variable*>(var)->unit = unit; | |
323 | } | ||
324 | |||
325 | ///////////////////////////////////////////////////////////////////////////// | ||
326 | ✗ | void pdserv_set_comment(struct pdvariable *var, const char *comment) | |
327 | { | ||
328 | ✗ | reinterpret_cast<PdServ::Variable*>(var)->comment = comment; | |
329 | } | ||
330 | |||
331 | ///////////////////////////////////////////////////////////////////////////// | ||
332 | 156 | int pdserv_prepare(struct pdserv* pdserv) | |
333 | { | ||
334 | 156 | return reinterpret_cast<Main*>(pdserv)->setup(); | |
335 | } | ||
336 | |||
337 | ///////////////////////////////////////////////////////////////////////////// | ||
338 | ✗ | const char *pdserv_get_variable_path(const struct pdvariable *var) | |
339 | { | ||
340 | ✗ | return reinterpret_cast<const PdServ::Variable*>(var)->path.c_str(); | |
341 | 9 | } | |
342 |