source: BAORadio/libindi/v1.0.1/libs/indicom.c@ 680

Last change on this file since 680 was 501, checked in by frichard, 15 years ago

-BAOControl : petite interface permettant de contrôler les antennes via le pilote indi_BAO
-Le pilote indi_BAO utilise désormais libindi v 0.7

File size: 30.1 KB
Line 
1/*
2 INDI LIB
3 Common routines used by all drivers
4 Copyright (C) 2003 by Jason Harris (jharris@30doradus.org)
5 Elwood C. Downey
6
7 This is the C version of the astronomical library in KStars
8 modified by Jasem Mutlaq (mutlaqja@ikarustech.com)
9
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2.1 of the License, or (at your option) any later version.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
24*/
25
26#include <stdlib.h>
27#include <math.h>
28#include <stdio.h>
29#include <string.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <errno.h>
33#include <stdarg.h>
34#include <sys/param.h>
35
36//#include <config.h>
37
38#ifdef HAVE_NOVA_H
39#include <libnova.h>
40#endif
41
42#include "indicom.h"
43#ifdef _WIN32
44#undef CX
45#undef CY
46#endif
47
48#ifndef _WIN32
49#include <termios.h>
50#define PARITY_NONE 0
51#define PARITY_EVEN 1
52#define PARITY_ODD 2
53#endif
54
55#define MAXRBUF 2048
56
57#include "indidevapi.h"
58
59void getSexComponents(double value, int *d, int *m, int *s);
60
61
62int extractISOTime(char *timestr, struct ln_date *iso_date)
63{
64 #ifdef HAVE_NOVA_H
65 struct tm utm;
66
67 if (strptime(timestr, "%Y/%m/%dT%H:%M:%S", &utm))
68 {
69 ln_get_date_from_tm(&utm, iso_date);
70 return (0);
71 }
72
73 if (strptime(timestr, "%Y-%m-%dT%H:%M:%S", &utm))
74 {
75 ln_get_date_from_tm(&utm, iso_date);
76 return (0);
77 }
78 #endif
79
80 return (-1);
81}
82
83
84/* sprint the variable a in sexagesimal format into out[].
85 * w is the number of spaces for the whole part.
86 * fracbase is the number of pieces a whole is to broken into; valid options:
87 * 360000: <w>:mm:ss.ss
88 * 36000: <w>:mm:ss.s
89 * 3600: <w>:mm:ss
90 * 600: <w>:mm.m
91 * 60: <w>:mm
92 * return number of characters written to out, not counting finaif (NOVA_FOUND)
93 include_directories(${NOVA_INCLUDE_DIR})
94endif (NOVA_FOUND)l '\0'.
95 */
96int
97fs_sexa (char *out, double a, int w, int fracbase)
98{
99 char *out0 = out;
100 unsigned long n;
101 int d;
102 int f;
103 int m;
104 int s;
105 int isneg;
106
107 /* save whether it's negative but do all the rest with a positive */
108 isneg = (a < 0);
109 if (isneg)
110 a = -a;
111
112 /* convert to an integral number of whole portions */
113 n = (unsigned long)(a * fracbase + 0.5);
114 d = n/fracbase;
115 f = n%fracbase;
116
117 /* form the whole part; "negative 0" is a special case */
118 if (isneg && d == 0)
119 out += sprintf (out, "%*s-0", w-2, "");
120 else
121 out += sprintf (out, "%*d", w, isneg ? -d : d);
122
123 /* do the rest */
124 switch (fracbase) {
125 case 60: /* dd:mm */
126 m = f/(fracbase/60);
127 out += sprintf (out, ":%02d", m);
128 break;
129 case 600: /* dd:mm.m */
130 out += sprintf (out, ":%02d.%1d", f/10, f%10);
131 break;
132 case 3600: /* dd:mm:ss */
133 m = f/(fracbase/60);
134 s = f%(fracbase/60);
135 out += sprintf (out, ":%02d:%02d", m, s);
136 break;
137 case 36000: /* dd:mm:ss.s*/
138 m = f/(fracbase/60);
139 s = f%(fracbase/60);
140 out += sprintf (out, ":%02d:%02d.%1d", m, s/10, s%10);
141 break;
142 case 360000: /* dd:mm:ss.ss */
143 m = f/(fracbase/60);
144 s = f%(fracbase/60);
145 out += sprintf (out, ":%02d:%02d.%02d", m, s/100, s%100);
146 break;
147 default:
148 printf ("fs_sexa: unknown fracbase: %d\n", fracbase);
149 exit(1);
150 }
151
152 return (out - out0);
153}
154
155/* convert sexagesimal string str AxBxC to double.
156 * x can be anything non-numeric. Any missing A, B or C will be assumed 0.
157 * optional - and + can be anywhere.
158 * return 0 if ok, -1 if can't find a thing.
159 */
160int
161f_scansexa (
162const char *str0, /* input string */
163double *dp) /* cracked value, if return 0 */
164{
165 double a = 0, b = 0, c = 0;
166 char str[128];
167 char *neg;
168 int r;
169
170 /* copy str0 so we can play with it */
171 strncpy (str, str0, sizeof(str)-1);
172 str[sizeof(str)-1] = '\0';
173
174 neg = strchr(str, '-');
175 if (neg)
176 *neg = ' ';
177 r = sscanf (str, "%lf%*[^0-9]%lf%*[^0-9]%lf", &a, &b, &c);
178 if (r < 1)
179 return (-1);
180 *dp = a + b/60 + c/3600;
181 if (neg)
182 *dp *= -1;
183 return (0);
184}
185
186void getSexComponents(double value, int *d, int *m, int *s)
187{
188
189 *d = (int) fabs(value);
190 *m = (int) ((fabs(value) - *d) * 60.0);
191 *s = (int) rint(((fabs(value) - *d) * 60.0 - *m) *60.0);
192
193 if (value < 0)
194 *d *= -1;
195}
196
197/* fill buf with properly formatted INumber string. return length */
198int
199numberFormat (char *buf, const char *format, double value)
200{
201 int w, f, s;
202 char m;
203
204 if (sscanf (format, "%%%d.%d%c", &w, &f, &m) == 3 && m == 'm') {
205 /* INDI sexi format */
206 switch (f) {
207 case 9: s = 360000; break;
208 case 8: s = 36000; break;
209 case 6: s = 3600; break;
210 case 5: s = 600; break;
211 default: s = 60; break;
212 }
213 return (fs_sexa (buf, value, w-f, s));
214 } else {
215 /* normal printf format */
216 return (sprintf (buf, format, value));
217 }
218}
219
220/* log message locally.
221 * this has nothing to do with XML or any Clients.
222 */
223void
224IDLog (const char *fmt, ...)
225{
226 va_list ap;
227 /* JM: Since all INDI's stderr are timestampped now, we don't need to time stamp ID Log */
228 /*fprintf (stderr, "%s ", timestamp());*/
229 va_start (ap, fmt);
230 vfprintf (stderr, fmt, ap);
231 va_end (ap);
232}
233
234/* return current system time in message format */
235const char *
236timestamp()
237{
238 static char ts[32];
239 struct tm *tp;
240 time_t t;
241
242 time (&t);
243 tp = gmtime (&t);
244 strftime (ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", tp);
245 return (ts);
246}
247
248int tty_timeout(int fd, int timeout)
249{
250 struct timeval tv;
251 fd_set readout;
252 int retval;
253
254 FD_ZERO(&readout);
255 FD_SET(fd, &readout);
256
257 /* wait for 'timeout' seconds */
258 tv.tv_sec = timeout;
259 tv.tv_usec = 0;
260
261 /* Wait till we have a change in the fd status */
262 retval = select (fd+1, &readout, NULL, NULL, &tv);
263
264 /* Return 0 on successful fd change */
265 if (retval > 0)
266 return TTY_OK;
267 /* Return -1 due to an error */
268 else if (retval == -1)
269 return TTY_SELECT_ERROR;
270 /* Return -2 if time expires before anything interesting happens */
271 else
272 return TTY_TIME_OUT;
273
274}
275
276int tty_write(int fd, const char * buf, int nbytes, int *nbytes_written)
277{
278 int bytes_w = 0;
279 *nbytes_written = 0;
280
281 while (nbytes > 0)
282 {
283
284 bytes_w = write(fd, buf, nbytes);
285
286 if (bytes_w < 0)
287 return TTY_WRITE_ERROR;
288
289 *nbytes_written += bytes_w;
290 buf += bytes_w;
291 nbytes -= bytes_w;
292 }
293
294 return TTY_OK;
295}
296
297int tty_write_string(int fd, const char * buf, int *nbytes_written)
298{
299 unsigned int nbytes;
300 int bytes_w = 0;
301 *nbytes_written = 0;
302
303 nbytes = strlen(buf);
304
305 while (nbytes > 0)
306 {
307
308 bytes_w = write(fd, buf, nbytes);
309
310 if (bytes_w < 0)
311 return TTY_WRITE_ERROR;
312
313 *nbytes_written += bytes_w;
314 buf += bytes_w;
315 nbytes -= bytes_w;
316 }
317
318 return TTY_OK;
319}
320
321int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
322{
323
324 int bytesRead = 0;
325 int err = 0;
326 *nbytes_read =0;
327
328 if (nbytes <=0)
329 return TTY_PARAM_ERROR;
330
331 while (nbytes > 0)
332 {
333 if ( (err = tty_timeout(fd, timeout)) )
334 return err;
335
336 bytesRead = read(fd, buf, ((unsigned) nbytes));
337
338 if (bytesRead < 0 )
339 return TTY_READ_ERROR;
340
341 buf += bytesRead;
342 *nbytes_read += bytesRead;
343 nbytes -= bytesRead;
344 }
345
346 return TTY_OK;
347}
348
349int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
350{
351
352 int bytesRead = 0;
353 int err = TTY_OK;
354 *nbytes_read = 0;
355
356 for (;;)
357 {
358 if ( (err = tty_timeout(fd, timeout)) )
359 return err;
360
361 bytesRead = read(fd, buf, 1);
362
363 if (bytesRead < 0 )
364 return TTY_READ_ERROR;
365
366 if (bytesRead)
367 (*nbytes_read)++;
368
369 if (*buf == stop_char)
370 return TTY_OK;
371
372 buf += bytesRead;
373 }
374
375 return TTY_TIME_OUT;
376}
377
378#ifdef BSD
379// BSD - OSX version
380int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
381{
382 int t_fd = -1;
383 int bps;
384 char msg[80];
385 int handshake;
386 struct termios tty_setting;
387
388 // Open the serial port read/write, with no controlling terminal, and don't wait for a connection.
389 // The O_NONBLOCK flag also causes subsequent I/O on the device to be non-blocking.
390 // See open(2) ("man 2 open") for details.
391
392 t_fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
393 if (t_fd == -1)
394 {
395 printf("Error opening serial port %s - %s(%d).\n",
396 device, strerror(errno), errno);
397 goto error;
398 }
399
400 // Note that open() follows POSIX semantics: multiple open() calls to the same file will succeed
401 // unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned
402 // processes.
403 // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
404
405 if (ioctl(t_fd, TIOCEXCL) == -1)
406 {
407 printf("Error setting TIOCEXCL on %s - %s(%d).\n",
408 device, strerror(errno), errno);
409 goto error;
410 }
411
412 // Now that the device is open, clear the O_NONBLOCK flag so subsequent I/O will block.
413 // See fcntl(2) ("man 2 fcntl") for details.
414
415 if (fcntl(t_fd, F_SETFL, 0) == -1)
416 {
417 printf("Error clearing O_NONBLOCK %s - %s(%d).\n",
418 device, strerror(errno), errno);
419 goto error;
420 }
421
422 // Get the current options and save them so we can restore the default settings later.
423 if (tcgetattr(t_fd, &tty_setting) == -1)
424 {
425 printf("Error getting tty attributes %s - %s(%d).\n",
426 device, strerror(errno), errno);
427 goto error;
428 }
429
430 // Set raw input (non-canonical) mode, with reads blocking until either a single character
431 // has been received or a one second timeout expires.
432 // See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") for details.
433
434 cfmakeraw(&tty_setting);
435 tty_setting.c_cc[VMIN] = 1;
436 tty_setting.c_cc[VTIME] = 10;
437
438 // The baud rate, word length, and handshake options can be set as follows:
439 switch (bit_rate) {
440 case 0:
441 bps = B0;
442 break;
443 case 50:
444 bps = B50;
445 break;
446 case 75:
447 bps = B75;
448 break;
449 case 110:
450 bps = B110;
451 break;
452 case 134:
453 bps = B134;
454 break;
455 case 150:
456 bps = B150;
457 break;
458 case 200:
459 bps = B200;
460 break;
461 case 300:
462 bps = B300;
463 break;
464 case 600:
465 bps = B600;
466 break;
467 case 1200:
468 bps = B1200;
469 break;
470 case 1800:
471 bps = B1800;
472 break;
473 case 2400:
474 bps = B2400;
475 break;
476 case 4800:
477 bps = B4800;
478 break;
479 case 9600:
480 bps = B9600;
481 break;
482 case 19200:
483 bps = B19200;
484 break;
485 case 38400:
486 bps = B38400;
487 break;
488 case 57600:
489 bps = B57600;
490 break;
491 case 115200:
492 bps = B115200;
493 break;
494 case 230400:
495 bps = B230400;
496 break;
497 default:
498 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid bit rate.", bit_rate) 0)
499 perror(NULL);
500 else
501 perror(msg);
502 return TTY_PARAM_ERROR;
503 }
504
505 cfsetspeed(&tty_setting, bps); // Set baud rate
506 /* word size */
507 switch (word_size) {
508 case 5:
509 tty_setting.c_cflag |= CS5;
510 break;
511 case 6:
512 tty_setting.c_cflag |= CS6;
513 break;
514 case 7:
515 tty_setting.c_cflag |= CS7;
516 break;
517 case 8:
518 tty_setting.c_cflag |= CS8;
519 break;
520 default:
521
522 fprintf( stderr, "Default\n") ;
523 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid data bit count.", word_size) 0)
524 perror(NULL);
525 else
526 perror(msg);
527
528 return TTY_PARAM_ERROR;
529 }
530
531 /* parity */
532 switch (parity) {
533 case PARITY_NONE:
534 break;
535 case PARITY_EVEN:
536 tty_setting.c_cflag |= PARENB;
537 break;
538 case PARITY_ODD:
539 tty_setting.c_cflag |= PARENB | PARODD;
540 break;
541 default:
542
543 fprintf( stderr, "Default1\n") ;
544 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid parity selection value.", parity) 0)
545 perror(NULL);
546 else
547 perror(msg);
548
549 return TTY_PARAM_ERROR;
550 }
551
552 /* stop_bits */
553 switch (stop_bits) {
554 case 1:
555 break;
556 case 2:
557 tty_setting.c_cflag |= CSTOPB;
558 break;
559 default:
560 fprintf( stderr, "Default2\n") ;
561 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid stop bit count.", stop_bits) 0)
562 perror(NULL);
563 else
564 perror(msg);
565
566 return TTY_PARAM_ERROR;
567 }
568
569#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
570 // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
571 // other than those specified by POSIX. The driver for the underlying serial hardware
572 // ultimately determines which baud rates can be used. This ioctl sets both the input
573 // and output speed.
574
575 speed_t speed = 14400; // Set 14400 baud
576 if (ioctl(fileDescriptor, IOSSIOSPEED, &speed) == -1)
577 {
578 printf("Error calling ioctl(..., IOSSIOSPEED, ...) %s - %s(%d).\n",
579 bsdPath, strerror(errno), errno);
580 }
581#endif
582
583 // Cause the new options to take effect immediately.
584 if (tcsetattr(t_fd, TCSANOW, &tty_setting) == -1)
585 {
586 printf("Error setting tty attributes %s - %s(%d).\n",
587 device, strerror(errno), errno);
588 goto error;
589 }
590
591 // To set the modem handshake lines, use the following ioctls.
592 // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
593
594 if (ioctl(t_fd, TIOCSDTR) == -1) // Assert Data Terminal Ready (DTR)
595 {
596 printf("Error asserting DTR %s - %s(%d).\n",
597 device, strerror(errno), errno);
598 }
599
600 if (ioctl(t_fd, TIOCCDTR) == -1) // Clear Data Terminal Ready (DTR)
601 {
602 printf("Error clearing DTR %s - %s(%d).\n",
603 device, strerror(errno), errno);
604 }
605
606 handshake = TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
607 if (ioctl(t_fd, TIOCMSET, &handshake) == -1)
608 // Set the modem lines depending on the bits set in handshake
609 {
610 printf("Error setting handshake lines %s - %s(%d).\n",
611 device, strerror(errno), errno);
612 }
613
614 // To read the state of the modem lines, use the following ioctl.
615 // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
616
617 if (ioctl(t_fd, TIOCMGET, &handshake) == -1)
618 // Store the state of the modem lines in handshake
619 {
620 printf("Error getting handshake lines %s - %s(%d).\n",
621 device, strerror(errno), errno);
622 }
623
624 printf("Handshake lines currently set to %d\n", handshake);
625
626#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
627 unsigned long mics = 1UL;
628
629 // Set the receive latency in microseconds. Serial drivers use this value to determine how often to
630 // dequeue characters received by the hardware. Most applications don't need to set this value: if an
631 // app reads lines of characters, the app can't do anything until the line termination character has been
632 // received anyway. The most common applications which are sensitive to read latency are MIDI and IrDA
633 // applications.
634
635 if (ioctl(t_fd, IOSSDATALAT, &mics) == -1)
636 {
637 // set latency to 1 microsecond
638 printf("Error setting read latency %s - %s(%d).\n",
639 device, strerror(errno), errno);
640 goto error;
641 }
642#endif
643
644 *fd = t_fd;
645 /* return success */
646 return TTY_OK;
647
648 // Failure path
649error:
650 if (t_fd != -1)
651 {
652 close(t_fd);
653 }
654
655 return TTY_PORT_FAILURE;
656}
657#else
658int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
659{
660#ifdef _WIN32
661 return TTY_PORT_FAILURE;
662
663#else
664 int t_fd=0;
665 char msg[80];
666 int bps;
667 struct termios tty_setting;
668
669 if ( (t_fd = open(device, O_RDWR | O_NOCTTY )) == -1)
670 return TTY_PORT_FAILURE;
671
672 /* Control Modes
673 Set bps rate */
674 switch (bit_rate) {
675 case 0:
676 bps = B0;
677 break;
678 case 50:
679 bps = B50;
680 break;
681 case 75:
682 bps = B75;
683 break;
684 case 110:
685 bps = B110;
686 break;
687 case 134:
688 bps = B134;
689 break;
690 case 150:
691 bps = B150;
692 break;
693 case 200:
694 bps = B200;
695 break;
696 case 300:
697 bps = B300;
698 break;
699 case 600:
700 bps = B600;
701 break;
702 case 1200:
703 bps = B1200;
704 break;
705 case 1800:
706 bps = B1800;
707 break;
708 case 2400:
709 bps = B2400;
710 break;
711 case 4800:
712 bps = B4800;
713 break;
714 case 9600:
715 bps = B9600;
716 break;
717 case 19200:
718 bps = B19200;
719 break;
720 case 38400:
721 bps = B38400;
722 break;
723 case 57600:
724 bps = B57600;
725 break;
726 case 115200:
727 bps = B115200;
728 break;
729 case 230400:
730 bps = B230400;
731 break;
732 default:
733 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid bit rate.", bit_rate) < 0)
734 perror(NULL);
735 else
736 perror(msg);
737 return TTY_PARAM_ERROR;
738 }
739 if ((cfsetispeed(&tty_setting, bps) < 0) ||
740 (cfsetospeed(&tty_setting, bps) < 0))
741 {
742 perror("tty_connect: failed setting bit rate.");
743 return TTY_PORT_FAILURE;
744 }
745
746 /* Control Modes
747 set no flow control word size, parity and stop bits.
748 Also don't hangup automatically and ignore modem status.
749 Finally enable receiving characters. */
750 tty_setting.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | HUPCL | CRTSCTS);
751 tty_setting.c_cflag |= (CLOCAL | CREAD);
752
753 /* word size */
754 switch (word_size) {
755 case 5:
756 tty_setting.c_cflag |= CS5;
757 break;
758 case 6:
759 tty_setting.c_cflag |= CS6;
760 break;
761 case 7:
762 tty_setting.c_cflag |= CS7;
763 break;
764 case 8:
765 tty_setting.c_cflag |= CS8;
766 break;
767 default:
768
769 fprintf( stderr, "Default\n") ;
770 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid data bit count.", word_size) < 0)
771 perror(NULL);
772 else
773 perror(msg);
774
775 return TTY_PARAM_ERROR;
776 }
777
778 /* parity */
779 switch (parity) {
780 case PARITY_NONE:
781 break;
782 case PARITY_EVEN:
783 tty_setting.c_cflag |= PARENB;
784 break;
785 case PARITY_ODD:
786 tty_setting.c_cflag |= PARENB | PARODD;
787 break;
788 default:
789
790 fprintf( stderr, "Default1\n") ;
791 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid parity selection value.", parity) < 0)
792 perror(NULL);
793 else
794 perror(msg);
795
796 return TTY_PARAM_ERROR;
797 }
798
799 /* stop_bits */
800 switch (stop_bits) {
801 case 1:
802 break;
803 case 2:
804 tty_setting.c_cflag |= CSTOPB;
805 break;
806 default:
807 fprintf( stderr, "Default2\n") ;
808 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid stop bit count.", stop_bits) < 0)
809 perror(NULL);
810 else
811 perror(msg);
812
813 return TTY_PARAM_ERROR;
814 }
815 /* Control Modes complete */
816
817 /* Ignore bytes with parity errors and make terminal raw and dumb.*/
818 tty_setting.c_iflag &= ~(PARMRK | ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON | IXANY);
819 tty_setting.c_iflag |= INPCK | IGNPAR | IGNBRK;
820
821 /* Raw output.*/
822 tty_setting.c_oflag &= ~(OPOST | ONLCR);
823
824 /* Local Modes
825 Don't echo characters. Don't generate signals.
826 Don't process any characters.*/
827 tty_setting.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN | NOFLSH | TOSTOP);
828 tty_setting.c_lflag |= NOFLSH;
829
830 /* blocking read until 1 char arrives */
831 tty_setting.c_cc[VMIN] = 1;
832 tty_setting.c_cc[VTIME] = 0;
833
834 /* now clear input and output buffers and activate the new terminal settings */
835 tcflush(t_fd, TCIOFLUSH);
836 if (tcsetattr(t_fd, TCSANOW, &tty_setting))
837 {
838 perror("tty_connect: failed setting attributes on serial port.");
839 tty_disconnect(t_fd);
840 return TTY_PORT_FAILURE;
841 }
842
843 *fd = t_fd;
844 /* return success */
845 return TTY_OK;
846#endif
847}
848// Unix - Linux version
849
850#endif
851
852
853int tty_disconnect(int fd)
854{
855#ifdef _WIN32
856 return TTY_ERRNO;
857#else
858 int err;
859 tcflush(fd, TCIOFLUSH);
860 err = close(fd);
861
862 if (err != 0)
863 return TTY_ERRNO;
864
865 return TTY_OK;
866#endif
867}
868
869void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
870{
871 char error_string[512];
872
873 switch (err_code)
874 {
875 case TTY_OK:
876 strncpy(err_msg, "No Error", err_msg_len);
877 break;
878
879 case TTY_READ_ERROR:
880 snprintf(error_string, 512, "Read Error: %s", strerror(errno));
881 strncpy(err_msg, error_string, err_msg_len);
882 break;
883
884 case TTY_WRITE_ERROR:
885 snprintf(error_string, 512, "Write Error: %s", strerror(errno));
886 strncpy(err_msg, error_string, err_msg_len);
887 break;
888
889 case TTY_SELECT_ERROR:
890 snprintf(error_string, 512, "Select Error: %s", strerror(errno));
891 strncpy(err_msg, error_string, err_msg_len);
892 break;
893
894 case TTY_TIME_OUT:
895 strncpy(err_msg, "Timeout error", err_msg_len);
896 break;
897
898 case TTY_PORT_FAILURE:
899 snprintf(error_string, 512, "Port failure Error: %s", strerror(errno));
900 strncpy(err_msg, error_string, err_msg_len);
901 break;
902
903 case TTY_PARAM_ERROR:
904 strncpy(err_msg, "Parameter error", err_msg_len);
905 break;
906
907 case TTY_ERRNO:
908 snprintf(error_string, 512, "%s", strerror(errno));
909 strncpy(err_msg, error_string, err_msg_len);
910 break;
911
912 default:
913 strncpy(err_msg, "Error: unrecognized error code", err_msg_len);
914 break;
915
916
917 }
918}
919
920/* return static string corresponding to the given property or light state */
921const char *
922pstateStr (IPState s)
923{
924 switch (s) {
925 case IPS_IDLE: return ("Idle");
926 case IPS_OK: return ("Ok");
927 case IPS_BUSY: return ("Busy");
928 case IPS_ALERT: return ("Alert");
929 default:
930 fprintf (stderr, "Impossible IPState %d\n", s);
931 exit(1);
932 }
933}
934
935/* crack string into IPState.
936 * return 0 if ok, else -1
937 */
938int
939crackIPState (const char *str, IPState *ip)
940{
941 if (!strcmp (str, "Idle")) *ip = IPS_IDLE;
942 else if (!strcmp (str, "Ok")) *ip = IPS_OK;
943 else if (!strcmp (str, "Busy")) *ip = IPS_BUSY;
944 else if (!strcmp (str, "Alert")) *ip = IPS_ALERT;
945 else return (-1);
946 return (0);
947}
948
949/* crack string into ISState.
950 * return 0 if ok, else -1
951 */
952int
953crackISState (const char *str, ISState *ip)
954{
955 if (!strcmp (str, "On")) *ip = ISS_ON;
956 else if (!strcmp (str, "Off")) *ip = ISS_OFF;
957 else return (-1);
958 return (0);
959}
960
961int
962crackIPerm (const char *str, IPerm *ip)
963{
964 if (!strcmp (str, "rw")) *ip = IP_RW;
965 else if (!strcmp (str, "ro")) *ip = IP_RO;
966 else if (!strcmp (str, "wo")) *ip = IP_WO;
967 else return (-1);
968 return (0);
969}
970
971int crackISRule (const char *str, ISRule *ip)
972{
973 if (!strcmp (str, "OneOfMany")) *ip = ISR_1OFMANY;
974 else if (!strcmp (str, "AtMostOne")) *ip = ISR_ATMOST1;
975 else if (!strcmp (str, "AnyOfMany")) *ip = ISR_NOFMANY;
976 else return (-1);
977 return (0);
978}
979
980/* return static string corresponding to the given switch state */
981const char *
982sstateStr (ISState s)
983{
984 switch (s) {
985 case ISS_ON: return ("On");
986 case ISS_OFF: return ("Off");
987 default:
988 fprintf (stderr, "Impossible ISState %d\n", s);
989 }
990}
991
992/* return static string corresponding to the given Rule */
993const char *
994ruleStr (ISRule r)
995{
996 switch (r) {
997 case ISR_1OFMANY: return ("OneOfMany");
998 case ISR_ATMOST1: return ("AtMostOne");
999 case ISR_NOFMANY: return ("AnyOfMany");
1000 default:
1001 fprintf (stderr, "Impossible ISRule %d\n", r);
1002 }
1003}
1004
1005/* return static string corresponding to the given IPerm */
1006const char *
1007permStr (IPerm p)
1008{
1009 switch (p) {
1010 case IP_RO: return ("ro");
1011 case IP_WO: return ("wo");
1012 case IP_RW: return ("rw");
1013 default:
1014 fprintf (stderr, "Impossible IPerm %d\n", p);
1015 }
1016}
1017
1018/* print the boilerplate comment introducing xml */
1019void
1020xmlv1()
1021{
1022 printf ("<?xml version='1.0'?>\n");
1023}
1024
1025/* pull out device and name attributes from root.
1026 * return 0 if ok else -1 with reason in msg[].
1027 */
1028int
1029crackDN (XMLEle *root, char **dev, char **name, char msg[])
1030{
1031 XMLAtt *ap;
1032
1033 ap = findXMLAtt (root, "device");
1034 if (!ap) {
1035 sprintf (msg, "%s requires 'device' attribute", tagXMLEle(root));
1036 return (-1);
1037 }
1038 *dev = valuXMLAtt(ap);
1039
1040 ap = findXMLAtt (root, "name");
1041 if (!ap) {
1042 sprintf (msg, "%s requires 'name' attribute", tagXMLEle(root));
1043 return (-1);
1044 }
1045 *name = valuXMLAtt(ap);
1046
1047 return (0);
1048}
1049
1050/* find a member of an IText vector, else NULL */
1051IText *
1052IUFindText (const ITextVectorProperty *tvp, const char *name)
1053{
1054 int i;
1055
1056 for (i = 0; i < tvp->ntp; i++)
1057 if (strcmp (tvp->tp[i].name, name) == 0)
1058 return (&tvp->tp[i]);
1059 fprintf (stderr, "No IText '%s' in %s.%s\n",name,tvp->device,tvp->name);
1060 return (NULL);
1061}
1062
1063/* find a member of an INumber vector, else NULL */
1064INumber *
1065IUFindNumber(const INumberVectorProperty *nvp, const char *name)
1066{
1067 int i;
1068
1069 for (i = 0; i < nvp->nnp; i++)
1070 if (strcmp (nvp->np[i].name, name) == 0)
1071 return (&nvp->np[i]);
1072 fprintf(stderr,"No INumber '%s' in %s.%s\n",name,nvp->device,nvp->name);
1073 return (NULL);
1074}
1075
1076/* find a member of an ISwitch vector, else NULL */
1077ISwitch *
1078IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
1079{
1080 int i;
1081
1082 for (i = 0; i < svp->nsp; i++)
1083 if (strcmp (svp->sp[i].name, name) == 0)
1084 return (&svp->sp[i]);
1085 fprintf(stderr,"No ISwitch '%s' in %s.%s\n",name,svp->device,svp->name);
1086 return (NULL);
1087}
1088
1089/* find a member of an ILight vector, else NULL */
1090ILight *
1091IUFindLight(const ILightVectorProperty *lvp, const char *name)
1092{
1093 int i;
1094
1095 for (i = 0; i < lvp->nlp; i++)
1096 if (strcmp (lvp->lp[i].name, name) == 0)
1097 return (&lvp->lp[i]);
1098 fprintf(stderr,"No ILight '%s' in %s.%s\n",name,lvp->device,lvp->name);
1099 return (NULL);
1100}
1101
1102/* find a member of an IBLOB vector, else NULL */
1103IBLOB *
1104IUFindBLOB(const IBLOBVectorProperty *bvp, const char *name)
1105{
1106 int i;
1107
1108 for (i = 0; i < bvp->nbp; i++)
1109 if (strcmp (bvp->bp[i].name, name) == 0)
1110 return (&bvp->bp[i]);
1111 fprintf(stderr,"No IBLOB '%s' in %s.%s\n",name,bvp->device,bvp->name);
1112 return (NULL);
1113}
1114
1115/* find an ON member of an ISwitch vector, else NULL.
1116 * N.B. user must make sense of result with ISRule in mind.
1117 */
1118ISwitch *
1119IUFindOnSwitch(const ISwitchVectorProperty *svp)
1120{
1121 int i;
1122
1123 for (i = 0; i < svp->nsp; i++)
1124 if (svp->sp[i].s == ISS_ON)
1125 return (&svp->sp[i]);
1126 /*fprintf(stderr, "No ISwitch On in %s.%s\n", svp->device, svp->name);*/
1127 return (NULL);
1128}
1129
1130/* Set all switches to off */
1131void
1132IUResetSwitch(ISwitchVectorProperty *svp)
1133{
1134 int i;
1135
1136 for (i = 0; i < svp->nsp; i++)
1137 svp->sp[i].s = ISS_OFF;
1138}
1139
1140/* save malloced copy of newtext in tp->text, reusing if not first time */
1141void
1142IUSaveText (IText *tp, const char *newtext)
1143{
1144 /* seed for realloc */
1145 if (tp->text == NULL)
1146 tp->text = malloc (1);
1147
1148 /* copy in fresh string */
1149 tp->text = strcpy (realloc (tp->text, strlen(newtext)+1), newtext);
1150}
Note: See TracBrowser for help on using the repository browser.