GCC Code Coverage Report


Directory: ./
File: pdserv/src/lib/interface.cpp
Date: 2025-08-17 04:10:43
Exec Total Coverage
Lines: 56 131 42.7%
Branches: 10 77 13.0%

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