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