Initial revision
This commit is contained in:
13
Lib/Serial/Makefile.am
Normal file
13
Lib/Serial/Makefile.am
Normal file
@@ -0,0 +1,13 @@
|
||||
bin_PROGRAMS = testserial
|
||||
|
||||
noinst_LIBRARIES = libSerial.a
|
||||
|
||||
libSerial_a_SOURCES = serial.cxx serial.hxx
|
||||
|
||||
testserial_SOURCES = testserial.cxx
|
||||
|
||||
testserial_LDADD = \
|
||||
$(top_builddir)/Lib/Serial/libSerial.a \
|
||||
$(top_builddir)/Lib/Debug/libDebug.a
|
||||
|
||||
INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib
|
||||
384
Lib/Serial/serial.cxx
Normal file
384
Lib/Serial/serial.cxx
Normal file
@@ -0,0 +1,384 @@
|
||||
// serial.cxx -- Unix serial I/O support
|
||||
//
|
||||
// Written by Curtis Olson, started November 1998.
|
||||
//
|
||||
// Copyright (C) 1998 Curtis L. Olson - curt@flightgear.org
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
// (Log is kept at end of this file)
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "Include/compiler.h"
|
||||
#ifdef FG_HAVE_STD_INCLUDE
|
||||
# include <cerrno>
|
||||
#else
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
|
||||
// maybe include something???
|
||||
#else
|
||||
# include <termios.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <fcntl.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <Debug/logstream.hxx>
|
||||
|
||||
#include "serial.hxx"
|
||||
|
||||
|
||||
fgSERIAL::fgSERIAL()
|
||||
: dev_open(false)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
fgSERIAL::fgSERIAL(const string& device, int baud) {
|
||||
open_port(device);
|
||||
|
||||
if ( dev_open ) {
|
||||
set_baud(baud);
|
||||
}
|
||||
}
|
||||
|
||||
fgSERIAL::~fgSERIAL() {
|
||||
// closing the port here screws us up because if we would even so
|
||||
// much as make a copy of an fgSERIAL object and then delete it,
|
||||
// the file descriptor gets closed. Doh!!!
|
||||
}
|
||||
|
||||
bool fgSERIAL::open_port(const string& device) {
|
||||
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
|
||||
|
||||
fd = CreateFile( device.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, // dwShareMode
|
||||
NULL, // lpSecurityAttributes
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
NULL );
|
||||
if ( fd == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL );
|
||||
|
||||
FG_LOG( FG_SERIAL, FG_ALERT, "Error opening serial device \""
|
||||
<< device << "\" " << (const char*) lpMsgBuf );
|
||||
LocalFree( lpMsgBuf );
|
||||
return false;
|
||||
}
|
||||
|
||||
dev_open = true;
|
||||
return true;
|
||||
|
||||
#else
|
||||
|
||||
struct termios config;
|
||||
|
||||
fd = open(device.c_str(), O_RDWR | O_NONBLOCK);
|
||||
cout << "Serial fd created = " << fd << endl;
|
||||
|
||||
if ( fd == -1 ) {
|
||||
FG_LOG( FG_SERIAL, FG_ALERT, "Cannot open " << device
|
||||
<< " for serial I/O" );
|
||||
return false;
|
||||
} else {
|
||||
dev_open = true;
|
||||
}
|
||||
|
||||
// set required port parameters
|
||||
if ( tcgetattr( fd, &config ) != 0 ) {
|
||||
FG_LOG( FG_SERIAL, FG_ALERT, "Unable to poll port settings" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// cfmakeraw( &config );
|
||||
|
||||
// cout << "config.c_iflag = " << config.c_iflag << endl;
|
||||
|
||||
// software flow control on
|
||||
config.c_iflag |= IXON;
|
||||
// config.c_iflag |= IXOFF;
|
||||
|
||||
// config.c_cflag |= CLOCAL;
|
||||
|
||||
#if ! defined( sgi )
|
||||
// disable hardware flow control
|
||||
config.c_cflag &= ~(CRTSCTS);
|
||||
#endif
|
||||
|
||||
// cout << "config.c_iflag = " << config.c_iflag << endl;
|
||||
|
||||
if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
|
||||
FG_LOG( FG_SERIAL, FG_ALERT, "Unable to update port settings" );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool fgSERIAL::close_port() {
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
|
||||
CloseHandle( fd );
|
||||
#else
|
||||
close(fd);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool fgSERIAL::set_baud(int baud) {
|
||||
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
|
||||
|
||||
return true;
|
||||
|
||||
#else
|
||||
|
||||
struct termios config;
|
||||
speed_t speed = B9600;
|
||||
|
||||
if ( tcgetattr( fd, &config ) != 0 ) {
|
||||
FG_LOG( FG_SERIAL, FG_ALERT, "Unable to poll port settings" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( baud == 300 ) {
|
||||
speed = B300;
|
||||
} else if ( baud == 1200 ) {
|
||||
speed = B1200;
|
||||
} else if ( baud == 2400 ) {
|
||||
speed = B2400;
|
||||
} else if ( baud == 4800 ) {
|
||||
speed = B4800;
|
||||
} else if ( baud == 9600 ) {
|
||||
speed = B9600;
|
||||
} else if ( baud == 19200 ) {
|
||||
speed = B19200;
|
||||
} else if ( baud == 38400 ) {
|
||||
speed = B38400;
|
||||
} else if ( baud == 57600 ) {
|
||||
speed = B57600;
|
||||
} else if ( baud == 115200 ) {
|
||||
speed = B115200;
|
||||
#if defined( linux ) || defined( __FreeBSD__ )
|
||||
} else if ( baud == 230400 ) {
|
||||
speed = B230400;
|
||||
#endif
|
||||
} else {
|
||||
FG_LOG( FG_SERIAL, FG_ALERT, "Unsupported baud rate " << baud );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( cfsetispeed( &config, speed ) != 0 ) {
|
||||
FG_LOG( FG_SERIAL, FG_ALERT, "Problem setting input baud rate" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( cfsetospeed( &config, speed ) != 0 ) {
|
||||
FG_LOG( FG_SERIAL, FG_ALERT, "Problem setting output baud rate" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
|
||||
FG_LOG( FG_SERIAL, FG_ALERT, "Unable to update port settings" );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
string fgSERIAL::read_port() {
|
||||
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
|
||||
|
||||
string result = "";
|
||||
return result;
|
||||
|
||||
#else
|
||||
|
||||
const int max_count = 1024;
|
||||
char buffer[max_count+1];
|
||||
int count;
|
||||
string result;
|
||||
|
||||
count = read(fd, buffer, max_count);
|
||||
// cout << "read " << count << " bytes" << endl;
|
||||
|
||||
if ( count < 0 ) {
|
||||
// error condition
|
||||
if ( errno != EAGAIN ) {
|
||||
FG_LOG( FG_SERIAL, FG_ALERT,
|
||||
"Serial I/O on read, error number = " << errno );
|
||||
}
|
||||
|
||||
return "";
|
||||
} else {
|
||||
buffer[count] = '\0';
|
||||
result = buffer;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int fgSERIAL::write_port(const string& value) {
|
||||
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
|
||||
|
||||
LPCVOID lpBuffer = value.c_str();
|
||||
DWORD nNumberOfBytesToWrite = value.length();
|
||||
DWORD lpNumberOfBytesWritten;
|
||||
OVERLAPPED lpOverlapped;
|
||||
|
||||
if ( WriteFile( fd,
|
||||
lpBuffer,
|
||||
nNumberOfBytesToWrite,
|
||||
&lpNumberOfBytesWritten,
|
||||
&lpOverlapped ) == 0 )
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL );
|
||||
|
||||
FG_LOG( FG_SERIAL, FG_ALERT, "Serial I/O write error: "
|
||||
<< (const char*) lpMsgBuf );
|
||||
LocalFree( lpMsgBuf );
|
||||
return int(lpNumberOfBytesWritten);
|
||||
}
|
||||
|
||||
return int(lpNumberOfBytesWritten);
|
||||
|
||||
#else
|
||||
|
||||
static bool error = false;
|
||||
int count;
|
||||
|
||||
if ( error ) {
|
||||
// attempt some sort of error recovery
|
||||
count = write(fd, "\n", 1);
|
||||
if ( count == 1 ) {
|
||||
// cout << "Serial error recover successful!\n";
|
||||
error = false;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
count = write(fd, value.c_str(), value.length());
|
||||
// cout << "write '" << value << "' " << count << " bytes" << endl;
|
||||
|
||||
if ( (int)count == (int)value.length() ) {
|
||||
error = false;
|
||||
} else {
|
||||
error = true;
|
||||
if ( errno == EAGAIN ) {
|
||||
// ok ... in our context we don't really care if we can't
|
||||
// write a string, we'll just get it the next time around
|
||||
} else {
|
||||
FG_LOG( FG_SERIAL, FG_ALERT,
|
||||
"Serial I/O on write, error number = " << errno );
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
// $Log$
|
||||
// Revision 1.1 1999/04/05 21:32:34 curt
|
||||
// Initial revision
|
||||
//
|
||||
// Revision 1.9 1999/02/02 20:13:23 curt
|
||||
// MSVC++ portability changes by Bernie Bright:
|
||||
//
|
||||
// Lib/Serial/serial.[ch]xx: Initial Windows support - incomplete.
|
||||
// Simulator/Astro/stars.cxx: typo? included <stdio> instead of <cstdio>
|
||||
// Simulator/Cockpit/hud.cxx: Added Standard headers
|
||||
// Simulator/Cockpit/panel.cxx: Redefinition of default parameter
|
||||
// Simulator/Flight/flight.cxx: Replaced cout with FG_LOG. Deleted <stdio.h>
|
||||
// Simulator/Main/fg_init.cxx:
|
||||
// Simulator/Main/GLUTmain.cxx:
|
||||
// Simulator/Main/options.hxx: Shuffled <fg_serial.hxx> dependency
|
||||
// Simulator/Objects/material.hxx:
|
||||
// Simulator/Time/timestamp.hxx: VC++ friend kludge
|
||||
// Simulator/Scenery/tile.[ch]xx: Fixed using std::X declarations
|
||||
// Simulator/Main/views.hxx: Added a constant
|
||||
//
|
||||
// Revision 1.8 1999/01/20 13:42:21 curt
|
||||
// Tweaked FDM interface.
|
||||
// Testing check sum support for NMEA serial output.
|
||||
//
|
||||
// Revision 1.7 1998/12/04 01:24:35 curt
|
||||
// Tweak for SGI portability.
|
||||
//
|
||||
// Revision 1.6 1998/11/30 17:15:29 curt
|
||||
// Having the class destructor close the fd was a bad idea ... especially if you
|
||||
// ever make a copy of the instance and then subsequently destroy either.
|
||||
// close_port() is now a separate member function.
|
||||
//
|
||||
// Revision 1.5 1998/11/25 01:33:23 curt
|
||||
// Remove call to cfmakeraw()
|
||||
//
|
||||
// Revision 1.4 1998/11/23 21:47:00 curt
|
||||
// Cygnus tools compatibility tweaks.
|
||||
//
|
||||
// Revision 1.3 1998/11/19 13:52:54 curt
|
||||
// port configuration tweaks & experiments.
|
||||
//
|
||||
// Revision 1.2 1998/11/19 03:35:43 curt
|
||||
// Updates ...
|
||||
//
|
||||
// Revision 1.1 1998/11/16 13:53:02 curt
|
||||
// Initial revision.
|
||||
//
|
||||
115
Lib/Serial/serial.hxx
Normal file
115
Lib/Serial/serial.hxx
Normal file
@@ -0,0 +1,115 @@
|
||||
// serial.hxx -- Unix serial I/O support
|
||||
//
|
||||
// Written by Curtis Olson, started November 1998.
|
||||
//
|
||||
// Copyright (C) 1998 Curtis L. Olson - curt@flightgear.org
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
// (Log is kept at end of this file)
|
||||
|
||||
|
||||
#ifndef _SERIAL_HXX
|
||||
#define _SERIAL_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <Include/compiler.h>
|
||||
#include STL_STRING
|
||||
FG_USING_STD(string);
|
||||
|
||||
// if someone know how to do this all with C++ streams let me know
|
||||
// #include <stdio.h>
|
||||
|
||||
|
||||
class fgSERIAL
|
||||
{
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
|
||||
typedef HANDLE fd_type;
|
||||
#else
|
||||
typedef int fd_type;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
fd_type fd;
|
||||
bool dev_open;
|
||||
|
||||
public:
|
||||
|
||||
fgSERIAL();
|
||||
fgSERIAL(const string& device, int baud);
|
||||
|
||||
~fgSERIAL();
|
||||
|
||||
bool open_port(const string& device);
|
||||
bool close_port();
|
||||
bool set_baud(int baud);
|
||||
string read_port();
|
||||
int write_port(const string& value);
|
||||
|
||||
inline bool is_enabled() { return dev_open; }
|
||||
};
|
||||
|
||||
|
||||
#endif // _SERIAL_HXX
|
||||
|
||||
|
||||
// $Log$
|
||||
// Revision 1.1 1999/04/05 21:32:34 curt
|
||||
// Initial revision
|
||||
//
|
||||
// Revision 1.5 1999/03/02 01:01:58 curt
|
||||
// Tweaks for compiling with native SGI compilers.
|
||||
//
|
||||
// Revision 1.4 1999/02/26 22:08:13 curt
|
||||
// Added initial support for native SGI compilers.
|
||||
//
|
||||
// Revision 1.3 1999/02/02 20:13:24 curt
|
||||
// MSVC++ portability changes by Bernie Bright:
|
||||
//
|
||||
// Lib/Serial/serial.[ch]xx: Initial Windows support - incomplete.
|
||||
// Simulator/Astro/stars.cxx: typo? included <stdio> instead of <cstdio>
|
||||
// Simulator/Cockpit/hud.cxx: Added Standard headers
|
||||
// Simulator/Cockpit/panel.cxx: Redefinition of default parameter
|
||||
// Simulator/Flight/flight.cxx: Replaced cout with FG_LOG. Deleted <stdio.h>
|
||||
// Simulator/Main/fg_init.cxx:
|
||||
// Simulator/Main/GLUTmain.cxx:
|
||||
// Simulator/Main/options.hxx: Shuffled <fg_serial.hxx> dependency
|
||||
// Simulator/Objects/material.hxx:
|
||||
// Simulator/Time/timestamp.hxx: VC++ friend kludge
|
||||
// Simulator/Scenery/tile.[ch]xx: Fixed using std::X declarations
|
||||
// Simulator/Main/views.hxx: Added a constant
|
||||
//
|
||||
// Revision 1.2 1998/11/30 17:15:30 curt
|
||||
// Having the class destructor close the fd was a bad idea ... especially if you
|
||||
// ever make a copy of the instance and then subsequently destroy either.
|
||||
// close_port() is now a separate member function.
|
||||
//
|
||||
// Revision 1.1 1998/11/16 13:53:02 curt
|
||||
// Initial revision.
|
||||
//
|
||||
30
Lib/Serial/testserial.cxx
Normal file
30
Lib/Serial/testserial.cxx
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <string>
|
||||
|
||||
#include <Debug/logstream.hxx>
|
||||
|
||||
#include "serial.hxx"
|
||||
|
||||
main () {
|
||||
fgSERIAL port;
|
||||
string value;
|
||||
bool result;
|
||||
|
||||
fglog().setLogLevels( FG_ALL, FG_INFO );
|
||||
|
||||
cout << "start of main" << endl;
|
||||
|
||||
result = port.open_port("/dev/ttyS1");
|
||||
cout << "opened port, result = " << result << endl;
|
||||
|
||||
result = port.set_baud(4800);
|
||||
cout << "set baud, result = " << result << endl;
|
||||
|
||||
port.write_port("ATDT 626-9800\n");
|
||||
|
||||
while ( true ) {
|
||||
value = port.read_port();
|
||||
if ( value.length() ) {
|
||||
cout << "-> " << value << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user