plptools
Loading...
Searching...
No Matches
mp_serial.c
Go to the documentation of this file.
1/*
2 // PLP - An implementation of the PSION link protocol
3 //
4 // The code in this file was written by Rudolf Koenig
5 // (rfkoenig@immd4.informatik.uni-erlangen.de). (from his p3nfs code)
6 // The Copyright remains his.
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License along
19 // along with this program; if not, see <https://www.gnu.org/licenses/>.
20 //
21 // e-mail philip.proudman@btinternet.com
22 */
23#include "config.h"
24
25#include <stdio.h>
26#include <fcntl.h>
27#include <unistd.h> /* for usleep() */
28#include <string.h> /* for bzero() */
29#include <termios.h>
30#if defined(linux) || defined(_IBMR2) || \
31 (defined(__APPLE__) && defined(__MACH__)) || \
32 defined(__NetBSD__) || defined(__FreeBSD__)
33#include <sys/ioctl.h> /* for ioctl() */
34#endif
35#include <errno.h>
36#ifdef sun
37#include <sys/ttold.h> /* sun has TIOCEXCL there */
38#endif
39#include <stdlib.h>
40
41#ifdef hpux
42#include <sys/termiox.h>
43#include <sys/modem.h>
44#endif
45
46#include "mp_serial.h"
47
48
49#ifdef __sgi
50#define CRTSCTS CNEW_RTSCTS
51#endif
52
53#ifndef O_NOCTTY
54#define O_NOCTTY 0
55#endif
56
57int
58init_serial(const char *dev, int speed, int debug)
59{
60 int fd, baud;
61 int uid, euid;
62 struct termios ti;
63#ifdef hpux
64 struct termiox tx;
65#endif
66 static struct baud {
67 int speed, baud;
68 } btable[] = {
69 { 9600, B9600 },
70#ifdef B19200
71 { 19200, B19200 },
72#else
73#ifdef EXTA
74 { 19200, EXTA },
75#endif
76#endif
77#ifdef B38400
78 { 38400, B38400 },
79#else
80#ifdef EXTB
81 { 38400, EXTB },
82#endif
83#endif
84#ifdef B57600
85 { 57600, B57600 },
86#endif
87#ifdef B115200
88 { 115200, B115200 },
89#endif
90 { 4800, B4800 },
91 { 2400, B2400 },
92 { 1200, B1200 },
93 { 300, B300 },
94 { 75, B75 },
95 { 50, B50 },
96 { 0, 0 }
97 }, *bptr;
98
99 if (speed) {
100 for (bptr = btable; bptr->speed; bptr++)
101 if (bptr->speed == speed)
102 break;
103 if (!bptr->baud) {
104 fprintf(stderr, "Cannot match selected speed %d\n", speed);
105 exit(1);
106 }
107 baud = bptr->baud;
108 } else
109 baud = 0;
110
111 if (debug)
112 printf("using %s...\n", dev);
113 euid = geteuid();
114 uid = getuid();
115
116#ifdef hpux
117#define seteuid(a) setresuid(-1, a, -1)
118#endif
119
120 if (seteuid(uid)) {
121 perror("seteuid");
122 exit(1);
123 }
124
125 int options = O_RDWR | O_NOCTTY;
126#if defined(__APPLE__) && defined(__MACH__)
127 // On macOS 27, open seems to hang indefinitely when opened 'blocking' so we always open in non-blocking mode on
128 // macOS. The Reconnect branch of plptools has opened the serial port non-blocking since its inception, so this
129 // is well tested. Since DataLink is entirely select-based and does not rely on blocking reads, non-blocking should
130 // be safe---even preferable---and we should probably enable this everywhere long-term.
131 options |= O_NONBLOCK;
132#endif
133
134 if ((fd = open(dev, options, 0)) < 0) {
135 perror(dev);
136 exit(1);
137 }
138 if (seteuid(euid)) {
139 perror("seteuid back");
140 exit(1);
141 }
142 if (debug)
143 printf("open done\n");
144#ifdef TIOCEXCL
145 ioctl(fd, TIOCEXCL, (char *) 0); /* additional open() calls shall fail */
146#else
147 fprintf(stderr, "WARNING: opened %s non-exclusive!\n", dev);
148#endif
149
150 memset(&ti, 0, sizeof(struct termios));
151 ti.c_cflag = CS8 | HUPCL | CLOCAL | CREAD;
152#if defined(sun) || defined(linux) || defined(__sgi) || \
153 (defined(__APPLE__) && defined(__MACH__)) || \
154 defined(__NetBSD__) || defined(__FreeBSD__)
155 ti.c_cflag |= CRTSCTS;
156 ti.c_iflag = IGNBRK | IGNPAR;
157 ti.c_cc[VMIN] = 1;
158 ti.c_cc[VTIME] = 0;
159#endif
160 cfsetispeed(&ti, baud);
161 cfsetospeed(&ti, baud);
162
163 if (tcsetattr(fd, TCSADRAIN, &ti) < 0)
164 perror("tcsetattr TCSADRAIN");
165
166#ifdef hpux
167 bzero(&tx, sizeof(struct termiox));
168 tx.x_hflag = RTSXOFF | CTSXON;
169 if (ioctl(fd, TCSETXW, &tx) < 0)
170 perror("TCSETXW");
171#endif
172#if defined(_IBMR2)
173 ioctl(fd, TXDELCD, "dtr");
174 ioctl(fd, TXDELCD, "xon");
175 ioctl(fd, TXADDCD, "rts"); /* That's how AIX does CRTSCTS */
176#endif
177
178 return fd;
179}
180
181void
182ser_exit(int fd)
183{
184 struct termios ti;
185
186#ifdef TIOCNXCL
187 ioctl(fd, TIOCNXCL, (char *) 0);
188#endif
189 if (tcgetattr(fd, &ti) < 0)
190 perror("tcgetattr");
191 ti.c_cflag &= ~CRTSCTS;
192 if (tcsetattr(fd, TCSANOW, &ti) < 0)
193 perror("tcsetattr");
194 (void) close(fd);
195}
int debug
Definition fuse.c:48
#define O_NOCTTY
Definition mp_serial.c:54
void ser_exit(int fd)
Definition mp_serial.c:182
int init_serial(const char *dev, int speed, int debug)
Definition mp_serial.c:58