FlightGear next
ATC-Main.cxx
Go to the documentation of this file.
1// ATC-Main.cxx -- FGFS interface to ATC hardware
2//
3// Written by Curtis Olson, started January 2002
4//
5// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20//
21// $Id$
22
23
24#ifdef HAVE_CONFIG_H
25# include <config.h>
26#endif
27
28#include <simgear/compiler.h>
29
30#include <stdlib.h> // atoi() atof() abs()
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <errno.h>
35
36#include <stdio.h> //snprintf
37#ifdef _WIN32
38# include <io.h> //lseek, read, write
39#endif
40
41#include <string>
42
43#include <simgear/debug/logstream.hxx>
44#include <simgear/props/props_io.hxx>
45#include <simgear/io/iochannel.hxx>
46#include <simgear/math/sg_types.hxx>
47#include <simgear/misc/sg_path.hxx>
48#include <simgear/props/props.hxx>
49#include <simgear/structure/exception.hxx>
50
52#include <Main/fg_props.hxx>
53#include <Main/globals.hxx>
54
55#include "ATC-Main.hxx"
56
57using std::string;
58using std::cout;
59using std::endl;
60using std::vector;
61
62// Lock the ATC hardware
63static int fgATCMainLock( int fd ) {
64 // rewind
65 lseek( fd, 0, SEEK_SET );
66
67 char tmp[2];
68 int result = read( fd, tmp, 1 );
69 if ( result != 1 ) {
70 SG_LOG( SG_IO, SG_DEBUG, "Lock failed" );
71 }
72
73 return result;
74}
75
76
77// Write a radios command
78static int fgATCMainRelease( int fd ) {
79 // rewind
80 lseek( fd, 0, SEEK_SET );
81
82 char tmp[2];
83 tmp[0] = tmp[1] = 0;
84 int result = write( fd, tmp, 1 );
85
86 if ( result != 1 ) {
87 SG_LOG( SG_IO, SG_DEBUG, "Release failed" );
88 }
89
90 return result;
91}
92
93
95#if defined( unix ) || defined( __CYGWIN__ )
96 // Next check home directory for .fgfsrc.hostname file
97 SGPath atcsim_config = SGPath::home();
98 atcsim_config.append( ".fgfs-atc610x.xml" );
99 try {
100 SG_LOG(SG_NETWORK, SG_ALERT,
101 "Warning: loading deprecated config file: " << atcsim_config);
102 readProperties( atcsim_config, globals->get_props() );
103 } catch (const sg_exception &e) {
104 // fail silently, this is an old style config file I want to continue
105 // to support if it exists.
106 }
107
108#endif
109}
110
111
112// Open and initialize ATC hardware
114 if ( is_enabled() ) {
115 SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel "
116 << "is already in use, ignoring" );
117 return false;
118 }
119
120 SG_LOG( SG_IO, SG_ALERT,
121 "Initializing ATC hardware, please wait ..." );
122
123 // This loads the config parameters generated by "simcal"
124 init_config();
125
127 // Open the /proc files
129
130 string lock0_file = "/proc/atcflightsim/board0/lock";
131 string lock1_file = "/proc/atcflightsim/board1/lock";
132
133 lock0_fd = ::open( lock0_file.c_str(), O_RDWR );
134 if ( lock0_fd == -1 ) {
135 SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
136 char msg[256];
137 snprintf( msg, 256, "Error opening %s", lock0_file.c_str() );
138 perror( msg );
139 exit( -1 );
140 }
141
142 lock1_fd = ::open( lock1_file.c_str(), O_RDWR );
143 if ( lock1_fd == -1 ) {
144 SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
145 char msg[256];
146 snprintf( msg, 256, "Error opening %s", lock1_file.c_str() );
147 perror( msg );
148 exit( -1 );
149 }
150
151 if ( !input0_path.isNull() ) {
152 input0 = new FGATCInput( 0, input0_path );
153 input0->open();
154 }
155 if ( !input1_path.isNull() ) {
156 input1 = new FGATCInput( 1, input1_path );
157 input1->open();
158 }
159 if ( !output0_path.isNull() ) {
160 output0 = new FGATCOutput( 0, output0_path );
161 output0->open( lock0_fd );
162 }
163 if ( !output1_path.isNull() ) {
164 output1 = new FGATCOutput( 1, output1_path );
165 output1->open( lock1_fd );
166 }
167
168 set_hz( 30 ); // default to processing requests @ 30Hz
169 set_enabled( true );
170
172 // Finished initing hardware
174
175 SG_LOG( SG_IO, SG_ALERT,
176 "Done initializing ATC hardware." );
177
178 return true;
179}
180
181
183 // cout << "Main::process()\n";
184
185 bool board0_locked = false;
186 bool board1_locked = false;
187
188 if ( input0 != NULL || output0 != NULL ) {
189 // Lock board0 if we have a configuration for it
190 if ( fgATCMainLock( lock0_fd ) > 0 ) {
191 board0_locked = true;
192 }
193 }
194
195 if ( input1 != NULL || output1 != NULL ) {
196 // Lock board1 if we have a configuration for it
197 if ( fgATCMainLock( lock1_fd ) > 0 ) {
198 board1_locked = true;
199 }
200 }
201
202 // cout << " locks: ";
203 // if ( board0_locked ) { cout << "board0 "; }
204 // if ( board1_locked ) { cout << "board1 "; }
205 // cout << endl;
206
207 // process the ATC inputs
208 if ( input0 != NULL && board0_locked ) {
209 input0->process();
210 }
211 if ( input1 != NULL && board1_locked ) {
212 input1->process();
213 }
214
215 // run our custom nasal script. This is a layer above the raw
216 // hardware inputs. It handles situations where there isn't a
217 // direct 1-1 linear mapping between ATC functionality and FG
218 // functionality, and handles situations where FG expects more
219 // functionality from the interface than the ATC hardware can
220 // directly provide.
221
222 auto n = globals->get_subsystem<FGNasalSys>();
223 bool result = n->parseAndRun( "atcsim.update()" );
224 if ( !result ) {
225 SG_LOG( SG_NETWORK, SG_ALERT, "Nasal: atcsim.update() failed!" );
226 }
227
228 // process the ATC outputs
229 if ( output0 != NULL && board0_locked ) {
230 output0->process();
231 }
232 if ( output1 != NULL && board1_locked ) {
233 output1->process();
234 }
235
236 if ( board0_locked ) {
237 fgATCMainRelease( lock0_fd );
238 }
239 if ( board1_locked ) {
240 fgATCMainRelease( lock1_fd );
241 }
242
243 return true;
244}
245
246
248 cout << "FGATCMain::close()" << endl;
249
250 int result;
251
252 if ( input0 != NULL ) {
253 input0->close();
254 }
255 if ( input1 != NULL ) {
256 input1->close();
257 }
258 if ( output0 != NULL ) {
259 output0->close();
260 }
261 if ( output1 != NULL ) {
262 output1->close();
263 }
264
265 result = ::close( lock0_fd );
266 if ( result == -1 ) {
267 SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
268 char msg[256];
269 snprintf( msg, 256, "Error closing lock0_fd" );
270 perror( msg );
271 exit( -1 );
272 }
273
274 result = ::close( lock1_fd );
275 if ( result == -1 ) {
276 SG_LOG( SG_IO, SG_ALERT, "errno = " << errno );
277 char msg[256];
278 snprintf( msg, 256, "Error closing lock1_fd" );
279 perror( msg );
280 exit( -1 );
281 }
282
283 return true;
284}
static int fgATCMainRelease(int fd)
Definition ATC-Main.cxx:78
static int fgATCMainLock(int fd)
Definition ATC-Main.cxx:63
void init_config()
Definition ATC-Main.cxx:94
bool process()
Definition ATC-Main.cxx:182
bool open()
Definition ATC-Main.cxx:113
bool close()
Definition ATC-Main.cxx:247
bool parseAndRun(const std::string &source)
Definition NasalSys.cxx:388
void set_hz(double t)
Definition protocol.hxx:69
void set_enabled(const bool b)
Definition protocol.hxx:88
bool is_enabled() const
Definition protocol.hxx:87
FGGlobals * globals
Definition globals.cxx:142