//
// Written by Curtis Olson, started November 1998.
//
-// Copyright (C) 1998 Curtis L. Olson - curt@flightgear.org
+// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
-// You should have received a copy of the GNU Library General Public
-// License along with this library; if not, write to the
-// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-// Boston, MA 02111-1307, USA.
+// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
#include <simgear/compiler.h>
-#ifdef SG_HAVE_STD_INCLUDE
-# include <cerrno>
-#else
-# include <errno.h>
-#endif
+#include <iostream>
+#include <cerrno>
-#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
- // maybe include something???
-#else
+#ifndef _WIN32
# include <termios.h>
# include <sys/types.h>
# include <sys/stat.h>
#include "serial.hxx"
-
-FGSerialPort::FGSerialPort()
+SGSerialPort::SGSerialPort()
: dev_open(false)
{
// empty
}
-FGSerialPort::FGSerialPort(const string& device, int baud) {
+SGSerialPort::SGSerialPort(const string& device, int baud) {
open_port(device);
if ( dev_open ) {
}
}
-FGSerialPort::~FGSerialPort() {
+SGSerialPort::~SGSerialPort() {
// closing the port here screws us up because if we would even so
- // much as make a copy of an FGSerialPort object and then delete it,
+ // much as make a copy of an SGSerialPort object and then delete it,
// the file descriptor gets closed. Doh!!!
}
-bool FGSerialPort::open_port(const string& device) {
+bool SGSerialPort::open_port(const string& device) {
-#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
+#ifdef _WIN32
fd = CreateFile( device.c_str(),
GENERIC_READ | GENERIC_WRITE,
0, // dwShareMode
NULL, // lpSecurityAttributes
OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED,
+ 0,
NULL );
if ( fd == INVALID_HANDLE_VALUE )
{
struct termios config;
- fd = open(device.c_str(), O_RDWR | O_NONBLOCK);
- cout << "Serial fd created = " << fd << endl;
+ fd = open(device.c_str(), O_RDWR | O_NOCTTY| O_NDELAY);
+ SG_LOG( SG_EVENT, SG_DEBUG, "Serial fd created = " << fd);
if ( fd == -1 ) {
SG_LOG( SG_IO, SG_ALERT, "Cannot open " << device
// cout << "config.c_iflag = " << config.c_iflag << endl;
- // software flow control on
- config.c_iflag |= IXON;
- // config.c_iflag |= IXOFF;
+ // disable LF expanded to CR-LF
+ config.c_oflag &= ~(ONLCR);
+
+ // disable software flow control
+ config.c_iflag &= ~(IXON | IXOFF | IXANY);
- // config.c_cflag |= CLOCAL;
+ // enable the receiver and set local mode
+ config.c_cflag |= (CLOCAL | CREAD);
-#if ! defined( sgi )
+#if !defined( sgi ) && !defined(_AIX)
// disable hardware flow control
config.c_cflag &= ~(CRTSCTS);
#endif
// cout << "config.c_iflag = " << config.c_iflag << endl;
+
+ // Raw (not cooked/canonical) input mode
+ config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
}
-bool FGSerialPort::close_port() {
-#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
+bool SGSerialPort::close_port() {
+#ifdef _WIN32
CloseHandle( fd );
#else
close(fd);
}
-bool FGSerialPort::set_baud(int baud) {
+bool SGSerialPort::set_baud(int baud) {
+
+#ifdef _WIN32
+
+ DCB dcb;
+ if ( GetCommState( fd, &dcb ) ) {
+ dcb.BaudRate = baud;
+ dcb.fOutxCtsFlow = FALSE;
+ dcb.fOutxDsrFlow = FALSE;
+ dcb.fOutX = TRUE;
+ dcb.fInX = TRUE;
+
+ if ( !SetCommState( fd, &dcb ) ) {
+ 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 );
+
+ SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings: "
+ << (const char*) lpMsgBuf );
+ LocalFree( lpMsgBuf );
+ return false;
+ }
+ } else {
+ 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 );
-#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
+ SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings: "
+ << (const char*) lpMsgBuf );
+ LocalFree( lpMsgBuf );
+ return false;
+ }
return true;
speed = B19200;
} else if ( baud == 38400 ) {
speed = B38400;
+#if defined( linux ) || defined( __FreeBSD__ )
} else if ( baud == 57600 ) {
speed = B57600;
} else if ( baud == 115200 ) {
speed = B115200;
-#if defined( linux ) || defined( __FreeBSD__ )
} else if ( baud == 230400 ) {
speed = B230400;
#endif
}
-string FGSerialPort::read_port() {
+string SGSerialPort::read_port() {
+
+ const int max_count = 1024;
+ char buffer[max_count+1];
+ string result;
+
+#ifdef _WIN32
+
+ DWORD count;
+ if ( ReadFile( fd, buffer, max_count, &count, 0 ) ) {
+ buffer[count] = '\0';
+ result = buffer;
+ } else {
+ 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 );
-#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
+ SG_LOG( SG_IO, SG_ALERT, "Serial I/O read error: "
+ << (const char*) lpMsgBuf );
+ LocalFree( lpMsgBuf );
+ }
- 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);
+ int count = read(fd, buffer, max_count);
// cout << "read " << count << " bytes" << endl;
if ( count < 0 ) {
}
-int FGSerialPort::read_port(char *buf, int len) {
+int SGSerialPort::read_port(char *buf, int len) {
+
+#ifdef _WIN32
-#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
+ DWORD count;
+ if ( ReadFile( fd, buf, len, &count, 0 ) ) {
+ buf[count] = '\0';
- buf[0] = '\0';
- return 0;
+ return count;
+ } else {
+ 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 );
+
+ SG_LOG( SG_IO, SG_ALERT, "Serial I/O read error: "
+ << (const char*) lpMsgBuf );
+ LocalFree( lpMsgBuf );
+
+ buf[0] = '\0';
+ return 0;
+ }
#else
}
-int FGSerialPort::write_port(const string& value) {
+int SGSerialPort::write_port(const string& value) {
-#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
+#ifdef _WIN32
- LPCVOID lpBuffer = value.c_str();
+ LPCVOID lpBuffer = value.data();
DWORD nNumberOfBytesToWrite = value.length();
DWORD lpNumberOfBytesWritten;
- OVERLAPPED lpOverlapped;
if ( WriteFile( fd,
lpBuffer,
nNumberOfBytesToWrite,
&lpNumberOfBytesWritten,
- &lpOverlapped ) == 0 )
+ 0 ) == 0 )
{
LPVOID lpMsgBuf;
FormatMessage(
}
-int FGSerialPort::write_port(const char* buf, int len) {
-#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
+int SGSerialPort::write_port(const char* buf, int len) {
+#ifdef _WIN32
LPCVOID lpBuffer = buf;
DWORD nNumberOfBytesToWrite = len;
DWORD lpNumberOfBytesWritten;
- OVERLAPPED lpOverlapped;
if ( WriteFile( fd,
lpBuffer,
nNumberOfBytesToWrite,
&lpNumberOfBytesWritten,
- &lpOverlapped ) == 0 )
+ 0 ) == 0 )
{
LPVOID lpMsgBuf;
FormatMessage(