Instrument Neutral Distributed Interface INDI 2.2.5
indidevapi.c
Go to the documentation of this file.
1#include "indidevapi.h"
2#include "indicom.h"
3#include "locale_compat.h"
4#include "base64.h"
5#include "userio.h"
6#include "indiuserio.h"
7#include "indiutility.h"
8
9#include <string.h>
10#include <stdlib.h>
11#include <assert.h>
12#include <sys/stat.h>
13
14#ifdef _WIN32
15#include <direct.h>
16#include <Windows.h>
17#endif
18
19#define MAXRBUF 2048
20
23void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
24{
26}
27
28void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
29{
30 IUUserIONewText(userio_file(), fp, tvp);
31}
32
33void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
34{
36}
37
38void IUSaveConfigBLOB(FILE *fp, const IBLOBVectorProperty *bvp)
39{
40 IUUserIONewBLOB(userio_file(), fp, bvp);
41}
42
43/* save malloced copy of newtext in tp->text, reusing if not first time */
44void IUSaveText(IText *tp, const char *newtext)
45{
46 /* copy in fresh string */
47 size_t size = strlen(newtext) + 1;
48 tp->text = realloc(tp->text, size);
49 memcpy(tp->text, newtext, size);
50}
51
52int IUSaveBLOB(IBLOB *bp, int size, int blobsize, char *blob, char *format)
53{
54 bp->bloblen = blobsize;
55 bp->size = size;
56 bp->blob = blob;
57 indi_strlcpy(bp->format, format, MAXINDIFORMAT);
58 return 0;
59}
60
64{
65 char configFileName[MAXRBUF];
66 char configDir[MAXRBUF];
67 char errmsg[MAXRBUF];
68 struct stat st;
69 FILE *fp = NULL;
70
71 snprintf(configDir, MAXRBUF-1, "%s/.indi/", getenv("HOME"));
72
73 if (getenv("INDICONFIG"))
74 snprintf(configFileName, MAXRBUF, "%s", getenv("INDICONFIG"));
75 else
76 snprintf(configFileName, MAXRBUF-1, "%s%s_config.xml", configDir, device);
77
78
79 if (stat(configDir, &st) != 0)
80 {
81#ifdef _WIN32
82 if (mkdir(configDir) != 0)
83#else
84 if (mkdir(configDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0)
85#endif
86 return NULL;
87 }
88
89 int statResult = stat(configFileName, &st);
90
91#ifdef _WIN32
92 (void)statResult;
93 BOOL isAdmin = FALSE;
94 SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
95 PSID AdministratorsGroup;
96 if (AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup))
97 {
98 if (CheckTokenMembership(NULL, AdministratorsGroup, &isAdmin) == FALSE)
99 isAdmin = FALSE;
100 FreeSid(AdministratorsGroup);
101 }
102 if ((st.st_uid == 0 && st.st_mode & S_IFDIR) || (st.st_gid == 0 && isAdmin == TRUE))
103 return NULL;
104#else
105 /* If file is owned by root and current user is NOT root then abort. Only the owner matters: on macOS,
106 * new files take the group of their directory, so files in e.g. /tmp belong to group wheel (0). */
107 if (statResult == 0 && st.st_uid == 0 && getuid() != 0)
108 return NULL;
109#endif
110
111 fp = fopen(configFileName, "r");
112 if (fp == NULL)
113 return NULL;
114
115 LilXML *lp = newLilXML();
116
117 XMLEle *root = readXMLFile(fp, lp, errmsg);
118
119 delLilXML(lp);
120 fclose(fp);
121
122 return root;
123}
127{
128 char errmsg[1024];
129 char *rdev, *rname;
130 int foundCounter = 0;
131 XMLEle *root = configRootFP(nvp->device);
132 if (root == NULL)
133 return -1;
134
135 XMLEle *ep = NULL;
136
137 for (ep = nextXMLEle(root, 1); ep != NULL; ep = nextXMLEle(root, 0))
138 {
139 /* pull out device and name */
140 if (crackDN(ep, &rdev, &rname, errmsg) < 0)
141 {
142 delXMLEle(root);
143 return -1;
144 }
145
146 // It doesn't belong to our device??
147 if (strcmp(nvp->device, rdev))
148 continue;
149
150 if (!strcmp(nvp->name, rname))
151 {
152 XMLEle *element = NULL;
153 for (element = nextXMLEle(ep, 1); element != NULL; element = nextXMLEle(ep, 0))
154 {
155 INumber *member = IUFindNumber(nvp, findXMLAttValu(element, "name"));
156 if (member)
157 {
158 member->value = atof(pcdataXMLEle(element));
159 foundCounter++;
160 }
161 }
162 break;
163 }
164 }
165
166 delXMLEle(root);
167 return foundCounter;
168}
169
171{
172 char errmsg[1024];
173 char *rdev, *rname;
174 int foundCounter = 0;
175 XMLEle *root = configRootFP(tvp->device);
176 if (root == NULL)
177 return -1;
178
179 XMLEle *ep = NULL;
180
181 for (ep = nextXMLEle(root, 1); ep != NULL; ep = nextXMLEle(root, 0))
182 {
183 /* pull out device and name */
184 if (crackDN(ep, &rdev, &rname, errmsg) < 0)
185 {
186 delXMLEle(root);
187 return -1;
188 }
189
190 // It doesn't belong to our device??
191 if (strcmp(tvp->device, rdev))
192 continue;
193
194 if (!strcmp(tvp->name, rname))
195 {
196 XMLEle *element = NULL;
197 for (element = nextXMLEle(ep, 1); element != NULL; element = nextXMLEle(ep, 0))
198 {
199 IText *member = IUFindText(tvp, findXMLAttValu(element, "name"));
200 if (member)
201 {
202 IUSaveText(member, pcdataXMLEle(element));
203 foundCounter++;
204 }
205 }
206 break;
207 }
208 }
209
210 delXMLEle(root);
211 return foundCounter;
212}
213
215{
216 char errmsg[1024];
217 char *rdev, *rname;
218 int foundCounter = 0;
219 XMLEle *root = configRootFP(svp->device);
220 if (root == NULL)
221 return -1;
222
223 XMLEle *ep = NULL;
224
225 for (ep = nextXMLEle(root, 1); ep != NULL; ep = nextXMLEle(root, 0))
226 {
227 /* pull out device and name */
228 if (crackDN(ep, &rdev, &rname, errmsg) < 0)
229 {
230 delXMLEle(root);
231 return -1;
232 }
233
234 // It doesn't belong to our device??
235 if (strcmp(svp->device, rdev))
236 continue;
237
238 if (!strcmp(svp->name, rname))
239 {
240 XMLEle *element = NULL;
241 for (element = nextXMLEle(ep, 1); element != NULL; element = nextXMLEle(ep, 0))
242 {
243 ISwitch *member = IUFindSwitch(svp, findXMLAttValu(element, "name"));
244 if (member)
245 {
246 ISState state;
247 if (crackISState(pcdataXMLEle(element), &state) == 0)
248 {
249 member->s = state;
250 foundCounter++;
251 }
252 }
253 }
254 break;
255 }
256 }
257
258 delXMLEle(root);
259 return foundCounter;
260}
261
264/* find a member of an IText vector, else NULL */
265IText *IUFindText(const ITextVectorProperty *tvp, const char *name)
266{
267 for (int i = 0; i < tvp->ntp; i++)
268 if (strcmp(tvp->tp[i].name, name) == 0)
269 return (&tvp->tp[i]);
270 fprintf(stderr, "No IText '%s' in %s.%s\n", name, tvp->device, tvp->name);
271 return (NULL);
272}
273
274/* find a member of an INumber vector, else NULL */
275INumber *IUFindNumber(const INumberVectorProperty *nvp, const char *name)
276{
277 for (int i = 0; i < nvp->nnp; i++)
278 if (strcmp(nvp->np[i].name, name) == 0)
279 return (&nvp->np[i]);
280 fprintf(stderr, "No INumber '%s' in %s.%s\n", name, nvp->device, nvp->name);
281 return (NULL);
282}
283
284/* find a member of an ISwitch vector, else NULL */
285ISwitch *IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
286{
287 for (int i = 0; i < svp->nsp; i++)
288 if (strcmp(svp->sp[i].name, name) == 0)
289 return (&svp->sp[i]);
290 fprintf(stderr, "No ISwitch '%s' in %s.%s\n", name, svp->device, svp->name);
291 return (NULL);
292}
293
294/* find a member of an ILight vector, else NULL */
295ILight *IUFindLight(const ILightVectorProperty *lvp, const char *name)
296{
297 for (int i = 0; i < lvp->nlp; i++)
298 if (strcmp(lvp->lp[i].name, name) == 0)
299 return (&lvp->lp[i]);
300 fprintf(stderr, "No ILight '%s' in %s.%s\n", name, lvp->device, lvp->name);
301 return (NULL);
302}
303
304/* find a member of an IBLOB vector, else NULL */
305IBLOB *IUFindBLOB(const IBLOBVectorProperty *bvp, const char *name)
306{
307 for (int i = 0; i < bvp->nbp; i++)
308 if (strcmp(bvp->bp[i].name, name) == 0)
309 return (&bvp->bp[i]);
310 fprintf(stderr, "No IBLOB '%s' in %s.%s\n", name, bvp->device, bvp->name);
311 return (NULL);
312}
313
314/* find an ON member of an ISwitch vector, else NULL.
315 * N.B. user must make sense of result with ISRule in mind.
316 */
318{
319 for (int i = 0; i < svp->nsp; i++)
320 if (svp->sp[i].s == ISS_ON)
321 return (&svp->sp[i]);
322 /*fprintf(stderr, "No ISwitch On in %s.%s\n", svp->device, svp->name);*/
323 return (NULL);
324}
325
326int IUFindIndex(const char *needle, char **hay, unsigned int n)
327{
328 for (int i = 0; i < (int)n; i++)
329 {
330 if (!strcmp(hay[i], needle))
331 return i;
332 }
333 return -1;
334}
335
336/* Find index of the ON member of an ISwitchVectorProperty */
338{
339 for (int i = 0; i < svp->nsp; i++)
340 if (svp->sp[i].s == ISS_ON)
341 return i;
342 return -1;
343}
344
345/* Find index of the ON member of ISState array */
346int IUFindOnStateIndex(ISState *states, int n)
347{
348 for (int i = 0; i < n; i++)
349 if (states[i] == ISS_ON)
350 return i;
351 return -1;
352}
353
354/* Find name the ON member in the given states and names */
355const char *IUFindOnSwitchName(ISState *states, char *names[], int n)
356{
357 for (int i = 0; i < n; i++)
358 if (states[i] == ISS_ON)
359 return names[i];
360 return NULL;
361}
362
365/* Set all switches to off */
367{
368 for (int i = 0; i < svp->nsp; i++)
369 svp->sp[i].s = ISS_OFF;
370}
371
376void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
377{
378 indi_strlcpy(sp->name, name, sizeof(sp->name));
379
380 indi_strlcpy(sp->label, label[0] ? label : name, sizeof(sp->label));
381
382 sp->s = s;
383 sp->svp = NULL;
384 sp->aux = NULL;
385}
386
387void IUFillLight(ILight *lp, const char *name, const char *label, IPState s)
388{
389 indi_strlcpy(lp->name, name, sizeof(lp->name));
390
391 indi_strlcpy(lp->label, label[0] ? label : name, sizeof(lp->label));
392
393 lp->s = s;
394 lp->lvp = NULL;
395 lp->aux = NULL;
396}
397
398void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max,
399 double step, double value)
400{
401 indi_strlcpy(np->name, name, sizeof(np->name));
402
403 indi_strlcpy(np->label, label[0] ? label : name, sizeof(np->label));
404
405 indi_strlcpy(np->format, format, sizeof(np->format));
406
407 np->min = min;
408 np->max = max;
409 np->step = step;
410 np->value = value;
411 np->nvp = NULL;
412 np->aux0 = NULL;
413 np->aux1 = NULL;
414}
415
416void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
417{
418 indi_strlcpy(tp->name, name, sizeof(tp->name));
419
420 indi_strlcpy(tp->label, label[0] ? label : name, sizeof(tp->label));
421
422 if (tp->text && tp->text[0])
423 free(tp->text);
424 tp->text = NULL;
425
426 tp->tvp = NULL;
427 tp->aux0 = NULL;
428 tp->aux1 = NULL;
429
430 if (initialText && initialText[0])
431 IUSaveText(tp, initialText);
432}
433
434void IUFillBLOB(IBLOB *bp, const char *name, const char *label, const char *format)
435{
436 memset(bp, 0, sizeof(IBLOB));
437
438 indi_strlcpy(bp->name, name, sizeof(bp->name));
439
440 indi_strlcpy(bp->label, label[0] ? label : name, sizeof(bp->label));
441
442 indi_strlcpy(bp->format, format, sizeof(bp->format));
443
444 bp->blob = 0;
445 bp->bloblen = 0;
446 bp->size = 0;
447 bp->bvp = 0;
448 bp->aux0 = 0;
449 bp->aux1 = 0;
450 bp->aux2 = 0;
451}
452
453void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name,
454 const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
455{
456 indi_strlcpy(svp->device, dev, sizeof(svp->device));
457
458 indi_strlcpy(svp->name, name, sizeof(svp->name));
459
460 indi_strlcpy(svp->label, label[0] ? label : name, sizeof(svp->label));
461
462 indi_strlcpy(svp->group, group, sizeof(svp->group));
463 svp->timestamp[0] = '\0';
464
465 svp->p = p;
466 svp->r = r;
467 svp->timeout = timeout;
468 svp->s = s;
469 svp->sp = sp;
470 svp->nsp = nsp;
471}
472
473void IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char *dev, const char *name,
474 const char *label, const char *group, IPState s)
475{
476 indi_strlcpy(lvp->device, dev, sizeof(lvp->device));
477
478 indi_strlcpy(lvp->name, name, sizeof(lvp->name));
479
480 indi_strlcpy(lvp->label, label[0] ? label : name, sizeof(lvp->label));
481
482 indi_strlcpy(lvp->group, group, sizeof(lvp->group));
483 lvp->timestamp[0] = '\0';
484
485 lvp->s = s;
486 lvp->lp = lp;
487 lvp->nlp = nlp;
488}
489
490void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name,
491 const char *label, const char *group, IPerm p, double timeout, IPState s)
492{
493 indi_strlcpy(nvp->device, dev, sizeof(nvp->device));
494
495 indi_strlcpy(nvp->name, name, sizeof(nvp->name));
496
497 indi_strlcpy(nvp->label, label[0] ? label : name, sizeof(nvp->label));
498
499 indi_strlcpy(nvp->group, group, sizeof(nvp->group));
500 nvp->timestamp[0] = '\0';
501
502 nvp->p = p;
503 nvp->timeout = timeout;
504 nvp->s = s;
505 nvp->np = np;
506 nvp->nnp = nnp;
507}
508
509void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name,
510 const char *label, const char *group, IPerm p, double timeout, IPState s)
511{
512 indi_strlcpy(tvp->device, dev, sizeof(tvp->device));
513
514 indi_strlcpy(tvp->name, name, sizeof(tvp->name));
515
516 indi_strlcpy(tvp->label, label[0] ? label : name, sizeof(tvp->label));
517
518 indi_strlcpy(tvp->group, group, sizeof(tvp->group));
519 tvp->timestamp[0] = '\0';
520
521 tvp->p = p;
522 tvp->timeout = timeout;
523 tvp->s = s;
524 tvp->tp = tp;
525 tvp->ntp = ntp;
526}
527
528void IUFillBLOBVector(IBLOBVectorProperty *bvp, IBLOB *bp, int nbp, const char *dev, const char *name,
529 const char *label, const char *group, IPerm p, double timeout, IPState s)
530{
531 memset(bvp, 0, sizeof(IBLOBVectorProperty));
532 indi_strlcpy(bvp->device, dev, sizeof(bvp->device));
533
534 indi_strlcpy(bvp->name, name, sizeof(bvp->name));
535
536 indi_strlcpy(bvp->label, label[0] ? label : name, sizeof(bvp->label));
537
538 indi_strlcpy(bvp->group, group, sizeof(bvp->group));
539 bvp->timestamp[0] = '\0';
540
541 bvp->p = p;
542 bvp->timeout = timeout;
543 bvp->s = s;
544 bvp->bp = bp;
545 bvp->nbp = nbp;
546}
547
550/* crack the snooped driver setNumberVector or defNumberVector message into
551 * the given INumberVectorProperty.
552 * return 0 if type, device and name match and all members are present, else
553 * return -1
554 */
556{
557 char *dev, *name;
558 XMLEle *ep;
559
560 /* check and crack type, device, name and state */
561 if (strcmp(tagXMLEle(root) + 3, "NumberVector") || crackDN(root, &dev, &name, NULL) < 0)
562 return (-1);
563 if (strcmp(dev, nvp->device) || strcmp(name, nvp->name))
564 return (-1); /* not this property */
565 (void)crackIPState(findXMLAttValu(root, "state"), &nvp->s);
566
567 /* match each INumber with a oneNumber */
568 locale_char_t *orig = indi_locale_C_numeric_push();
569 for (int i = 0; i < nvp->nnp; i++)
570 {
571 for (ep = nextXMLEle(root, 1); ep; ep = nextXMLEle(root, 0))
572 {
573 if (!strcmp(tagXMLEle(ep) + 3, "Number") && !strcmp(nvp->np[i].name, findXMLAttValu(ep, "name")))
574 {
575 if (f_scansexa(pcdataXMLEle(ep), &nvp->np[i].value) < 0)
576 {
577 indi_locale_C_numeric_pop(orig);
578 return (-1); /* bad number format */
579 }
580 break;
581 }
582 }
583 if (!ep)
584 {
585 indi_locale_C_numeric_pop(orig);
586 return (-1); /* element not found */
587 }
588 }
589 indi_locale_C_numeric_pop(orig);
590
591 /* ok */
592 return (0);
593}
594
595/* crack the snooped driver setTextVector or defTextVector message into
596 * the given ITextVectorProperty.
597 * return 0 if type, device and name match and all members are present, else
598 * return -1
599 */
601{
602 char *dev, *name;
603 XMLEle *ep;
604
605 /* check and crack type, device, name and state */
606 if (strcmp(tagXMLEle(root) + 3, "TextVector") || crackDN(root, &dev, &name, NULL) < 0)
607 return (-1);
608 if (strcmp(dev, tvp->device) || strcmp(name, tvp->name))
609 return (-1); /* not this property */
610 (void)crackIPState(findXMLAttValu(root, "state"), &tvp->s);
611
612 /* match each IText with a oneText */
613 for (int i = 0; i < tvp->ntp; i++)
614 {
615 for (ep = nextXMLEle(root, 1); ep; ep = nextXMLEle(root, 0))
616 {
617 if (!strcmp(tagXMLEle(ep) + 3, "Text") && !strcmp(tvp->tp[i].name, findXMLAttValu(ep, "name")))
618 {
619 IUSaveText(&tvp->tp[i], pcdataXMLEle(ep));
620 break;
621 }
622 }
623 if (!ep)
624 return (-1); /* element not found */
625 }
626
627 /* ok */
628 return (0);
629}
630
631/* crack the snooped driver setLightVector or defLightVector message into
632 * the given ILightVectorProperty. it is not necessary that all ILight names
633 * be found.
634 * return 0 if type, device and name match, else return -1.
635 */
637{
638 char *dev, *name;
639 XMLEle *ep;
640
641 /* check and crack type, device, name and state */
642 if (strcmp(tagXMLEle(root) + 3, "LightVector") || crackDN(root, &dev, &name, NULL) < 0)
643 return (-1);
644 if (strcmp(dev, lvp->device) || strcmp(name, lvp->name))
645 return (-1); /* not this property */
646
647 (void)crackIPState(findXMLAttValu(root, "state"), &lvp->s);
648
649 /* match each oneLight with one ILight */
650 for (ep = nextXMLEle(root, 1); ep; ep = nextXMLEle(root, 0))
651 {
652 if (!strcmp(tagXMLEle(ep) + 3, "Light"))
653 {
654 const char *name = findXMLAttValu(ep, "name");
655 for (int i = 0; i < lvp->nlp; i++)
656 {
657 if (!strcmp(lvp->lp[i].name, name))
658 {
659 if (crackIPState(pcdataXMLEle(ep), &lvp->lp[i].s) < 0)
660 {
661 return (-1); /* unrecognized state */
662 }
663 break;
664 }
665 }
666 }
667 }
668
669 /* ok */
670 return (0);
671}
672
673/* crack the snooped driver setSwitchVector or defSwitchVector message into the
674 * given ISwitchVectorProperty. it is not necessary that all ISwitch names be
675 * found.
676 * return 0 if type, device and name match, else return -1.
677 */
679{
680 char *dev, *name;
681 XMLEle *ep;
682
683 /* check and crack type, device, name and state */
684 if (strcmp(tagXMLEle(root) + 3, "SwitchVector") || crackDN(root, &dev, &name, NULL) < 0)
685 return (-1);
686 if (strcmp(dev, svp->device) || strcmp(name, svp->name))
687 return (-1); /* not this property */
688 (void)crackIPState(findXMLAttValu(root, "state"), &svp->s);
689
690 /* match each oneSwitch with one ISwitch */
691 for (ep = nextXMLEle(root, 1); ep; ep = nextXMLEle(root, 0))
692 {
693 if (!strcmp(tagXMLEle(ep) + 3, "Switch"))
694 {
695 const char *name = findXMLAttValu(ep, "name");
696 for (int i = 0; i < svp->nsp; i++)
697 {
698 if (!strcmp(svp->sp[i].name, name))
699 {
700 if (crackISState(pcdataXMLEle(ep), &svp->sp[i].s) < 0)
701 {
702 return (-1); /* unrecognized state */
703 }
704 break;
705 }
706 }
707 }
708 }
709
710 /* ok */
711 return (0);
712}
713
714/* crack the snooped driver setBLOBVector message into the given
715 * IBLOBVectorProperty. it is not necessary that all IBLOB names be found.
716 * return 0 if type, device and name match, else return -1.
717 * N.B. we assume any existing blob in bvp has been malloced, which we free
718 * and replace with a newly malloced blob if found.
719 */
721{
722 char *dev, *name;
723 XMLEle *ep;
724
725 /* check and crack type, device, name and state */
726 if (strcmp(tagXMLEle(root), "setBLOBVector") || crackDN(root, &dev, &name, NULL) < 0)
727 return (-1);
728
729 if (strcmp(dev, bvp->device) || strcmp(name, bvp->name))
730 return (-1); /* not this property */
731
732 crackIPState(findXMLAttValu(root, "state"), &bvp->s);
733
734 for (ep = nextXMLEle(root, 1); ep; ep = nextXMLEle(root, 0))
735 {
736 if (strcmp(tagXMLEle(ep), "oneBLOB") == 0)
737 {
738 XMLAtt *na = findXMLAtt(ep, "name");
739 if (na == NULL)
740 return (-1);
741
742 IBLOB *bp = IUFindBLOB(bvp, valuXMLAtt(na));
743
744 if (bp == NULL)
745 return (-1);
746
747 XMLAtt *fa = findXMLAtt(ep, "format");
748 XMLAtt *sa = findXMLAtt(ep, "size");
749 if (fa && sa)
750 {
751 int base64datalen = pcdatalenXMLEle(ep);
752 assert_mem(bp->blob = realloc(bp->blob, 3 * base64datalen / 4));
753 bp->bloblen = from64tobits_fast(bp->blob, pcdataXMLEle(ep), base64datalen);
754 indi_strlcpy(bp->format, valuXMLAtt(fa), MAXINDIFORMAT);
755 bp->size = atoi(valuXMLAtt(sa));
756 }
757 }
758 }
759
760 /* ok */
761 return (0);
762}
763
766/* Functions are implemented in defaultdevice.cpp */
767
770int crackDN(XMLEle *root, char **dev, char **name, char msg[])
771{
772 XMLAtt *ap;
773
774 ap = findXMLAtt(root, "device");
775 if (!ap)
776 {
777 snprintf(msg, MAXRBUF, "%s requires 'device' attribute", tagXMLEle(root));
778 return (-1);
779 }
780 *dev = valuXMLAtt(ap);
781
782 ap = findXMLAtt(root, "name");
783 if (!ap)
784 {
785 snprintf(msg, MAXRBUF, "%s requires 'name' attribute", tagXMLEle(root));
786 return (-1);
787 }
788 *name = valuXMLAtt(ap);
789
790 return (0);
791}
792
793int crackIPState(const char *str, IPState *ip)
794{
795 if (!strcmp(str, "Idle"))
796 *ip = IPS_IDLE;
797 else if (!strncmp(str, "Ok", 2))
798 *ip = IPS_OK;
799 else if (!strcmp(str, "Busy"))
800 *ip = IPS_BUSY;
801 else if (!strcmp(str, "Alert"))
802 *ip = IPS_ALERT;
803 else
804 return (-1);
805 return (0);
806}
807
808int crackISState(const char *str, ISState *ip)
809{
810 if (!strncmp(str, "On", 2))
811 *ip = ISS_ON;
812 else if (!strcmp(str, "Off"))
813 *ip = ISS_OFF;
814 else
815 return (-1);
816 return (0);
817}
818
819int crackIPerm(const char *str, IPerm *ip)
820{
821 if (!strncmp(str, "rw", 2))
822 *ip = IP_RW;
823 else if (!strncmp(str, "ro", 2))
824 *ip = IP_RO;
825 else if (!strncmp(str, "wo", 2))
826 *ip = IP_WO;
827 else
828 return (-1);
829 return (0);
830}
831
832int crackISRule(const char *str, ISRule *ip)
833{
834 if (!strcmp(str, "OneOfMany"))
835 *ip = ISR_1OFMANY;
836 else if (!strcmp(str, "AtMostOne"))
837 *ip = ISR_ATMOST1;
838 else if (!strcmp(str, "AnyOfMany"))
839 *ip = ISR_NOFMANY;
840 else
841 return (-1);
842 return (0);
843}
844
845const char *pstateStr(IPState s)
846{
847 switch (s)
848 {
849 case IPS_IDLE:
850 return "Idle";
851 case IPS_OK:
852 return "Ok";
853 case IPS_BUSY:
854 return "Busy";
855 case IPS_ALERT:
856 return "Alert";
857 default:
858 fprintf(stderr, "Impossible IPState %d\n", s);
859 return NULL;
860 }
861}
862
863const char *sstateStr(ISState s)
864{
865 switch (s)
866 {
867 case ISS_ON:
868 return "On";
869 case ISS_OFF:
870 return "Off";
871 default:
872 fprintf(stderr, "Impossible ISState %d\n", s);
873 return NULL;
874 }
875}
876
877const char *ruleStr(ISRule r)
878{
879 switch (r)
880 {
881 case ISR_1OFMANY:
882 return "OneOfMany";
883 case ISR_ATMOST1:
884 return "AtMostOne";
885 case ISR_NOFMANY:
886 return "AnyOfMany";
887 default:
888 fprintf(stderr, "Impossible ISRule %d\n", r);
889 return NULL;
890 }
891}
892
893const char *permStr(IPerm p)
894{
895 switch (p)
896 {
897 case IP_RO:
898 return "ro";
899 case IP_WO:
900 return "wo";
901 case IP_RW:
902 return "rw";
903 default:
904 fprintf(stderr, "Impossible IPerm %d\n", p);
905 return NULL;
906 }
907}
908
909void xmlv1()
910{
911 userio_xmlv1(userio_file(), stdout);
912}
hid_device * device
int from64tobits_fast(char *out, const char *in, int inlen)
Definition base64.c:122
double max(void)
#define min(a, b)
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
#define MAXINDIFORMAT
Definition indiapi.h:193
#define assert_mem(p)
Bails out if memory pointer is 0. Prints file and function.
Definition indiapi.h:503
IPerm
Permission hint, with respect to client.
Definition indiapi.h:181
@ IP_RW
Definition indiapi.h:184
@ IP_RO
Definition indiapi.h:182
@ IP_WO
Definition indiapi.h:183
IPState
Property state.
Definition indiapi.h:158
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
ISRule
Switch vector rule hint.
Definition indiapi.h:170
@ ISR_1OFMANY
Definition indiapi.h:171
@ ISR_NOFMANY
Definition indiapi.h:173
@ ISR_ATMOST1
Definition indiapi.h:172
int f_scansexa(const char *str0, double *dp)
convert sexagesimal string str AxBxC to double. x can be anything non-numeric. Any missing A,...
Definition indicom.c:194
Implementations for common driver routines.
int IUSnoopSwitch(XMLEle *root, ISwitchVectorProperty *svp)
Update a snooped switch vector property from the given XML root element.
Definition indidevapi.c:678
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition indidevapi.c:33
void IUFillLight(ILight *lp, const char *name, const char *label, IPState s)
Assign attributes for a light property. The light's auxiliary elements will be set to NULL.
Definition indidevapi.c:387
int IULoadConfigSwitch(const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition indidevapi.c:214
IText * IUFindText(const ITextVectorProperty *tvp, const char *name)
Find an IText member in a vector text property.
Definition indidevapi.c:265
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:490
const char * ruleStr(ISRule r)
Definition indidevapi.c:877
ILight * IUFindLight(const ILightVectorProperty *lvp, const char *name)
Find an ILight member in a vector Light property.
Definition indidevapi.c:295
int IULoadConfigNumber(const INumberVectorProperty *nvp)
Load a number vector property value from the configuration file.
Definition indidevapi.c:126
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition indidevapi.c:337
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition indidevapi.c:366
void IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char *dev, const char *name, const char *label, const char *group, IPState s)
Assign attributes for a light vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:473
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:509
INumber * IUFindNumber(const INumberVectorProperty *nvp, const char *name)
Find an INumber member in a number text property.
Definition indidevapi.c:275
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition indidevapi.c:44
int IUFindIndex(const char *needle, char **hay, unsigned int n)
Returns the index of the string in a string array.
Definition indidevapi.c:326
int IUSnoopBLOB(XMLEle *root, IBLOBVectorProperty *bvp)
Update a snooped BLOB vector property from the given XML root element.
Definition indidevapi.c:720
int crackDN(XMLEle *root, char **dev, char **name, char msg[])
Extract dev and name attributes from an XML element.
Definition indidevapi.c:770
int IUSnoopLight(XMLEle *root, ILightVectorProperty *lvp)
Update a snooped light vector property from the given XML root element.
Definition indidevapi.c:636
ISwitch * IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
Find an ISwitch member in a vector switch property.
Definition indidevapi.c:285
#define MAXRBUF
Definition indidevapi.c:19
int IUSaveBLOB(IBLOB *bp, int size, int blobsize, char *blob, char *format)
Function to save blob metadata in the corresponding blob.
Definition indidevapi.c:52
void IUSaveConfigBLOB(FILE *fp, const IBLOBVectorProperty *bvp)
Add a BLOB vector property value to the configuration file.
Definition indidevapi.c:38
int IUSnoopText(XMLEle *root, ITextVectorProperty *tvp)
Update a snooped text vector property from the given XML root element.
Definition indidevapi.c:600
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition indidevapi.c:23
int IUSnoopNumber(XMLEle *root, INumberVectorProperty *nvp)
Update a snooped number vector property from the given XML root element.
Definition indidevapi.c:555
XMLEle * configRootFP(const char *device)
Definition indidevapi.c:63
const char * sstateStr(ISState s)
Definition indidevapi.c:863
const char * permStr(IPerm p)
Definition indidevapi.c:893
IBLOB * IUFindBLOB(const IBLOBVectorProperty *bvp, const char *name)
Find an IBLOB member in a vector BLOB property.
Definition indidevapi.c:305
void xmlv1()
print the boilerplate comment introducing xml
Definition indidevapi.c:909
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition indidevapi.c:376
ISwitch * IUFindOnSwitch(const ISwitchVectorProperty *svp)
Returns the first ON switch it finds in the vector switch property.
Definition indidevapi.c:317
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
Definition indidevapi.c:416
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
Definition indidevapi.c:398
int crackIPerm(const char *str, IPerm *ip)
Extract property permission state (RW, RO, WO) from the supplied string.
Definition indidevapi.c:819
void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
Definition indidevapi.c:28
int crackIPState(const char *str, IPState *ip)
Extract property state (Idle, OK, Busy, Alert) from the supplied string.
Definition indidevapi.c:793
const char * pstateStr(IPState s)
Definition indidevapi.c:845
int IULoadConfigText(const ITextVectorProperty *tvp)
Load a text vector property value from the configuration file.
Definition indidevapi.c:170
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:453
void IUFillBLOBVector(IBLOBVectorProperty *bvp, IBLOB *bp, int nbp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a BLOB vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:528
void IUFillBLOB(IBLOB *bp, const char *name, const char *label, const char *format)
Assign attributes for a BLOB property. The BLOB's data and auxiliary elements will be set to NULL.
Definition indidevapi.c:434
int crackISRule(const char *str, ISRule *ip)
Extract switch rule (OneOfMany, OnlyOne..etc) from the supplied string.
Definition indidevapi.c:832
const char * IUFindOnSwitchName(ISState *states, char *names[], int n)
Returns the name of the first ON switch it finds in the supplied arguments.
Definition indidevapi.c:355
int crackISState(const char *str, ISState *ip)
Extract switch state (On or Off) from the supplied string.
Definition indidevapi.c:808
int IUFindOnStateIndex(ISState *states, int n)
Returns the index of first ON switch it finds in the ISState array.
Definition indidevapi.c:346
Interface to the reference INDI C API device implementation on the Device Driver side.
void IUUserIONewBLOB(const userio *io, void *user, const IBLOBVectorProperty *bvp)
Definition indiuserio.c:251
void IUUserIONewSwitchFull(const userio *io, void *user, const ISwitchVectorProperty *svp)
Definition indiuserio.c:229
void IUUserIONewText(const userio *io, void *user, const ITextVectorProperty *tvp)
Definition indiuserio.c:216
void IUUserIONewNumber(const userio *io, void *user, const INumberVectorProperty *nvp)
Definition indiuserio.c:199
const char * findXMLAttValu(XMLEle *ep, const char *name)
Find an XML element's attribute value.
Definition lilxml.cpp:644
XMLEle * nextXMLEle(XMLEle *ep, int init)
Iterate an XML element for a list of nesetd XML elements.
Definition lilxml.cpp:555
XMLAtt * findXMLAtt(XMLEle *ep, const char *name)
Find an XML attribute within an XML element.
Definition lilxml.cpp:524
LilXML * newLilXML()
Create a new lilxml parser.
Definition lilxml.cpp:150
char * tagXMLEle(XMLEle *ep)
Return the tag of an XML element.
Definition lilxml.cpp:600
char * valuXMLAtt(XMLAtt *ap)
Return the value of an XML attribute.
Definition lilxml.cpp:624
void delXMLEle(XMLEle *ep)
delXMLEle Delete XML element.
Definition lilxml.cpp:167
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
Definition lilxml.cpp:606
void delLilXML(LilXML *lp)
Delete a lilxml parser.
Definition lilxml.cpp:159
XMLEle * readXMLFile(FILE *fp, LilXML *lp, char ynot[])
Handy wrapper to read one xml file.
Definition lilxml.cpp:653
int pcdatalenXMLEle(XMLEle *ep)
Return the number of characters in pcdata in an XML element.
Definition lilxml.cpp:612
char locale_char_t
One Blob (Binary Large Object) descriptor.
One light descriptor.
One number descriptor.
One switch descriptor.
One text descriptor.
BLOB (Binary Large Object) vector property descriptor.
Definition indiapi.h:469
char label[MAXINDILABEL]
Definition indiapi.h:475
char group[MAXINDIGROUP]
Definition indiapi.h:477
char timestamp[MAXINDITSTAMP]
Definition indiapi.h:489
char name[MAXINDINAME]
Definition indiapi.h:473
char device[MAXINDIDEVICE]
Definition indiapi.h:471
char name[MAXINDINAME]
Definition indiapi.h:443
Light vector property descriptor.
Definition indiapi.h:415
char label[MAXINDILABEL]
Definition indiapi.h:421
char name[MAXINDINAME]
Definition indiapi.h:419
char device[MAXINDIDEVICE]
Definition indiapi.h:417
char group[MAXINDIGROUP]
Definition indiapi.h:423
char timestamp[MAXINDITSTAMP]
Definition indiapi.h:431
char name[MAXINDINAME]
Definition indiapi.h:399
IPState s
Definition indiapi.h:403
Number vector property descriptor.
Definition indiapi.h:317
char group[MAXINDIGROUP]
Definition indiapi.h:325
char device[MAXINDIDEVICE]
Definition indiapi.h:319
char name[MAXINDINAME]
Definition indiapi.h:321
char label[MAXINDILABEL]
Definition indiapi.h:323
char timestamp[MAXINDITSTAMP]
Definition indiapi.h:337
char name[MAXINDINAME]
Definition indiapi.h:276
double value
Definition indiapi.h:288
Switch vector property descriptor.
Definition indiapi.h:365
char device[MAXINDIDEVICE]
Definition indiapi.h:367
char name[MAXINDINAME]
Definition indiapi.h:369
char label[MAXINDILABEL]
Definition indiapi.h:371
char group[MAXINDIGROUP]
Definition indiapi.h:373
char timestamp[MAXINDITSTAMP]
Definition indiapi.h:387
ISState s
Definition indiapi.h:353
char name[MAXINDINAME]
Definition indiapi.h:349
Text vector property descriptor.
Definition indiapi.h:244
char label[MAXINDILABEL]
Definition indiapi.h:250
char device[MAXINDIDEVICE]
Definition indiapi.h:246
char timestamp[MAXINDITSTAMP]
Definition indiapi.h:264
char name[MAXINDINAME]
Definition indiapi.h:248
char group[MAXINDIGROUP]
Definition indiapi.h:252
char name[MAXINDINAME]
Definition indiapi.h:226
#define TRUE
Definition stvdriver.c:54
#define FALSE
Definition stvdriver.c:53
void userio_xmlv1(const userio *io, void *user)
Definition userio.c:104
const struct userio * userio_file()
Definition userio.c:39