]> git.mxchange.org Git - simgear.git/blob - Serial/serial.cxx
Tweaked FDM interface.
[simgear.git] / Serial / serial.cxx
1 // serial.cxx -- Unix serial I/O support
2 //
3 // Written by Curtis Olson, started November 1998.
4 //
5 // Copyright (C) 1998  Curtis L. Olson - curt@flightgear.org
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22 // (Log is kept at end of this file)
23
24
25 #include <errno.h>
26 #include <termios.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31
32 #include <Debug/logstream.hxx>
33
34 #include "serial.hxx"
35
36
37 fgSERIAL::fgSERIAL() {
38     dev_open = false;
39 }
40
41 fgSERIAL::fgSERIAL(const string& device, int baud) {
42     open_port(device);
43     
44     if ( dev_open ) {
45         set_baud(baud);
46     }
47 }
48
49 fgSERIAL::~fgSERIAL() {
50     // closing the port here screws us up because if we would even so
51     // much as make a copy of an fgSERIAL object and then delete it,
52     // the file descriptor gets closed.  Doh!!!
53
54     // close(fd);
55 }
56
57 bool fgSERIAL::open_port(const string& device) {
58     struct termios config;
59
60     fd = open(device.c_str(), O_RDWR | O_NONBLOCK);
61     cout << "Serial fd created = " << fd << endl;
62
63     if ( fd  == -1 ) {
64         FG_LOG( FG_SERIAL, FG_ALERT, "Cannot open " << device
65                 << " for serial I/O" );
66         return false;
67     } else {
68         dev_open = true;
69     }
70
71     // set required port parameters 
72     if ( tcgetattr( fd, &config ) != 0 ) {
73         FG_LOG( FG_SERIAL, FG_ALERT, "Unable to poll port settings" );
74         return false;
75     }
76
77     // cfmakeraw( &config );
78
79     // cout << "config.c_iflag = " << config.c_iflag << endl;
80
81     // software flow control on
82     config.c_iflag |= IXON;
83     // config.c_iflag |= IXOFF;
84
85     // config.c_cflag |= CLOCAL;
86
87 #if ! defined( sgi )    
88     // disable hardware flow control
89     config.c_cflag &= ~(CRTSCTS);
90 #endif
91
92     // cout << "config.c_iflag = " << config.c_iflag << endl;
93
94     if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
95         FG_LOG( FG_SERIAL, FG_ALERT, "Unable to update port settings" );
96         return false;
97     }
98
99     return true;
100 }
101
102
103 bool fgSERIAL::close_port() {
104     close(fd);
105     return true;
106 }
107
108
109 bool fgSERIAL::set_baud(int baud) {
110     struct termios config;
111     speed_t speed = B9600;
112
113     if ( tcgetattr( fd, &config ) != 0 ) {
114         FG_LOG( FG_SERIAL, FG_ALERT, "Unable to poll port settings" );
115         return false;
116     }
117
118     if ( baud == 300 ) {
119         speed = B300;
120     } else if ( baud == 1200 ) {
121         speed = B1200;
122     } else if ( baud == 2400 ) {
123         speed = B2400;
124     } else if ( baud == 4800 ) {
125         speed = B4800;
126     } else if ( baud == 9600 ) {
127         speed = B9600;
128     } else if ( baud == 19200 ) {
129         speed = B19200;
130     } else if ( baud == 38400 ) {
131         speed = B38400;
132     } else if ( baud == 57600 ) {
133         speed = B57600;
134     } else if ( baud == 115200 ) {
135         speed = B115200;
136 #if defined( linux ) || defined( __FreeBSD__ )
137     } else if ( baud == 230400 ) {
138         speed = B230400;
139 #endif
140     } else {
141         FG_LOG( FG_SERIAL, FG_ALERT, "Unsupported baud rate " << baud );
142         return false;
143     }
144
145     if ( cfsetispeed( &config, speed ) != 0 ) {
146         FG_LOG( FG_SERIAL, FG_ALERT, "Problem setting input baud rate" );
147         return false;
148     }
149
150     if ( cfsetospeed( &config, speed ) != 0 ) {
151         FG_LOG( FG_SERIAL, FG_ALERT, "Problem setting output baud rate" );
152         return false;
153     }
154
155     if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
156         FG_LOG( FG_SERIAL, FG_ALERT, "Unable to update port settings" );
157         return false;
158     }
159
160     return true;
161 }
162
163 string fgSERIAL::read_port() {
164     const int max_count = 1024;
165     char buffer[max_count+1];
166     int count;
167     string result;
168
169     count = read(fd, buffer, max_count);
170     // cout << "read " << count << " bytes" << endl;
171
172     if ( count < 0 ) {
173         // error condition
174         if ( errno != EAGAIN ) {
175             FG_LOG( FG_SERIAL, FG_ALERT, 
176                     "Serial I/O on read, error number = " << errno );
177         }
178
179         return "";
180     } else {
181         buffer[count] = '\0';
182         result = buffer;
183
184         return result;
185     }
186 }
187
188 int fgSERIAL::write_port(const string& value) {
189     static bool error = false;
190     int count;
191
192     if ( error ) {
193         // attempt some sort of error recovery
194         count = write(fd, "\n", 1);
195         if ( count == 1 ) {
196             // cout << "Serial error recover successful!\n";
197             error = false;
198         } else {
199             return 0;
200         }
201     }
202
203     count = write(fd, value.c_str(), value.length());
204     // cout << "write '" << value << "'  " << count << " bytes" << endl;
205
206     if ( (int)count == (int)value.length() ) {
207         error = false;
208     } else {
209         error = true;
210         if ( errno == EAGAIN ) {
211             // ok ... in our context we don't really care if we can't
212             // write a string, we'll just get it the next time around
213         } else {
214             FG_LOG( FG_SERIAL, FG_ALERT,
215                     "Serial I/O on write, error number = " << errno );
216         }
217     }
218
219     return count;
220 }
221
222
223 // $Log$
224 // Revision 1.8  1999/01/20 13:42:21  curt
225 // Tweaked FDM interface.
226 // Testing check sum support for NMEA serial output.
227 //
228 // Revision 1.7  1998/12/04 01:24:35  curt
229 // Tweak for SGI portability.
230 //
231 // Revision 1.6  1998/11/30 17:15:29  curt
232 // Having the class destructor close the fd was a bad idea ... especially if you
233 // ever make a copy of the instance and then subsequently destroy either.
234 // close_port() is now a separate member function.
235 //
236 // Revision 1.5  1998/11/25 01:33:23  curt
237 // Remove call to cfmakeraw()
238 //
239 // Revision 1.4  1998/11/23 21:47:00  curt
240 // Cygnus tools compatibility tweaks.
241 //
242 // Revision 1.3  1998/11/19 13:52:54  curt
243 // port configuration tweaks & experiments.
244 //
245 // Revision 1.2  1998/11/19 03:35:43  curt
246 // Updates ...
247 //
248 // Revision 1.1  1998/11/16 13:53:02  curt
249 // Initial revision.
250 //