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

Last change on this file since 614 was 501, checked in by frichard, 14 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.