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