head 1.4; access; symbols; locks; strict; comment @# @; 1.4 date 2002.09.07.01.50.39; author curt; state Exp; branches; next 1.3; 1.3 date 2002.08.31.19.01.56; author curt; state Exp; branches; next 1.2; 1.2 date 2002.08.31.18.54.03; author curt; state Exp; branches; next 1.1; 1.1 date 2002.02.15.17.21.59; author curt; state Exp; branches; next ; desc @@ 1.4 log @Updated doxygen docs. @ text @
Main Page Class Hierarchy Compound List File List Compound Members File Members

# serial.cxx

    00001 // serial.cxx -- Unix serial I/O support
    00002 //
    00003 // Written by Curtis Olson, started November 1998.
    00004 //
    00005 // Copyright (C) 1998  Curtis L. Olson - curt@@flightgear.org
    00006 //
    00007 // This library is free software; you can redistribute it and/or
    00008 // modify it under the terms of the GNU Library General Public
    00009 // License as published by the Free Software Foundation; either
    00010 // version 2 of the License, or (at your option) any later version.
    00011 //
    00012 // This library is distributed in the hope that it will be useful,
    00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00015 // Library General Public License for more details.
    00016 //
    00017 // You should have received a copy of the GNU Library General Public
    00018 // License along with this library; if not, write to the
    00019 // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00020 // Boston, MA  02111-1307, USA.
    00021 //
    00022 // $Id: serial.cxx,v 1.7 2001/05/23 19:25:28 curt Exp $
    00023
    00024
    00025 #include <simgear/compiler.h>
    00026
    00027 #include STL_IOSTREAM
    00028
    00029 #ifdef SG_HAVE_STD_INCLUDE
    00030 #  include <cerrno>
    00031 #else
    00032 #  include <errno.h>
    00033 #endif
    00034
    00035 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
    00036   // maybe include something???
    00037 #else
    00038 #  include <termios.h>
    00039 #  include <sys/types.h>
    00040 #  include <sys/stat.h>
    00041 #  include <fcntl.h>
    00042 #  include <unistd.h>
    00043 #endif
    00044
    00045 #include <simgear/debug/logstream.hxx>
    00046
    00047 #include "serial.hxx"
    00048
    00049 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
    00050 SG_USING_STD(cout);
    00051 SG_USING_STD(endl);
    00052 #endif
    00053
    00054
    00055 FGSerialPort::FGSerialPort()
    00056     : dev_open(false)
    00057 {
    00058     // empty
    00059 }
    00060
    00061 FGSerialPort::FGSerialPort(const string& device, int baud) {
    00062     open_port(device);
    00063
    00064     if ( dev_open ) {
    00065         set_baud(baud);
    00066     }
    00067 }
    00068
    00069 FGSerialPort::~FGSerialPort() {
    00070     // closing the port here screws us up because if we would even so
    00071     // much as make a copy of an FGSerialPort object and then delete it,
    00072     // the file descriptor gets closed.  Doh!!!
    00073 }
    00074
    00075 bool FGSerialPort::open_port(const string& device) {
    00076
    00077 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
    00078
    00079     fd = CreateFile( device.c_str(),
    00080         GENERIC_READ | GENERIC_WRITE,
    00081         0, // dwShareMode
    00082         NULL, // lpSecurityAttributes
    00083         OPEN_EXISTING,
    00084         FILE_FLAG_OVERLAPPED,
    00085         NULL );
    00086     if ( fd == INVALID_HANDLE_VALUE )
    00087     {
    00088         LPVOID lpMsgBuf;
    00089         FormatMessage(
    00090             FORMAT_MESSAGE_ALLOCATE_BUFFER |
    00091             FORMAT_MESSAGE_FROM_SYSTEM |
    00092             FORMAT_MESSAGE_IGNORE_INSERTS,
    00093             NULL,
    00094             GetLastError(),
    00095             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    00096             (LPTSTR) &lpMsgBuf,
    00097             0,
    00098             NULL );
    00099
    00100         SG_LOG( SG_IO, SG_ALERT, "Error opening serial device \""
    00101             << device << "\" " << (const char*) lpMsgBuf );
    00102         LocalFree( lpMsgBuf );
    00103         return false;
    00104     }
    00105
    00106     dev_open = true;
    00107     return true;
    00108
    00109 #else
    00110
    00111     struct termios config;
    00112
    00113     fd = open(device.c_str(), O_RDWR | O_NONBLOCK);
    00114     cout << "Serial fd created = " << fd << endl;
    00115
    00116     if ( fd  == -1 ) {
    00117         SG_LOG( SG_IO, SG_ALERT, "Cannot open " << device
    00118                 << " for serial I/O" );
    00119         return false;
    00120     } else {
    00121         dev_open = true;
    00122     }
    00123
    00124     // set required port parameters
    00125     if ( tcgetattr( fd, &config ) != 0 ) {
    00126         SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
    00127         return false;
    00128     }
    00129
    00130     // cfmakeraw( &config );
    00131
    00132     // cout << "config.c_iflag = " << config.c_iflag << endl;
    00133
    00134     // software flow control on
    00135     config.c_iflag |= IXON;
    00136     // config.c_iflag |= IXOFF;
    00137
    00138     // config.c_cflag |= CLOCAL;
    00139
    00140 #if ! defined( sgi )
    00141     // disable hardware flow control
    00142     config.c_cflag &= ~(CRTSCTS);
    00143 #endif
    00144
    00145     // cout << "config.c_iflag = " << config.c_iflag << endl;
    00146
    00147     if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
    00148         SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
    00149         return false;
    00150     }
    00151
    00152     return true;
    00153 #endif
    00154 }
    00155
    00156
    00157 bool FGSerialPort::close_port() {
    00158 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
    00159     CloseHandle( fd );
    00160 #else
    00161     close(fd);
    00162 #endif
    00163
    00164     dev_open = false;
    00165
    00166     return true;
    00167 }
    00168
    00169
    00170 bool FGSerialPort::set_baud(int baud) {
    00171
    00172 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
    00173
    00174     return true;
    00175
    00176 #else
    00177
    00178     struct termios config;
    00179     speed_t speed = B9600;
    00180
    00181     if ( tcgetattr( fd, &config ) != 0 ) {
    00182         SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
    00183         return false;
    00184     }
    00185
    00186     if ( baud == 300 ) {
    00187         speed = B300;
    00188     } else if ( baud == 1200 ) {
    00189         speed = B1200;
    00190     } else if ( baud == 2400 ) {
    00191         speed = B2400;
    00192     } else if ( baud == 4800 ) {
    00193         speed = B4800;
    00194     } else if ( baud == 9600 ) {
    00195         speed = B9600;
    00196     } else if ( baud == 19200 ) {
    00197         speed = B19200;
    00198     } else if ( baud == 38400 ) {
    00199         speed = B38400;
    00200     } else if ( baud == 57600 ) {
    00201         speed = B57600;
    00202     } else if ( baud == 115200 ) {
    00203         speed = B115200;
    00204 #if defined( linux ) || defined( __FreeBSD__ )
    00205     } else if ( baud == 230400 ) {
    00206         speed = B230400;
    00207 #endif
    00208     } else {
    00209         SG_LOG( SG_IO, SG_ALERT, "Unsupported baud rate " << baud );
    00210         return false;
    00211     }
    00212
    00213     if ( cfsetispeed( &config, speed ) != 0 ) {
    00214         SG_LOG( SG_IO, SG_ALERT, "Problem setting input baud rate" );
    00215         return false;
    00216     }
    00217
    00218     if ( cfsetospeed( &config, speed ) != 0 ) {
    00219         SG_LOG( SG_IO, SG_ALERT, "Problem setting output baud rate" );
    00220         return false;
    00221     }
    00222
    00223     if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
    00224         SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
    00225         return false;
    00226     }
    00227
    00228     return true;
    00229
    00230 #endif
    00231
    00232 }
    00233
    00234 string FGSerialPort::read_port() {
    00235
    00236 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
    00237
    00238     string result = "";
    00239     return result;
    00240
    00241 #else
    00242
    00243     const int max_count = 1024;
    00244     char buffer[max_count+1];
    00245     int count;
    00246     string result;
    00247
    00248     count = read(fd, buffer, max_count);
    00249     // cout << "read " << count << " bytes" << endl;
    00250
    00251     if ( count < 0 ) {
    00252         // error condition
    00253         if ( errno != EAGAIN ) {
    00254             SG_LOG( SG_IO, SG_ALERT,
    00255                     "Serial I/O on read, error number = " << errno );
    00256         }
    00257
    00258         return "";
    00259     } else {
    00260         buffer[count] = '\0';
    00261         result = buffer;
    00262
    00263         return result;
    00264     }
    00265
    00266 #endif
    00267
    00268 }
    00269
    00270 int FGSerialPort::read_port(char *buf, int len) {
    00271
    00272 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
    00273
    00274     buf[0] = '\0';
    00275     return 0;
    00276
    00277 #else
    00278
    00279     string result;
    00280
    00281     int count = read(fd, buf, len);
    00282     // cout << "read " << count << " bytes" << endl;
    00283
    00284     if ( count < 0 ) {
    00285         // error condition
    00286         if ( errno != EAGAIN ) {
    00287             SG_LOG( SG_IO, SG_ALERT,
    00288                     "Serial I/O on read, error number = " << errno );
    00289         }
    00290
    00291         buf[0] = '\0';
    00292         return 0;
    00293     } else {
    00294         buf[count] = '\0';
    00295
    00296         return count;
    00297     }
    00298
    00299 #endif
    00300
    00301 }
    00302
    00303
    00304 int FGSerialPort::write_port(const string& value) {
    00305
    00306 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
    00307
    00308     LPCVOID lpBuffer = value.c_str();
    00309     DWORD nNumberOfBytesToWrite = value.length();
    00310     DWORD lpNumberOfBytesWritten;
    00311     OVERLAPPED lpOverlapped;
    00312
    00313     if ( WriteFile( fd,
    00314         lpBuffer,
    00315         nNumberOfBytesToWrite,
    00316         &lpNumberOfBytesWritten,
    00317         &lpOverlapped ) == 0 )
    00318     {
    00319         LPVOID lpMsgBuf;
    00320         FormatMessage(
    00321             FORMAT_MESSAGE_ALLOCATE_BUFFER |
    00322             FORMAT_MESSAGE_FROM_SYSTEM |
    00323             FORMAT_MESSAGE_IGNORE_INSERTS,
    00324             NULL,
    00325             GetLastError(),
    00326             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    00327             (LPTSTR) &lpMsgBuf,
    00328             0,
    00329             NULL );
    00330
    00331         SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
    00332              << (const char*) lpMsgBuf );
    00333         LocalFree( lpMsgBuf );
    00334         return int(lpNumberOfBytesWritten);
    00335     }
    00336
    00337     return int(lpNumberOfBytesWritten);
    00338
    00339 #else
    00340
    00341     static bool error = false;
    00342     int count;
    00343
    00344     if ( error ) {
    00345         SG_LOG( SG_IO, SG_ALERT, "attempting serial write error recovery" );
    00346         // attempt some sort of error recovery
    00347         count = write(fd, "\n", 1);
    00348         if ( count == 1 ) {
    00349             // cout << "Serial error recover successful!\n";
    00350             error = false;
    00351         } else {
    00352             return 0;
    00353         }
    00354     }
    00355
    00356     count = write(fd, value.c_str(), value.length());
    00357     // cout << "write '" << value << "'  " << count << " bytes" << endl;
    00358
    00359     if ( (int)count == (int)value.length() ) {
    00360         error = false;
    00361     } else {
    00362         if ( errno == EAGAIN ) {
    00363             // ok ... in our context we don't really care if we can't
    00364             // write a string, we'll just get it the next time around
    00365             error = false;
    00366         } else {
    00367             error = true;
    00368             SG_LOG( SG_IO, SG_ALERT,
    00369                     "Serial I/O on write, error number = " << errno );
    00370         }
    00371     }
    00372
    00373     return count;
    00374
    00375 #endif
    00376
    00377 }
    00378
    00379
    00380 int FGSerialPort::write_port(const char* buf, int len) {
    00381 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
    00382
    00383     LPCVOID lpBuffer = buf;
    00384     DWORD nNumberOfBytesToWrite = len;
    00385     DWORD lpNumberOfBytesWritten;
    00386     OVERLAPPED lpOverlapped;
    00387
    00388     if ( WriteFile( fd,
    00389         lpBuffer,
    00390         nNumberOfBytesToWrite,
    00391         &lpNumberOfBytesWritten,
    00392         &lpOverlapped ) == 0 )
    00393     {
    00394         LPVOID lpMsgBuf;
    00395         FormatMessage(
    00396             FORMAT_MESSAGE_ALLOCATE_BUFFER |
    00397             FORMAT_MESSAGE_FROM_SYSTEM |
    00398             FORMAT_MESSAGE_IGNORE_INSERTS,
    00399             NULL,
    00400             GetLastError(),
    00401             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    00402             (LPTSTR) &lpMsgBuf,
    00403             0,
    00404             NULL );
    00405
    00406         SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
    00407              << (const char*) lpMsgBuf );
    00408         LocalFree( lpMsgBuf );
    00409         return int(lpNumberOfBytesWritten);
    00410     }
    00411
    00412     return int(lpNumberOfBytesWritten);
    00413
    00414 #else
    00415
    00416     static bool error = false;
    00417     int count;
    00418
    00419     if ( error ) {
    00420         // attempt some sort of error recovery
    00421         count = write(fd, "\n", 1);
    00422         if ( count == 1 ) {
    00423             // cout << "Serial error recover successful!\n";
    00424             error = false;
    00425         } else {
    00426             return 0;
    00427         }
    00428     }
    00429
    00430     count = write(fd, buf, len);
    00431     // cout << "write '" << buf << "'  " << count << " bytes" << endl;
    00432
    00433     if ( (int)count == len ) {
    00434         error = false;
    00435     } else {
    00436         error = true;
    00437         if ( errno == EAGAIN ) {
    00438             // ok ... in our context we don't really care if we can't
    00439             // write a string, we'll just get it the next time around
    00440         } else {
    00441             SG_LOG( SG_IO, SG_ALERT,
    00442                     "Serial I/O on write, error number = " << errno );
    00443         }
    00444     }
    00445
    00446     return count;
    00447
    00448 #endif
    00449
    00450 }

@ 1.3 log @Oops, try again. @ text @d459 1 a459 1