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