BOROSOFTWAREAll work →
scantool/diag_cfg.c 352 lines
3 findings in this fileB3L7B4L132B2L210
1/* freediag
2 *
3 * Configurable items code
4 *
5 * (c) fenugrec 2015
6 * GPLv3
7 *
8 */
9
10
11#include "diag.h"
12#include "diag_cfg.h"
13#include "diag_err.h"
14#include "diag_tty.h" //for diag_tty_getportlist()
15
16#include <assert.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21static const char tty_descr[]="Serial/tty port, such as \"/dev/ttyS0\" or \"\\\\.\\COM11\"";
22static const char tty_sn[]="port"; /** tty cfg shortname */
23static const char tty_def[]="/dev/null"; /** last resort fallback */
24
25/* top decls */
26void optarray_clear(struct cfgi *cfgp);
27
28
29//Optional func to refresh opt[] and numopts (for tty, J2534, etc), doesn't change *val
30void diag_cfg_refresh(struct cfgi *cfgp) {
31 if (cfgp->refresh) {
32 cfgp->refresh(cfgp);
33 }
34 return;
35}
36
37//Optional: func to reset *val to default; doesn't call refresh()
38void diag_cfg_reset(struct cfgi *cfgp) {
39 if (cfgp->reset) {
40 cfgp->reset(cfgp);
41 }
42 return;
43}
44
45
46int diag_cfg_setstr(struct cfgi *cfgp, const char *str) {
47 size_t slen;
48 int rv;
49
50 if (cfgp->type != CFGT_STR) {
51 return diag_iseterr(DIAG_ERR_BADCFG);
52 }
53
54 slen=strlen(str);
55 if (cfgp->dyn_val && (cfgp->val.str != NULL)) {
56 free(cfgp->val.str);
57 cfgp->val.str = NULL;
58 }
59 rv = diag_malloc(&cfgp->val.str, slen+1);
60 if (rv != 0) {
61 return diag_ifwderr(rv);
62 }
63 cfgp->dyn_val = 1; //need to free
64 strcpy(cfgp->val.str, str);
65 return 0;
66
67}
68
69//set config value for a BOOL param
70int diag_cfg_setbool(struct cfgi *cfgp, bool val) {
71 if (cfgp->type == CFGT_BOOL) {
72 cfgp->val.b = val;
73 return 0;
74 }
75 return diag_iseterr(DIAG_ERR_BADCFG);
76}
77
78//
79int diag_cfg_setu8(struct cfgi *cfgp, uint8_t val) {
80 if (cfgp->type == CFGT_U8) {
81 cfgp->val.u8 = val;
82 return 0;
83 }
84 return diag_iseterr(DIAG_ERR_BADCFG);
85}
86
87int diag_cfg_setint(struct cfgi *cfgp, int val) {
88 if (cfgp->type == CFGT_INT) {
89 cfgp->val.i = val;
90 return 0;
91 }
92 return diag_iseterr(DIAG_ERR_BADCFG);
93}
94
95//set config value to one of the predefined options. Ret 0 if ok
96int diag_cfg_setopt(struct cfgi *cfgp, int optid) {
97 if (optid > (cfgp->numopts - 1)) {
98 return diag_iseterr(DIAG_ERR_BADCFG);
99 }
100 switch (cfgp->type) {
101 case CFGT_STR:
102 if (cfgp->opt[optid] == NULL) {
103 return diag_iseterr(DIAG_ERR_BADCFG);
104 }
105 diag_cfg_setstr(cfgp, cfgp->opt[optid]);
106 break;
107
108 case CFGT_INT:
109 cfgp->val.i = optid;
110 break;
111 case CFGT_U8: //these don't really make sense
112 case CFGT_BOOL:
113 break;
114 default:
115 assert(0);
116 break;
117 }
118 return 0;
119}
120
121//directly set param value (caller knows correct type and handles mem management, etc) BAD
122//void diag_cfg_setraw(struct cfgi *cfgp, void *val) {}
123
124//get param value, as new string to be free'd by caller.
125//for u8 / int types, sprintf with %X and %d formatters respectively
126char *diag_cfg_getstr(struct cfgi *cfgp) {
127 char *str;
128 size_t len = 0;
129 int rv;
130
131 /* determine required length first */
132 switch (cfgp->type) {
133 case CFGT_U8:
134 len=5;
135 break;
136 case CFGT_INT:
137 //handle 7 digits.
138 len=8;
139 break;
140 case CFGT_STR:
141 len=strlen(cfgp->val.str)+1;
142 break;
143 default:
144 assert(0);
145 break;
146 }
147
148 rv = diag_malloc(&str, len);
149 if (rv != 0) {
150 return diag_pfwderr(rv);
151 }
152
153 /* fill str */
154 switch (cfgp->type) {
155 case CFGT_U8:
156 snprintf(str, len, "0x%02X", (unsigned) cfgp->val.u8);
157 break;
158 case CFGT_INT:
159 snprintf(str, len, "%7d", cfgp->val.i);
160 break;
161 case CFGT_STR:
162 memcpy(str, cfgp->val.str, len);
163 break;
164 default:
165 assert(0);
166 break;
167 }
168
169 return str;
170}
171
172//free contents of *cfgp (prior to free'ing the struct itself, for instance)
173void diag_cfg_clear(struct cfgi *cfgp) {
174 /* For now, handles only CFGT_STR types */
175 if (cfgp->type != CFGT_STR) {
176 return;
177 }
178 if (cfgp->dyn_val && (cfgp->val.str != NULL)) {
179 free(cfgp->val.str);
180 }
181 cfgp->dyn_val = 0;
182 cfgp->val.str=NULL;
183
184 optarray_clear(cfgp);
185
186 if (cfgp->dyn_dval && (cfgp->dval.str != NULL)) {
187 free(cfgp->dval.str);
188 }
189 cfgp->dyn_dval = 0;
190 cfgp->dval.str=NULL;
191}
192
193
194/*** struct management funcs ***/
195
196//clear / free ->opt[] array
197void optarray_clear(struct cfgi *cfgp) {
198 if (cfgp->dyn_opt && (cfgp->opt != NULL)) {
199 /* Need to free every string, and the array of string ptrs */
200 strlist_free(cfgp->opt, cfgp->numopts);
201 }
202 cfgp->dyn_opt = 0;
203 cfgp->opt=NULL;
204 cfgp->numopts = 0;
205}
206
207//stock reset() function
208void std_reset(struct cfgi *cfgp) {
209 switch (cfgp->type) {
210 case CFGT_U8:
211 cfgp->val.b = cfgp->dval.b;
212 break;
213 case CFGT_INT:
214 cfgp->val.i = cfgp->dval.i;
215 break;
216 case CFGT_STR:
217 if (cfgp->dval.str == NULL) {
218 return;
219 }
220 if (cfgp->dyn_val && (cfgp->val.str != NULL)) {
221 free(cfgp->val.str);
222 cfgp->val.str = NULL;
223 }
224 diag_cfg_setstr(cfgp, cfgp->dval.str);
225 break;
226 case CFGT_BOOL:
227 cfgp->val.b = cfgp->dval.b;
228 break;
229 default:
230 break;
231 }
232}
233
234
235/** Refresh list of known ports
236 *
237 * Keep current port; update default.
238 * If no ports are found, changes nothing
239 */
240void tty_refresh(struct cfgi *cfgp) {
241
242 optarray_clear(cfgp);
243
244 cfgp->opt = diag_tty_getportlist(&cfgp->numopts);
245
246 if (cfgp->numopts == 0) {
247 /* no ports found : change nothing */
248 return;
249 }
250
251 /* Update default port */
252 cfgp->dyn_dval = 1;
253 if (diag_malloc(&cfgp->dval.str, strlen(cfgp->opt[0])+1)) {
254 optarray_clear(cfgp);
255 return;
256 }
257 strcpy(cfgp->dval.str, cfgp->opt[0]); //we just used strlen; strcpy is just as dangerous...
258 cfgp->dyn_opt = 1;
259
260 return;
261}
262
263//new TTY / serial port config item
264int diag_cfgn_tty(struct cfgi *cfgp) {
265 int rv = diag_cfgn_str(cfgp, tty_def, tty_descr, tty_sn);
266 if (rv != 0) {
267 return rv;
268 }
269
270 cfgp->refresh = &tty_refresh;
271 std_reset(cfgp);
272
273 return 0;
274}
275
276/** generic types **/
277
278//ordinary int param using caller's val, and def as default value for reset().
279//Doesn't fill descr and shortname
280int diag_cfgn_int(struct cfgi *cfgp, int val, int def) {
281 cfgp->dyn_val = 0; //caller-supplied
282 cfgp->dyn_dval = 0;
283 cfgp->type = CFGT_INT;
284 cfgp->numopts=0;
285 cfgp->dval.i = def;
286 cfgp->val.i = val;
287 cfgp->refresh = NULL;
288 cfgp->reset = &std_reset;
289 return 0;
290}
291
292//ordinary u8 param (copy of _int code) using caller's &val, and *dev as default value for reset().
293//Doesn't fill descr and shortname
294int diag_cfgn_u8(struct cfgi *cfgp, uint8_t val, uint8_t def) {
295 cfgp->dyn_val = 0; //managed by caller
296 cfgp->dyn_dval = 0;
297 cfgp->type = CFGT_U8;
298 cfgp->numopts=0;
299 cfgp->val.u8 = val;
300 cfgp->dval.u8 = def;
301 cfgp->refresh = NULL;
302 cfgp->reset = &std_reset;
303 return 0;
304}
305
306//ordinary bool (copy of _int code)
307int diag_cfgn_bool(struct cfgi *cfgp, bool val, bool def) {
308 cfgp->dyn_val = 0; //managed by caller
309 cfgp->dyn_dval = 0;
310 cfgp->type = CFGT_BOOL;
311 cfgp->numopts=0;
312 cfgp->val.b = val;
313 cfgp->dval.b = def;
314 cfgp->refresh = NULL;
315 cfgp->reset = &std_reset;
316 return 0;
317}
318
319//ordinary string, copies *def for its default value; sets descr and shortname ptrs
320int diag_cfgn_str(struct cfgi *cfgp, const char *def, const char *descr, const char *sn) {
321 char *val, *dval;
322 int rv;
323
324 assert(def && descr && sn);
325
326 cfgp->type = CFGT_STR;
327 rv = diag_malloc(&dval, strlen(def)+1);
328 if (rv != 0) {
329 return diag_ifwderr(rv);
330 }
331 rv = diag_malloc(&val, strlen(def)+1);
332 if (rv != 0) {
333 free(dval);
334 return diag_ifwderr(rv);
335 }
336
337 cfgp->dval.str = dval;
338 cfgp->dyn_dval = 1;
339 strcpy(dval, def); //danger
340
341 cfgp->val.str = val;
342 cfgp->dyn_val = 1;
343 strcpy(val, def); //danger
344
345 cfgp->descr = descr;
346 cfgp->shortname = sn;
347
348 cfgp->refresh = NULL;
349 cfgp->reset = &std_reset;
350 return 0;
351}
352