]> git.mxchange.org Git - flightgear.git/blob - src/Main/fg_io.cxx
Added a specific "altas" format for output which includes a proprietary string
[flightgear.git] / src / Main / fg_io.cxx
1 // fg_io.cxx -- higher level I/O channel management routines
2 //
3 // Written by Curtis Olson, started November 1999.
4 //
5 // Copyright (C) 1999  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
23
24 #include <simgear/compiler.h>
25
26 #include STL_STRING
27
28 #include <simgear/debug/logstream.hxx>
29 #include <simgear/io/iochannel.hxx>
30 #include <simgear/io/sg_file.hxx>
31 #include <simgear/io/sg_serial.hxx>
32 #include <simgear/io/sg_socket.hxx>
33 #include <simgear/math/sg_types.hxx>
34 #include <simgear/timing/timestamp.hxx>
35
36 #include <Network/protocol.hxx>
37 #include <Network/atlas.hxx>
38 #include <Network/garmin.hxx>
39 #include <Network/joyclient.hxx>
40 #include <Network/native.hxx>
41 #include <Network/nmea.hxx>
42 #include <Network/props.hxx>
43 #include <Network/pve.hxx>
44 #include <Network/ray.hxx>
45 #include <Network/rul.hxx>
46
47 #include "globals.hxx"
48
49 FG_USING_STD(string);
50
51
52 // define the global I/O channel list
53 io_container global_io_list;
54
55
56 // configure a port based on the config string
57 static FGProtocol *parse_port_config( const string& config )
58 {
59     string::size_type begin, end;
60
61     begin = 0;
62
63     FG_LOG( FG_IO, FG_INFO, "Parse I/O channel request: " << config );
64
65     // determine protocol
66     end = config.find(",", begin);
67     if ( end == string::npos ) {
68         return NULL;            // dummy
69     }
70     
71     string protocol = config.substr(begin, end - begin);
72     begin = end + 1;
73     FG_LOG( FG_IO, FG_INFO, "  protocol = " << protocol );
74
75     FGProtocol *io;
76     if ( protocol == "atlas" ) {
77         FGAtlas *atlas = new FGAtlas;
78         io = atlas;
79     } else if ( protocol == "garmin" ) {
80         FGGarmin *garmin = new FGGarmin;
81         io = garmin;
82     } else if ( protocol == "joyclient" ) {
83         FGJoyClient *joyclient = new FGJoyClient;
84         io = joyclient;
85     } else if ( protocol == "native" ) {
86         FGNative *native = new FGNative;
87         io = native;
88     } else if ( protocol == "nmea" ) {
89         FGNMEA *nmea = new FGNMEA;
90         io = nmea;
91     } else if ( protocol == "props" ) {
92         FGProps *props = new FGProps;
93         io = props;
94     } else if ( protocol == "pve" ) {
95         FGPVE *pve = new FGPVE;
96         io = pve;
97     } else if ( protocol == "ray" ) {
98         FGRAY *ray = new FGRAY;
99         io = ray;
100     } else if ( protocol == "rul" ) {
101         FGRUL *rul = new FGRUL;
102         io = rul;
103     } else {
104         return NULL;
105     }
106
107     // determine medium
108     end = config.find(",", begin);
109     if ( end == string::npos ) {
110         return NULL;            // dummy
111     }
112     
113     string medium = config.substr(begin, end - begin);
114     begin = end + 1;
115     FG_LOG( FG_IO, FG_INFO, "  medium = " << medium );
116
117     // determine direction
118     end = config.find(",", begin);
119     if ( end == string::npos ) {
120         return NULL;            // dummy
121     }
122     
123     string direction = config.substr(begin, end - begin);
124     begin = end + 1;
125     io->set_direction( direction );
126     FG_LOG( FG_IO, FG_INFO, "  direction = " << direction );
127
128     // determine hertz
129     end = config.find(",", begin);
130     if ( end == string::npos ) {
131         return NULL;            // dummy
132     }
133     
134     string hertz_str = config.substr(begin, end - begin);
135     begin = end + 1;
136     double hertz = atof( hertz_str.c_str() );
137     io->set_hz( hertz );
138     FG_LOG( FG_IO, FG_INFO, "  hertz = " << hertz );
139
140     if ( medium == "serial" ) {
141         // device name
142         end = config.find(",", begin);
143         if ( end == string::npos ) {
144             return NULL;
145         }
146     
147         string device = config.substr(begin, end - begin);
148         begin = end + 1;
149         FG_LOG( FG_IO, FG_INFO, "  device = " << device );
150
151         // baud
152         string baud = config.substr(begin);
153         FG_LOG( FG_IO, FG_INFO, "  baud = " << baud );
154
155         SGSerial *ch = new SGSerial( device, baud );
156         io->set_io_channel( ch );
157     } else if ( medium == "file" ) {
158         // file name
159         string file = config.substr(begin);
160         FG_LOG( FG_IO, FG_INFO, "  file name = " << file );
161
162         SGFile *ch = new SGFile( file );
163         io->set_io_channel( ch );
164     } else if ( medium == "socket" ) {
165         // hostname
166         end = config.find(",", begin);
167         if ( end == string::npos ) {
168             return NULL;
169         }
170     
171         string hostname = config.substr(begin, end - begin);
172         begin = end + 1;
173         FG_LOG( FG_IO, FG_INFO, "  hostname = " << hostname );
174
175         // port string
176         end = config.find(",", begin);
177         if ( end == string::npos ) {
178             return NULL;
179         }
180     
181         string port = config.substr(begin, end - begin);
182         begin = end + 1;
183         FG_LOG( FG_IO, FG_INFO, "  port string = " << port );
184
185         // socket style
186         string style_str = config.substr(begin);
187         FG_LOG( FG_IO, FG_INFO, "  style string = " << style_str );
188        
189         SGSocket *ch = new SGSocket( hostname, port, style_str );
190         io->set_io_channel( ch );
191     }
192
193     return io;
194 }
195
196
197 // step through the port config streams (from fgOPTIONS) and setup
198 // serial port channels for each
199 void fgIOInit() {
200     // FG_LOG( FG_IO, FG_INFO, "I/O Channel initialization, " << 
201     //         globals->get_channel_options_list()->size() << " requests." );
202
203     FGProtocol *p;
204     string_list *channel_options_list = globals->get_channel_options_list();
205
206     // we could almost do this in a single step except pushing a valid
207     // port onto the port list copies the structure and destroys the
208     // original, which closes the port and frees up the fd ... doh!!!
209
210     // parse the configuration strings and store the results in the
211     // appropriate FGIOChannel structures
212     for ( int i = 0; i < (int)channel_options_list->size(); ++i ) {
213         p = parse_port_config( (*channel_options_list)[i] );
214         if ( p != NULL ) {
215             p->open();
216             global_io_list.push_back( p );
217             if ( !p->is_enabled() ) {
218                 FG_LOG( FG_IO, FG_ALERT, "I/O Channel config failed." );
219                 exit(-1);
220             }
221         } else {
222             FG_LOG( FG_IO, FG_INFO, "I/O Channel parse failed." );
223         }
224     }
225 }
226
227
228 // process any serial port work
229 void fgIOProcess() {
230     FGProtocol *p;
231
232     // cout << "processing I/O channels" << endl;
233
234     static int inited = 0;
235     int interval;
236     static SGTimeStamp last;
237     SGTimeStamp current;
238
239     if ( ! inited ) {
240         inited = 1;
241         last.stamp();
242         interval = 0;
243     } else {
244         current.stamp();
245         interval = current - last;
246         last = current;
247     }
248
249     for ( int i = 0; i < (int)global_io_list.size(); ++i ) {
250         // cout << "  channel = " << i << endl;
251         p = global_io_list[i];
252
253         if ( p->is_enabled() ) {
254             p->dec_count_down( interval );
255             while ( p->get_count_down() < 0 ) {
256                 p->process();
257                 p->dec_count_down( -1000000.0 / p->get_hz() );
258             }
259         }
260     }
261 }
262
263
264 // shutdown all I/O connections
265 void fgIOShutdownAll() {
266     FGProtocol *p;
267
268     // cout << "processing I/O channels" << endl;
269
270     for ( int i = 0; i < (int)global_io_list.size(); ++i ) {
271         // cout << "  channel = " << i << endl;
272         p = global_io_list[i];
273
274         if ( p->is_enabled() ) {
275             p->close();
276         }
277     }
278 }