source: BAORadio/libindi/v1/libs/indicom.c@ 655

Last change on this file since 655 was 490, checked in by campagne, 15 years ago

import libindi (JEC)

File size: 14.5 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/* needed for sincos() in math.h */
27#ifndef _GNU_SOURCE
28#define _GNU_SOURCE
29#endif
30#ifdef _WIN32
31#define CX _CX
32#define CY _CY
33#endif
34#include <stdlib.h>
35#include <math.h>
36#include <stdio.h>
37#include <string.h>
38#include <unistd.h>
39#include <fcntl.h>
40#include <errno.h>
41#include <stdarg.h>
42
43#include <config.h>
44
45#ifdef HAVE_NOVA_H
46#include <libnova.h>
47#endif
48
49
50#include "indicom.h"
51#ifdef _WIN32
52#undef CX
53#undef CY
54#endif
55const char * Direction[] = { "North", "West", "East", "South", "All"};
56const char * SolarSystem[] = { "Mercury", "Venus", "Moon", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"};
57
58/* make it compile on solaris */
59#ifndef M_PI
60#define M_PI 3.14159265358979323846264338327950288419716939937510582097494459
61#endif
62
63#ifndef _WIN32
64#include <termios.h>
65#define PARITY_NONE 0
66#define PARITY_EVEN 1
67#define PARITY_ODD 2
68#endif
69
70void getSexComponents(double value, int *d, int *m, int *s);
71
72
73int extractISOTime(char *timestr, struct ln_date *iso_date)
74{
75 #ifdef HAVE_NOVA_H
76 struct tm utm;
77
78 if (strptime(timestr, "%Y/%m/%dT%H:%M:%S", &utm))
79 {
80 ln_get_date_from_tm(&utm, iso_date);
81 return (0);
82 }
83
84 if (strptime(timestr, "%Y-%m-%dT%H:%M:%S", &utm))
85 {
86 ln_get_date_from_tm(&utm, iso_date);
87 return (0);
88 }
89 #endif
90
91 return (-1);
92}
93
94
95/* sprint the variable a in sexagesimal format into out[].
96 * w is the number of spaces for the whole part.
97 * fracbase is the number of pieces a whole is to broken into; valid options:
98 * 360000: <w>:mm:ss.ss
99 * 36000: <w>:mm:ss.s
100 * 3600: <w>:mm:ss
101 * 600: <w>:mm.m
102 * 60: <w>:mm
103 * return number of characters written to out, not counting finaif (NOVA_FOUND)
104 include_directories(${NOVA_INCLUDE_DIR})
105endif (NOVA_FOUND)l '\0'.
106 */
107int
108fs_sexa (char *out, double a, int w, int fracbase)
109{
110 char *out0 = out;
111 unsigned long n;
112 int d;
113 int f;
114 int m;
115 int s;
116 int isneg;
117
118 /* save whether it's negative but do all the rest with a positive */
119 isneg = (a < 0);
120 if (isneg)
121 a = -a;
122
123 /* convert to an integral number of whole portions */
124 n = (unsigned long)(a * fracbase + 0.5);
125 d = n/fracbase;
126 f = n%fracbase;
127
128 /* form the whole part; "negative 0" is a special case */
129 if (isneg && d == 0)
130 out += sprintf (out, "%*s-0", w-2, "");
131 else
132 out += sprintf (out, "%*d", w, isneg ? -d : d);
133
134 /* do the rest */
135 switch (fracbase) {
136 case 60: /* dd:mm */
137 m = f/(fracbase/60);
138 out += sprintf (out, ":%02d", m);
139 break;
140 case 600: /* dd:mm.m */
141 out += sprintf (out, ":%02d.%1d", f/10, f%10);
142 break;
143 case 3600: /* dd:mm:ss */
144 m = f/(fracbase/60);
145 s = f%(fracbase/60);
146 out += sprintf (out, ":%02d:%02d", m, s);
147 break;
148 case 36000: /* dd:mm:ss.s*/
149 m = f/(fracbase/60);
150 s = f%(fracbase/60);
151 out += sprintf (out, ":%02d:%02d.%1d", m, s/10, s%10);
152 break;
153 case 360000: /* dd:mm:ss.ss */
154 m = f/(fracbase/60);
155 s = f%(fracbase/60);
156 out += sprintf (out, ":%02d:%02d.%02d", m, s/100, s%100);
157 break;
158 default:
159 printf ("fs_sexa: unknown fracbase: %d\n", fracbase);
160 exit(1);
161 }
162
163 return (out - out0);
164}
165
166/* convert sexagesimal string str AxBxC to double.
167 * x can be anything non-numeric. Any missing A, B or C will be assumed 0.
168 * optional - and + can be anywhere.
169 * return 0 if ok, -1 if can't find a thing.
170 */
171int
172f_scansexa (
173const char *str0, /* input string */
174double *dp) /* cracked value, if return 0 */
175{
176 double a = 0, b = 0, c = 0;
177 char str[128];
178 char *neg;
179 int r;
180
181 /* copy str0 so we can play with it */
182 strncpy (str, str0, sizeof(str)-1);
183 str[sizeof(str)-1] = '\0';
184
185 neg = strchr(str, '-');
186 if (neg)
187 *neg = ' ';
188 r = sscanf (str, "%lf%*[^0-9]%lf%*[^0-9]%lf", &a, &b, &c);
189 if (r < 1)
190 return (-1);
191 *dp = a + b/60 + c/3600;
192 if (neg)
193 *dp *= -1;
194 return (0);
195}
196
197void getSexComponents(double value, int *d, int *m, int *s)
198{
199
200 *d = (int) fabs(value);
201 *m = (int) ((fabs(value) - *d) * 60.0);
202 *s = (int) rint(((fabs(value) - *d) * 60.0 - *m) *60.0);
203
204 if (value < 0)
205 *d *= -1;
206}
207
208/* fill buf with properly formatted INumber string. return length */
209int
210numberFormat (char *buf, const char *format, double value)
211{
212 int w, f, s;
213 char m;
214
215 if (sscanf (format, "%%%d.%d%c", &w, &f, &m) == 3 && m == 'm') {
216 /* INDI sexi format */
217 switch (f) {
218 case 9: s = 360000; break;
219 case 8: s = 36000; break;
220 case 6: s = 3600; break;
221 case 5: s = 600; break;
222 default: s = 60; break;
223 }
224 return (fs_sexa (buf, value, w-f, s));
225 } else {
226 /* normal printf format */
227 return (sprintf (buf, format, value));
228 }
229}
230
231/* log message locally.
232 * this has nothing to do with XML or any Clients.
233 */
234void
235IDLog (const char *fmt, ...)
236{
237 va_list ap;
238 /* JM: Since all INDI's stderr are timestampped now, we don't need to time stamp ID Log */
239 /*fprintf (stderr, "%s ", timestamp());*/
240 va_start (ap, fmt);
241 vfprintf (stderr, fmt, ap);
242 va_end (ap);
243}
244
245/* return current system time in message format */
246const char *
247timestamp()
248{
249 static char ts[32];
250 struct tm *tp;
251 time_t t;
252
253 time (&t);
254 tp = gmtime (&t);
255 strftime (ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", tp);
256 return (ts);
257}
258
259int tty_timeout(int fd, int timeout)
260{
261 struct timeval tv;
262 fd_set readout;
263 int retval;
264
265 FD_ZERO(&readout);
266 FD_SET(fd, &readout);
267
268 /* wait for 'timeout' seconds */
269 tv.tv_sec = timeout;
270 tv.tv_usec = 0;
271
272 /* Wait till we have a change in the fd status */
273 retval = select (fd+1, &readout, NULL, NULL, &tv);
274
275 /* Return 0 on successful fd change */
276 if (retval > 0)
277 return TTY_OK;
278 /* Return -1 due to an error */
279 else if (retval == -1)
280 return TTY_SELECT_ERROR;
281 /* Return -2 if time expires before anything interesting happens */
282 else
283 return TTY_TIME_OUT;
284
285}
286
287int tty_write(int fd, const char * buf, int nbytes, int *nbytes_written)
288{
289 int bytes_w = 0;
290 *nbytes_written = 0;
291
292 while (nbytes > 0)
293 {
294
295 bytes_w = write(fd, buf, nbytes);
296
297 if (bytes_w < 0)
298 return TTY_WRITE_ERROR;
299
300 *nbytes_written += bytes_w;
301 buf += bytes_w;
302 nbytes -= bytes_w;
303 }
304
305 return TTY_OK;
306}
307
308int tty_write_string(int fd, const char * buf, int *nbytes_written)
309{
310 unsigned int nbytes;
311 int bytes_w = 0;
312 *nbytes_written = 0;
313
314 nbytes = strlen(buf);
315
316 while (nbytes > 0)
317 {
318
319 bytes_w = write(fd, buf, nbytes);
320
321 if (bytes_w < 0)
322 return TTY_WRITE_ERROR;
323
324 *nbytes_written += bytes_w;
325 buf += bytes_w;
326 nbytes -= bytes_w;
327 }
328
329 return TTY_OK;
330}
331
332int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
333{
334
335 int bytesRead = 0;
336 int err = 0;
337 *nbytes_read =0;
338
339 if (nbytes <=0)
340 return TTY_PARAM_ERROR;
341
342 while (nbytes > 0)
343 {
344 if ( (err = tty_timeout(fd, timeout)) )
345 return err;
346
347 bytesRead = read(fd, buf, ((unsigned) nbytes));
348
349 if (bytesRead < 0 )
350 return TTY_READ_ERROR;
351
352 buf += bytesRead;
353 *nbytes_read += bytesRead;
354 nbytes -= bytesRead;
355 }
356
357 return TTY_OK;
358}
359
360int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
361{
362
363 int bytesRead = 0;
364 int err = TTY_OK;
365 *nbytes_read = 0;
366
367 for (;;)
368 {
369 if ( (err = tty_timeout(fd, timeout)) )
370 return err;
371
372 bytesRead = read(fd, buf, 1);
373
374 if (bytesRead < 0 )
375 return TTY_READ_ERROR;
376
377 if (bytesRead)
378 (*nbytes_read)++;
379
380 if (*buf == stop_char)
381 return TTY_OK;
382
383 buf += bytesRead;
384 }
385
386 return TTY_TIME_OUT;
387}
388
389int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
390{
391#ifdef _WIN32
392 return TTY_PORT_FAILURE;
393
394#else
395 int t_fd=0;
396 char msg[80];
397 int bps;
398 struct termios tty_setting;
399
400 if ( (t_fd = open(device, O_RDWR | O_NOCTTY )) == -1)
401 return TTY_PORT_FAILURE;
402
403 /* Control Modes
404 Set bps rate */
405 switch (bit_rate) {
406 case 0:
407 bps = B0;
408 break;
409 case 50:
410 bps = B50;
411 break;
412 case 75:
413 bps = B75;
414 break;
415 case 110:
416 bps = B110;
417 break;
418 case 134:
419 bps = B134;
420 break;
421 case 150:
422 bps = B150;
423 break;
424 case 200:
425 bps = B200;
426 break;
427 case 300:
428 bps = B300;
429 break;
430 case 600:
431 bps = B600;
432 break;
433 case 1200:
434 bps = B1200;
435 break;
436 case 1800:
437 bps = B1800;
438 break;
439 case 2400:
440 bps = B2400;
441 break;
442 case 4800:
443 bps = B4800;
444 break;
445 case 9600:
446 bps = B9600;
447 break;
448 case 19200:
449 bps = B19200;
450 break;
451 case 38400:
452 bps = B38400;
453 break;
454 case 57600:
455 bps = B57600;
456 break;
457 case 115200:
458 bps = B115200;
459 break;
460 case 230400:
461 bps = B230400;
462 break;
463 default:
464 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid bit rate.", bit_rate) < 0)
465 perror(NULL);
466 else
467 perror(msg);
468 return TTY_PARAM_ERROR;
469 }
470 if ((cfsetispeed(&tty_setting, bps) < 0) ||
471 (cfsetospeed(&tty_setting, bps) < 0))
472 {
473 perror("tty_connect: failed setting bit rate.");
474 return TTY_PORT_FAILURE;
475 }
476
477 /* Control Modes
478 set no flow control word size, parity and stop bits.
479 Also don't hangup automatically and ignore modem status.
480 Finally enable receiving characters. */
481 tty_setting.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | HUPCL | CRTSCTS);
482 tty_setting.c_cflag |= (CLOCAL | CREAD);
483
484 /* word size */
485 switch (word_size) {
486 case 5:
487 tty_setting.c_cflag |= CS5;
488 break;
489 case 6:
490 tty_setting.c_cflag |= CS6;
491 break;
492 case 7:
493 tty_setting.c_cflag |= CS7;
494 break;
495 case 8:
496 tty_setting.c_cflag |= CS8;
497 break;
498 default:
499
500 fprintf( stderr, "Default\n") ;
501 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid data bit count.", word_size) < 0)
502 perror(NULL);
503 else
504 perror(msg);
505
506 return TTY_PARAM_ERROR;
507 }
508
509 /* parity */
510 switch (parity) {
511 case PARITY_NONE:
512 break;
513 case PARITY_EVEN:
514 tty_setting.c_cflag |= PARENB;
515 break;
516 case PARITY_ODD:
517 tty_setting.c_cflag |= PARENB | PARODD;
518 break;
519 default:
520
521 fprintf( stderr, "Default1\n") ;
522 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid parity selection value.", parity) < 0)
523 perror(NULL);
524 else
525 perror(msg);
526
527 return TTY_PARAM_ERROR;
528 }
529
530 /* stop_bits */
531 switch (stop_bits) {
532 case 1:
533 break;
534 case 2:
535 tty_setting.c_cflag |= CSTOPB;
536 break;
537 default:
538 fprintf( stderr, "Default2\n") ;
539 if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid stop bit count.", stop_bits) < 0)
540 perror(NULL);
541 else
542 perror(msg);
543
544 return TTY_PARAM_ERROR;
545 }
546 /* Control Modes complete */
547
548 /* Ignore bytes with parity errors and make terminal raw and dumb.*/
549 tty_setting.c_iflag &= ~(PARMRK | ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON | IXANY);
550 tty_setting.c_iflag |= INPCK | IGNPAR | IGNBRK;
551
552 /* Raw output.*/
553 tty_setting.c_oflag &= ~(OPOST | ONLCR);
554
555 /* Local Modes
556 Don't echo characters. Don't generate signals.
557 Don't process any characters.*/
558 tty_setting.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN | NOFLSH | TOSTOP);
559 tty_setting.c_lflag |= NOFLSH;
560
561 /* blocking read until 1 char arrives */
562 tty_setting.c_cc[VMIN] = 1;
563 tty_setting.c_cc[VTIME] = 0;
564
565 /* now clear input and output buffers and activate the new terminal settings */
566 tcflush(t_fd, TCIOFLUSH);
567 if (tcsetattr(t_fd, TCSANOW, &tty_setting))
568 {
569 perror("tty_connect: failed setting attributes on serial port.");
570 tty_disconnect(t_fd);
571 return TTY_PORT_FAILURE;
572 }
573
574 *fd = t_fd;
575 /* return success */
576 return TTY_OK;
577#endif
578}
579
580int tty_disconnect(int fd)
581{
582#ifdef _WIN32
583 return TTY_ERRNO;
584#else
585 int err;
586 tcflush(fd, TCIOFLUSH);
587 err = close(fd);
588
589 if (err != 0)
590 return TTY_ERRNO;
591
592 return TTY_OK;
593#endif
594}
595
596void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
597{
598 char error_string[512];
599
600 switch (err_code)
601 {
602 case TTY_OK:
603 strncpy(err_msg, "No Error", err_msg_len);
604 break;
605
606 case TTY_READ_ERROR:
607 snprintf(error_string, 512, "Read Error: %s", strerror(errno));
608 strncpy(err_msg, error_string, err_msg_len);
609 break;
610
611 case TTY_WRITE_ERROR:
612 snprintf(error_string, 512, "Write Error: %s", strerror(errno));
613 strncpy(err_msg, error_string, err_msg_len);
614 break;
615
616 case TTY_SELECT_ERROR:
617 snprintf(error_string, 512, "Select Error: %s", strerror(errno));
618 strncpy(err_msg, error_string, err_msg_len);
619 break;
620
621 case TTY_TIME_OUT:
622 strncpy(err_msg, "Timeout error", err_msg_len);
623 break;
624
625 case TTY_PORT_FAILURE:
626 snprintf(error_string, 512, "Port failure Error: %s", strerror(errno));
627 strncpy(err_msg, error_string, err_msg_len);
628 break;
629
630 case TTY_PARAM_ERROR:
631 strncpy(err_msg, "Parameter error", err_msg_len);
632 break;
633
634 case TTY_ERRNO:
635 snprintf(error_string, 512, "%s", strerror(errno));
636 strncpy(err_msg, error_string, err_msg_len);
637 break;
638
639 default:
640 strncpy(err_msg, "Error: unrecognized error code", err_msg_len);
641 break;
642
643
644 }
645}
Note: See TracBrowser for help on using the repository browser.