1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2000
3*4882a593Smuzhiyun * Murray Jensen <Murray.Jensen@csiro.au>
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <unistd.h>
9*4882a593Smuzhiyun #include <string.h>
10*4882a593Smuzhiyun #include <fcntl.h>
11*4882a593Smuzhiyun #include <sys/time.h>
12*4882a593Smuzhiyun #include "serial.h"
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #if defined(__sun__) || \
15*4882a593Smuzhiyun defined(__OpenBSD__) || \
16*4882a593Smuzhiyun defined(__FreeBSD__) || \
17*4882a593Smuzhiyun defined(__NetBSD__) || \
18*4882a593Smuzhiyun defined(__APPLE__)
19*4882a593Smuzhiyun static struct termios tios = { BRKINT, 0, B115200|CS8|CREAD, 0, { 0 } };
20*4882a593Smuzhiyun #else
21*4882a593Smuzhiyun static struct termios tios = { BRKINT, 0, B115200|CS8|CREAD, 0, 0 };
22*4882a593Smuzhiyun #endif
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun static struct speedmap {
25*4882a593Smuzhiyun char *str;
26*4882a593Smuzhiyun speed_t val;
27*4882a593Smuzhiyun } speedmap[] = {
28*4882a593Smuzhiyun { "50", B50 }, { "75", B75 }, { "110", B110 },
29*4882a593Smuzhiyun { "134", B134 }, { "150", B150 }, { "200", B200 },
30*4882a593Smuzhiyun { "300", B300 }, { "600", B600 }, { "1200", B1200 },
31*4882a593Smuzhiyun { "1800", B1800 }, { "2400", B2400 }, { "4800", B4800 },
32*4882a593Smuzhiyun { "9600", B9600 }, { "19200", B19200 }, { "38400", B38400 },
33*4882a593Smuzhiyun { "57600", B57600 },
34*4882a593Smuzhiyun #ifdef B76800
35*4882a593Smuzhiyun { "76800", B76800 },
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun { "115200", B115200 },
38*4882a593Smuzhiyun #ifdef B153600
39*4882a593Smuzhiyun { "153600", B153600 },
40*4882a593Smuzhiyun #endif
41*4882a593Smuzhiyun { "230400", B230400 },
42*4882a593Smuzhiyun #ifdef B307200
43*4882a593Smuzhiyun { "307200", B307200 },
44*4882a593Smuzhiyun #endif
45*4882a593Smuzhiyun #ifdef B460800
46*4882a593Smuzhiyun { "460800", B460800 }
47*4882a593Smuzhiyun #endif
48*4882a593Smuzhiyun };
49*4882a593Smuzhiyun static int nspeeds = sizeof speedmap / sizeof speedmap[0];
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun speed_t
cvtspeed(char * str)52*4882a593Smuzhiyun cvtspeed(char *str)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun struct speedmap *smp = speedmap, *esmp = &speedmap[nspeeds];
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun while (smp < esmp) {
57*4882a593Smuzhiyun if (strcmp(str, smp->str) == 0)
58*4882a593Smuzhiyun return (smp->val);
59*4882a593Smuzhiyun smp++;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun return B0;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun int
serialopen(char * device,speed_t speed)65*4882a593Smuzhiyun serialopen(char *device, speed_t speed)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun int fd;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun if (cfsetospeed(&tios, speed) < 0)
70*4882a593Smuzhiyun return -1;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun if ((fd = open(device, O_RDWR)) < 0)
73*4882a593Smuzhiyun return -1;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
76*4882a593Smuzhiyun (void)close(fd);
77*4882a593Smuzhiyun return -1;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun return fd;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun int
serialreadchar(int fd,int timeout)84*4882a593Smuzhiyun serialreadchar(int fd, int timeout)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun fd_set fds;
87*4882a593Smuzhiyun struct timeval tv;
88*4882a593Smuzhiyun int n;
89*4882a593Smuzhiyun char ch;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun tv.tv_sec = timeout;
92*4882a593Smuzhiyun tv.tv_usec = 0;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun FD_ZERO(&fds);
95*4882a593Smuzhiyun FD_SET(fd, &fds);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /* this is a fucking horrible quick hack - fix this */
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun if ((n = select(fd + 1, &fds, 0, 0, &tv)) < 0)
100*4882a593Smuzhiyun return SERIAL_ERROR;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun if (n == 0)
103*4882a593Smuzhiyun return SERIAL_TIMEOUT;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun if ((n = read(fd, &ch, 1)) < 0)
106*4882a593Smuzhiyun return SERIAL_ERROR;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun if (n == 0)
109*4882a593Smuzhiyun return SERIAL_EOF;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun return ch;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun int
serialwrite(int fd,char * buf,int len)115*4882a593Smuzhiyun serialwrite(int fd, char *buf, int len)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun int n;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun do {
120*4882a593Smuzhiyun n = write(fd, buf, len);
121*4882a593Smuzhiyun if (n < 0)
122*4882a593Smuzhiyun return 1;
123*4882a593Smuzhiyun len -= n;
124*4882a593Smuzhiyun buf += n;
125*4882a593Smuzhiyun } while (len > 0);
126*4882a593Smuzhiyun return 0;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun int
serialclose(int fd)130*4882a593Smuzhiyun serialclose(int fd)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun return close(fd);
133*4882a593Smuzhiyun }
134