]> git.mxchange.org Git - flightgear.git/blob - src/Main/fg_io.cxx
Code reorganization.
[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/logstream.hxx>
29 #include <simgear/fg_types.hxx>
30
31 #include <Main/options.hxx>
32
33 #include <Network/iochannel.hxx>
34 #include <Network/fg_file.hxx>
35 #include <Network/fg_serial.hxx>
36 #include <Network/fg_socket.hxx>
37
38 #include <Network/protocol.hxx>
39 #include <Network/native.hxx>
40 #include <Network/garmin.hxx>
41 #include <Network/nmea.hxx>
42 #include <Network/pve.hxx>
43 #include <Network/rul.hxx>
44
45 #include <Time/timestamp.hxx>
46
47 FG_USING_STD(string);
48
49
50 // define the global I/O channel list
51 io_container global_io_list;
52
53
54 // configure a port based on the config string
55 static FGProtocol *parse_port_config( const string& config )
56 {
57     string::size_type begin, end;
58
59     begin = 0;
60
61     FG_LOG( FG_IO, FG_INFO, "Parse I/O channel request: " << config );
62
63     // determine protocol
64     end = config.find(",", begin);
65     if ( end == string::npos ) {
66         return NULL;            // dummy
67     }
68     
69     string protocol = config.substr(begin, end - begin);
70     begin = end + 1;
71     FG_LOG( FG_IO, FG_INFO, "  protocol = " << protocol );
72
73     FGProtocol *io;
74     if ( protocol == "native" ) {
75         FGNative *native = new FGNative;
76         io = native;
77     } else if ( protocol == "garmin" ) {
78         FGGarmin *garmin = new FGGarmin;
79         io = garmin;
80     } else if ( protocol == "nmea" ) {
81         FGNMEA *nmea = new FGNMEA;
82         io = nmea;
83     } else if ( protocol == "pve" ) {
84         FGPVE *pve = new FGPVE;
85         io = pve;
86     } else if ( protocol == "rul" ) {
87         FGRUL *rul = new FGRUL;
88         io = rul;
89     } else {
90         return NULL;
91     }
92
93     // determine medium
94     end = config.find(",", begin);
95     if ( end == string::npos ) {
96         return NULL;            // dummy
97     }
98     
99     string medium = config.substr(begin, end - begin);
100     begin = end + 1;
101     FG_LOG( FG_IO, FG_INFO, "  medium = " << medium );
102
103     // determine direction
104     end = config.find(",", begin);
105     if ( end == string::npos ) {
106         return NULL;            // dummy
107     }
108     
109     string direction = config.substr(begin, end - begin);
110     begin = end + 1;
111     io->set_direction( direction );
112     FG_LOG( FG_IO, FG_INFO, "  direction = " << direction );
113
114     // determine hertz
115     end = config.find(",", begin);
116     if ( end == string::npos ) {
117         return NULL;            // dummy
118     }
119     
120     string hertz_str = config.substr(begin, end - begin);
121     begin = end + 1;
122     double hertz = atof( hertz_str.c_str() );
123     io->set_hz( hertz );
124     FG_LOG( FG_IO, FG_INFO, "  hertz = " << hertz );
125
126     if ( medium == "serial" ) {
127         FGSerial *ch = new FGSerial;
128         io->set_io_channel( ch );
129
130         // device name
131         end = config.find(",", begin);
132         if ( end == string::npos ) {
133             return NULL;
134         }
135     
136         ch->set_device( config.substr(begin, end - begin) );
137         begin = end + 1;
138         FG_LOG( FG_IO, FG_INFO, "  device = " << ch->get_device() );
139
140         // baud
141         ch->set_baud( config.substr(begin) );
142         FG_LOG( FG_IO, FG_INFO, "  baud = " << ch->get_baud() );
143
144         io->set_io_channel( ch );
145     } else if ( medium == "file" ) {
146         FGFile *ch = new FGFile;
147         io->set_io_channel( ch );
148
149         // file name
150         ch->set_file_name( config.substr(begin) );
151         FG_LOG( FG_IO, FG_INFO, "  file name = " << ch->get_file_name() );
152     } else if ( medium == "socket" ) {
153         FGSocket *ch = new FGSocket;
154         io->set_io_channel( ch );
155
156         // hostname
157         end = config.find(",", begin);
158         if ( end == string::npos ) {
159             return NULL;
160         }
161     
162         ch->set_hostname( config.substr(begin, end - begin) );
163         begin = end + 1;
164         FG_LOG( FG_IO, FG_INFO, "  hostname = " << ch->get_hostname() );
165
166         // port
167         ch->set_port_str( config.substr(begin) );
168         FG_LOG( FG_IO, FG_INFO, "  port string = " << ch->get_port_str() );
169
170     }
171
172     return io;
173 }
174
175
176 // step through the port config streams (from fgOPTIONS) and setup
177 // serial port channels for each
178 void fgIOInit() {
179     FGProtocol *p;
180     string_list channel_options_list = 
181         current_options.get_channel_options_list();
182
183     // we could almost do this in a single step except pushing a valid
184     // port onto the port list copies the structure and destroys the
185     // original, which closes the port and frees up the fd ... doh!!!
186
187     // parse the configuration strings and store the results in the
188     // appropriate FGIOChannel structures
189     for ( int i = 0; i < (int)channel_options_list.size(); ++i ) {
190         p = parse_port_config( channel_options_list[i] );
191         if ( p != NULL ) {
192             p->open();
193             global_io_list.push_back( p );
194             if ( !p->is_enabled() ) {
195                 FG_LOG( FG_IO, FG_INFO, "I/O Channel config failed." );
196             }
197         } else {
198             FG_LOG( FG_IO, FG_INFO, "I/O Channel parse failed." );
199         }
200     }
201 }
202
203
204 // process any serial port work
205 void fgIOProcess() {
206     FGProtocol *p;
207
208     // cout << "processing I/O channels" << endl;
209
210     static int inited = 0;
211     int interval;
212     static FGTimeStamp last;
213     FGTimeStamp current;
214
215     if ( ! inited ) {
216         inited = 1;
217         last.stamp();
218         interval = 0;
219     } else {
220         current.stamp();
221         interval = current - last;
222         last = current;
223     }
224
225     for ( int i = 0; i < (int)global_io_list.size(); ++i ) {
226         // cout << "  channel = " << i << endl;
227         p = global_io_list[i];
228
229         if ( p->is_enabled() ) {
230             p->dec_count_down( interval );
231             if ( p->get_count_down() < 0 ) {
232                 p->process();
233                 p->set_count_down( 1000000.0 / p->get_hz() );
234             }
235         }
236     }
237 }