summaryrefslogtreecommitdiff
path: root/serial.c
blob: 906ace5be2cd37bb01191132fe93545cc3e8c096 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include "config.h"
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

#if defined (HAVE_SYS_TERMIOS_H)
#include <sys/termios.h>
#else
#if defined (HAVE_TERMIOS_H)
#include <termios.h>
#endif
#endif

#include "gps.h"
#include "gpsd.h"

/* FIXME: these shouldn't be globals */
static struct termios ttyset, ttyset_old;

static int set_baud(long baud)
{
    int speed;

    if (baud < 200)
      baud *= 1000;
    if (baud < 2400)
      speed = B1200;
    else if (baud < 4800)
      speed = B2400;
    else if (baud < 9600)
      speed = B4800;
    else if (baud < 19200)
      speed = B9600;
    else if (baud < 38400)
      speed = B19200;
    else
      speed = B38400;

    return speed;
}

int gpsd_open(char *device_name, int device_speed, int stopbits)
{
    int ttyfd;

    gpsd_report(1, "opening GPS data source at %s\n", device_name);
    if ((ttyfd = open(device_name, O_RDWR | O_NONBLOCK)) < 0)
	return -1;

    if (isatty(ttyfd)) {
	gpsd_report(1, "setting speed %d, 8 bits, no parity\n", device_speed);
	/* Save original terminal parameters */
	if (tcgetattr(ttyfd,&ttyset_old) != 0)
	  return -1;

	memcpy(&ttyset, &ttyset_old, sizeof(ttyset));

	device_speed = set_baud(device_speed);
	cfsetispeed(&ttyset, (speed_t)device_speed);
	cfsetospeed(&ttyset, (speed_t)device_speed);

	ttyset.c_cflag &= ~(PARENB | CRTSCTS);
	ttyset.c_cflag |= (CSIZE & (stopbits==2 ? CS7 : CS8)) | CREAD | CLOCAL;
	ttyset.c_iflag = ttyset.c_oflag = ttyset.c_lflag = (tcflag_t) 0;
	ttyset.c_oflag = (ONLCR);
	if (tcsetattr(ttyfd, TCSANOW, &ttyset) != 0)
	    return -1;
    }
    return ttyfd;
}

void gpsd_close(int ttyfd)
/* restore original terminal settings, but make sure DTR goes down */
{
    if (ttyfd != -1) {
	if (isatty(ttyfd)) {
#if defined (USE_TERMIO)
	    ttyset.c_cflag = CBAUD & B0;
#else
	    ttyset.c_ispeed = B0;
	    ttyset.c_ospeed = B0;
#endif
            tcsetattr(ttyfd, TCSANOW, &ttyset);
	    ttyset_old.c_cflag |= HUPCL;
	    tcsetattr(ttyfd,TCSANOW,&ttyset_old);
	}
	close(ttyfd);
    }
}