1 // serial.cxx -- Unix serial I/O support
3 // Written by Curtis Olson, started November 1998.
5 // Copyright (C) 1998 Curtis L. Olson - curt@flightgear.org
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.
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.
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.
28 #include "Include/compiler.h"
29 #ifdef FG_HAVE_STD_INCLUDE
35 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
36 // maybe include something???
39 # include <sys/types.h>
40 # include <sys/stat.h>
45 #include <Debug/logstream.hxx>
56 fgSERIAL::fgSERIAL(const string& device, int baud) {
64 fgSERIAL::~fgSERIAL() {
65 // closing the port here screws us up because if we would even so
66 // much as make a copy of an fgSERIAL object and then delete it,
67 // the file descriptor gets closed. Doh!!!
70 bool fgSERIAL::open_port(const string& device) {
72 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
74 fd = CreateFile( device.c_str(),
75 GENERIC_READ | GENERIC_WRITE,
77 NULL, // lpSecurityAttributes
81 if ( fd == INVALID_HANDLE_VALUE )
85 FORMAT_MESSAGE_ALLOCATE_BUFFER |
86 FORMAT_MESSAGE_FROM_SYSTEM |
87 FORMAT_MESSAGE_IGNORE_INSERTS,
90 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
95 FG_LOG( FG_SERIAL, FG_ALERT, "Error opening serial device \""
96 << device << "\" " << (const char*) lpMsgBuf );
97 LocalFree( lpMsgBuf );
106 struct termios config;
108 fd = open(device.c_str(), O_RDWR | O_NONBLOCK);
109 cout << "Serial fd created = " << fd << endl;
112 FG_LOG( FG_SERIAL, FG_ALERT, "Cannot open " << device
113 << " for serial I/O" );
119 // set required port parameters
120 if ( tcgetattr( fd, &config ) != 0 ) {
121 FG_LOG( FG_SERIAL, FG_ALERT, "Unable to poll port settings" );
125 // cfmakeraw( &config );
127 // cout << "config.c_iflag = " << config.c_iflag << endl;
129 // software flow control on
130 config.c_iflag |= IXON;
131 // config.c_iflag |= IXOFF;
133 // config.c_cflag |= CLOCAL;
136 // disable hardware flow control
137 config.c_cflag &= ~(CRTSCTS);
140 // cout << "config.c_iflag = " << config.c_iflag << endl;
142 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
143 FG_LOG( FG_SERIAL, FG_ALERT, "Unable to update port settings" );
152 bool fgSERIAL::close_port() {
153 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
163 bool fgSERIAL::set_baud(int baud) {
165 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
171 struct termios config;
172 speed_t speed = B9600;
174 if ( tcgetattr( fd, &config ) != 0 ) {
175 FG_LOG( FG_SERIAL, FG_ALERT, "Unable to poll port settings" );
181 } else if ( baud == 1200 ) {
183 } else if ( baud == 2400 ) {
185 } else if ( baud == 4800 ) {
187 } else if ( baud == 9600 ) {
189 } else if ( baud == 19200 ) {
191 } else if ( baud == 38400 ) {
193 } else if ( baud == 57600 ) {
195 } else if ( baud == 115200 ) {
197 #if defined( linux ) || defined( __FreeBSD__ )
198 } else if ( baud == 230400 ) {
202 FG_LOG( FG_SERIAL, FG_ALERT, "Unsupported baud rate " << baud );
206 if ( cfsetispeed( &config, speed ) != 0 ) {
207 FG_LOG( FG_SERIAL, FG_ALERT, "Problem setting input baud rate" );
211 if ( cfsetospeed( &config, speed ) != 0 ) {
212 FG_LOG( FG_SERIAL, FG_ALERT, "Problem setting output baud rate" );
216 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
217 FG_LOG( FG_SERIAL, FG_ALERT, "Unable to update port settings" );
227 string fgSERIAL::read_port() {
229 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
236 const int max_count = 1024;
237 char buffer[max_count+1];
241 count = read(fd, buffer, max_count);
242 // cout << "read " << count << " bytes" << endl;
246 if ( errno != EAGAIN ) {
247 FG_LOG( FG_SERIAL, FG_ALERT,
248 "Serial I/O on read, error number = " << errno );
253 buffer[count] = '\0';
263 int fgSERIAL::write_port(const string& value) {
265 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
267 LPCVOID lpBuffer = value.c_str();
268 DWORD nNumberOfBytesToWrite = value.length();
269 DWORD lpNumberOfBytesWritten;
270 OVERLAPPED lpOverlapped;
274 nNumberOfBytesToWrite,
275 &lpNumberOfBytesWritten,
276 &lpOverlapped ) == 0 )
280 FORMAT_MESSAGE_ALLOCATE_BUFFER |
281 FORMAT_MESSAGE_FROM_SYSTEM |
282 FORMAT_MESSAGE_IGNORE_INSERTS,
285 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
290 FG_LOG( FG_SERIAL, FG_ALERT, "Serial I/O write error: "
291 << (const char*) lpMsgBuf );
292 LocalFree( lpMsgBuf );
293 return int(lpNumberOfBytesWritten);
296 return int(lpNumberOfBytesWritten);
300 static bool error = false;
304 // attempt some sort of error recovery
305 count = write(fd, "\n", 1);
307 // cout << "Serial error recover successful!\n";
314 count = write(fd, value.c_str(), value.length());
315 // cout << "write '" << value << "' " << count << " bytes" << endl;
317 if ( (int)count == (int)value.length() ) {
321 if ( errno == EAGAIN ) {
322 // ok ... in our context we don't really care if we can't
323 // write a string, we'll just get it the next time around
325 FG_LOG( FG_SERIAL, FG_ALERT,
326 "Serial I/O on write, error number = " << errno );