source: ntrip/trunk/ntripclient/serial.c@ 971

Last change on this file since 971 was 834, checked in by stoecker, 17 years ago

added support for serial output

File size: 8.6 KB
RevLine 
[834]1/*
2 Serial port access for NTRIP client for POSIX.
3 $Id$
4 Copyright (C) 2008 by Dirk Stöcker <soft@dstoecker.de>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 or read http://www.gnu.org/licenses/gpl.txt
20*/
21
22/* system includes */
23#include <stdio.h>
24#include <string.h>
25
26#ifndef WINDOWSVERSION
27#include <errno.h>
28#include <fcntl.h>
29#include <string.h>
30#include <termios.h>
31#include <unistd.h>
32#define SERIALDEFAULTDEVICE "/dev/ttyS0"
33enum SerialBaud {
34 SPABAUD_50 = B50, SPABAUD_110 = B110, SPABAUD_300 = B300, SPABAUD_600 = B600,
35 SPABAUD_1200 = B1200, SPABAUD_2400 = B2400, SPABAUD_4800 = B4800,
36 SPABAUD_9600 = B9600, SPABAUD_19200 = B19200,
37 SPABAUD_38400 = B38400, SPABAUD_57600 = B57600, SPABAUD_115200 = B115200 };
38enum SerialDatabits {
39 SPADATABITS_5 = CS5, SPADATABITS_6 = CS6, SPADATABITS_7 = CS7, SPADATABITS_8 = CS8 };
40enum SerialStopbits {
41 SPASTOPBITS_1 = 0, SPASTOPBITS_2 = CSTOPB };
42enum SerialParity {
43 SPAPARITY_NONE = 0, SPAPARITY_ODD = PARODD | PARENB, SPAPARITY_EVEN = PARENB };
44enum SerialProtocol {
45 SPAPROTOCOL_NONE = 0, SPAPROTOCOL_RTS_CTS = 9999,
46 SPAPROTOCOL_XON_XOFF = IXOFF | IXON };
47
48struct serial
49{
50 struct termios Termios;
51 int Stream;
52};
53#else /* WINDOWSVERSION */
54#include <windows.h>
55#define SERIALDEFAULTDEVICE "COM1"
56enum SerialBaud {
57 SPABAUD_50 = 50, SPABAUD_110 = 110, SPABAUD_300 = 300, SPABAUD_600 = 600,
58 SPABAUD_1200 = 1200, SPABAUD_2400 = 2400, SPABAUD_4800 = 4800,
59 SPABAUD_9600 = 9600, SPABAUD_19200 = 19200,
60 SPABAUD_38400 = 38400, SPABAUD_57600 = 57600, SPABAUD_115200 = 115200 };
61enum SerialDatabits {
62 SPADATABITS_5 = 5, SPADATABITS_6 = 6, SPADATABITS_7 = 7, SPADATABITS_8 = 8 };
63enum SerialStopbits {
64 SPASTOPBITS_1 = 1, SPASTOPBITS_2 = 2 };
65enum SerialParity {
66 SPAPARITY_NONE = 'N', SPAPARITY_ODD = 'O', SPAPARITY_EVEN = 'E'};
67enum SerialProtocol {
68 SPAPROTOCOL_NONE, SPAPROTOCOL_RTS_CTS, SPAPROTOCOL_XON_XOFF};
69
70struct serial
71{
72 DCB Termios;
73 HANDLE Stream;
74};
75#if !defined(__GNUC__)
76int strncasecmp(const char *a, const char *b, int len)
77{
78 while(len-- && *a && tolower(*a) == tolower(*b))
79 {
80 ++a; ++b;
81 }
82 return len ? (tolower(*a) - tolower(*b)) : 0;
83}
84#endif /* !__GNUC__ */
85
86#endif /* WINDOWSVERSION */
87
88static enum SerialParity SerialGetParity(const char *buf, int *ressize)
89{
90 int r = 0;
91 enum SerialParity p = SPAPARITY_NONE;
92 if(!strncasecmp(buf, "none", 4))
93 { r = 4; p = SPAPARITY_NONE; }
94 else if(!strncasecmp(buf, "no", 2))
95 { r = 2; p = SPAPARITY_NONE; }
96 else if(!strncasecmp(buf, "odd", 3))
97 { r = 3; p = SPAPARITY_ODD; }
98 else if(!strncasecmp(buf, "even", 4))
99 { r = 4; p = SPAPARITY_EVEN; }
100 else if(*buf == 'N' || *buf == 'n')
101 { r = 1; p = SPAPARITY_NONE; }
102 else if(*buf == 'O' || *buf == 'o')
103 { r = 1; p = SPAPARITY_ODD; }
104 else if(*buf == 'E' || *buf == 'e')
105 { r = 1; p = SPAPARITY_EVEN; }
106 if(ressize) *ressize = r;
107 return p;
108}
109
110static enum SerialProtocol SerialGetProtocol(const char *buf, int *ressize)
111{
112 int r = 0;
113 enum SerialProtocol Protocol = SPAPROTOCOL_NONE;
114 /* try some possible forms for input, be as gentle as possible */
115 if(!strncasecmp("xonxoff",buf,7)){r = 7; Protocol=SPAPROTOCOL_XON_XOFF;}
116 else if(!strncasecmp("xon_xoff",buf,8)){r = 8; Protocol=SPAPROTOCOL_XON_XOFF;}
117 else if(!strncasecmp("xon-xoff",buf,8)){r = 8; Protocol=SPAPROTOCOL_XON_XOFF;}
118 else if(!strncasecmp("xon xoff",buf,8)){r = 8; Protocol=SPAPROTOCOL_XON_XOFF;}
119 else if(!strncasecmp("xoff",buf,4)){r = 4; Protocol=SPAPROTOCOL_XON_XOFF;}
120 else if(!strncasecmp("xon",buf,3)){r = 3; Protocol=SPAPROTOCOL_XON_XOFF;}
121 else if(*buf == 'x' || *buf == 'X'){r = 1; Protocol=SPAPROTOCOL_XON_XOFF;}
122 else if(!strncasecmp("rtscts",buf,6)){r = 6; Protocol=SPAPROTOCOL_RTS_CTS;}
123 else if(!strncasecmp("rts_cts",buf,7)){r = 7; Protocol=SPAPROTOCOL_RTS_CTS;}
124 else if(!strncasecmp("rts-cts",buf,7)){r = 7; Protocol=SPAPROTOCOL_RTS_CTS;}
125 else if(!strncasecmp("rts cts",buf,7)){r = 7; Protocol=SPAPROTOCOL_RTS_CTS;}
126 else if(!strncasecmp("rts",buf,3)){r = 3; Protocol=SPAPROTOCOL_RTS_CTS;}
127 else if(!strncasecmp("cts",buf,3)){r = 3; Protocol=SPAPROTOCOL_RTS_CTS;}
128 else if(*buf == 'r' || *buf == 'R' || *buf == 'c' || *buf == 'C')
129 {r = 1; Protocol=SPAPROTOCOL_RTS_CTS;}
130 else if(!strncasecmp("none",buf,4)){r = 4; Protocol=SPAPROTOCOL_NONE;}
131 else if(!strncasecmp("no",buf,2)){r = 2; Protocol=SPAPROTOCOL_NONE;}
132 else if(*buf == 'n' || *buf == 'N'){r = 1; Protocol=SPAPROTOCOL_NONE;}
133 if(ressize) *ressize = r;
134 return Protocol;
135}
136
137#ifndef WINDOWSVERSION
138static void SerialFree(struct serial *sn)
139{
140 if(sn->Stream)
141 {
142 /* reset old settings */
143 tcsetattr(sn->Stream, TCSANOW, &sn->Termios);
144 close(sn->Stream);
145 sn->Stream = 0;
146 }
147}
148
149static const char * SerialInit(struct serial *sn,
150const char *Device, enum SerialBaud Baud, enum SerialStopbits StopBits,
151enum SerialProtocol Protocol, enum SerialParity Parity,
152enum SerialDatabits DataBits, int dowrite
153#ifdef __GNUC__
154__attribute__((__unused__))
155#endif /* __GNUC__ */
156)
157{
158 struct termios newtermios;
159
160 if((sn->Stream = open(Device, O_RDWR | O_NOCTTY | O_NONBLOCK)) <= 0)
161 return "could not open serial port";
162 tcgetattr(sn->Stream, &sn->Termios);
163
164 memset(&newtermios, 0, sizeof(struct termios));
165 newtermios.c_cflag = Baud | StopBits | Parity | DataBits
166 | CLOCAL | CREAD;
167 if(Protocol == SPAPROTOCOL_RTS_CTS)
168 newtermios.c_cflag |= CRTSCTS;
169 else
170 newtermios.c_cflag |= Protocol;
171 newtermios.c_cc[VMIN] = 1;
172 tcflush(sn->Stream, TCIOFLUSH);
173 tcsetattr(sn->Stream, TCSANOW, &newtermios);
174 tcflush(sn->Stream, TCIOFLUSH);
175 fcntl(sn->Stream, F_SETFL, O_NONBLOCK);
176 return 0;
177}
178
179static int SerialRead(struct serial *sn, char *buffer, size_t size)
180{
181 int j = read(sn->Stream, buffer, size);
182 if(j < 0)
183 {
184 if(errno == EAGAIN)
185 return 0;
186 else
187 return j;
188 }
189 return j;
190}
191
192static int SerialWrite(struct serial *sn, const char *buffer, size_t size)
193{
194 int j = write(sn->Stream, buffer, size);
195 if(j < 0)
196 {
197 if(errno == EAGAIN)
198 return 0;
199 else
200 return j;
201 }
202 return j;
203}
204
205#else /* WINDOWSVERSION */
206static void SerialFree(struct serial *sn)
207{
208 if(sn->Stream)
209 {
210 SetCommState(sn->Stream, &sn->Termios);
211 /* reset old settings */
212 CloseHandle(sn->Stream);
213 sn->Stream = 0;
214 }
215}
216
217static const char * SerialInit(struct serial *sn, const char *Device,
218enum SerialBaud Baud, enum SerialStopbits StopBits,
219enum SerialProtocol Protocol, enum SerialParity Parity,
220enum SerialDatabits DataBits, int dowrite)
221{
222 char mydevice[50];
223 if(Device[0] != '\\')
224 snprintf(mydevice, sizeof(mydevice), "\\\\.\\%s", Device);
225 else
226 mydevice[0] = 0;
227
228 if((sn->Stream = CreateFile(mydevice[0] ? mydevice : Device,
229 dowrite ? GENERIC_WRITE|GENERIC_READ : GENERIC_READ, 0, 0, OPEN_EXISTING,
230 0, 0)) == INVALID_HANDLE_VALUE)
231 return "could not create file";
232
233 memset(&sn->Termios, 0, sizeof(sn->Termios));
234 GetCommState(sn->Stream, &sn->Termios);
235
236 DCB dcb;
237 memset(&dcb, 0, sizeof(dcb));
238 char str[100];
239 snprintf(str,sizeof(str),
240 "baud=%d parity=%c data=%d stop=%d xon=%s octs=%s rts=%s",
241 Baud, Parity, DataBits, StopBits,
242 Protocol == SPAPROTOCOL_XON_XOFF ? "on" : "off",
243 Protocol == SPAPROTOCOL_RTS_CTS ? "on" : "off",
244 Protocol == SPAPROTOCOL_RTS_CTS ? "on" : "off");
245#ifdef DEBUG
246 fprintf(stderr, "COM Settings: %s\n", str);
247#endif
248
249 COMMTIMEOUTS ct = {MAXDWORD, 0, 0, 0, 0};
250
251 if(!BuildCommDCB(str, &dcb))
252 {
253 CloseHandle(sn->Stream);
254 return "creating device parameters failed";
255 }
256 else if(!SetCommState(sn->Stream, &dcb))
257 {
258 CloseHandle(sn->Stream);
259 return "setting device parameters failed";
260 }
261 else if(!SetCommTimeouts(sn->Stream, &ct))
262 {
263 CloseHandle(sn->Stream);
264 return "setting timeouts failed";
265 }
266
267 return 0;
268}
269
270static int SerialRead(struct serial *sn, char *buffer, size_t size)
271{
272 DWORD j = 0;
273 if(!ReadFile(sn->Stream, buffer, size, &j, 0))
274 return -1;
275 return j;
276}
277
278static int SerialWrite(struct serial *sn, const char *buffer, size_t size)
279{
280 DWORD j = 0;
281 if(!WriteFile(sn->Stream, buffer, size, &j, 0))
282 return -1;
283 return j;
284}
285#endif /* WINDOWSVERSION */
Note: See TracBrowser for help on using the repository browser.