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 library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Library General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Library General Public License for more details.
17 // You should have received a copy of the GNU Library General Public
18 // License along with this library; if not, write to the
19 // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 // Boston, MA 02111-1307, USA.
25 #include <simgear/compiler.h>
29 #ifdef SG_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 <simgear/debug/logstream.hxx>
49 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
55 FGSerialPort::FGSerialPort()
61 FGSerialPort::FGSerialPort(const string& device, int baud) {
69 FGSerialPort::~FGSerialPort() {
70 // closing the port here screws us up because if we would even so
71 // much as make a copy of an FGSerialPort object and then delete it,
72 // the file descriptor gets closed. Doh!!!
75 bool FGSerialPort::open_port(const string& device) {
77 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
79 fd = CreateFile( device.c_str(),
80 GENERIC_READ | GENERIC_WRITE,
82 NULL, // lpSecurityAttributes
86 if ( fd == INVALID_HANDLE_VALUE )
90 FORMAT_MESSAGE_ALLOCATE_BUFFER |
91 FORMAT_MESSAGE_FROM_SYSTEM |
92 FORMAT_MESSAGE_IGNORE_INSERTS,
95 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
100 SG_LOG( SG_IO, SG_ALERT, "Error opening serial device \""
101 << device << "\" " << (const char*) lpMsgBuf );
102 LocalFree( lpMsgBuf );
111 struct termios config;
113 fd = open(device.c_str(), O_RDWR | O_NONBLOCK);
114 cout << "Serial fd created = " << fd << endl;
117 SG_LOG( SG_IO, SG_ALERT, "Cannot open " << device
118 << " for serial I/O" );
124 // set required port parameters
125 if ( tcgetattr( fd, &config ) != 0 ) {
126 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
130 // cfmakeraw( &config );
132 // cout << "config.c_iflag = " << config.c_iflag << endl;
134 // software flow control on
135 config.c_iflag |= IXON;
136 // config.c_iflag |= IXOFF;
138 // config.c_cflag |= CLOCAL;
141 // disable hardware flow control
142 config.c_cflag &= ~(CRTSCTS);
145 // cout << "config.c_iflag = " << config.c_iflag << endl;
147 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
148 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
157 bool FGSerialPort::close_port() {
158 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
170 bool FGSerialPort::set_baud(int baud) {
172 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
178 struct termios config;
179 speed_t speed = B9600;
181 if ( tcgetattr( fd, &config ) != 0 ) {
182 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
188 } else if ( baud == 1200 ) {
190 } else if ( baud == 2400 ) {
192 } else if ( baud == 4800 ) {
194 } else if ( baud == 9600 ) {
196 } else if ( baud == 19200 ) {
198 } else if ( baud == 38400 ) {
200 } else if ( baud == 57600 ) {
202 } else if ( baud == 115200 ) {
204 #if defined( linux ) || defined( __FreeBSD__ )
205 } else if ( baud == 230400 ) {
209 SG_LOG( SG_IO, SG_ALERT, "Unsupported baud rate " << baud );
213 if ( cfsetispeed( &config, speed ) != 0 ) {
214 SG_LOG( SG_IO, SG_ALERT, "Problem setting input baud rate" );
218 if ( cfsetospeed( &config, speed ) != 0 ) {
219 SG_LOG( SG_IO, SG_ALERT, "Problem setting output baud rate" );
223 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
224 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
234 string FGSerialPort::read_port() {
236 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
243 const int max_count = 1024;
244 char buffer[max_count+1];
248 count = read(fd, buffer, max_count);
249 // cout << "read " << count << " bytes" << endl;
253 if ( errno != EAGAIN ) {
254 SG_LOG( SG_IO, SG_ALERT,
255 "Serial I/O on read, error number = " << errno );
260 buffer[count] = '\0';
270 int FGSerialPort::read_port(char *buf, int len) {
272 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
281 int count = read(fd, buf, len);
282 // cout << "read " << count << " bytes" << endl;
286 if ( errno != EAGAIN ) {
287 SG_LOG( SG_IO, SG_ALERT,
288 "Serial I/O on read, error number = " << errno );
304 int FGSerialPort::write_port(const string& value) {
306 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
308 LPCVOID lpBuffer = value.c_str();
309 DWORD nNumberOfBytesToWrite = value.length();
310 DWORD lpNumberOfBytesWritten;
311 OVERLAPPED lpOverlapped;
315 nNumberOfBytesToWrite,
316 &lpNumberOfBytesWritten,
317 &lpOverlapped ) == 0 )
321 FORMAT_MESSAGE_ALLOCATE_BUFFER |
322 FORMAT_MESSAGE_FROM_SYSTEM |
323 FORMAT_MESSAGE_IGNORE_INSERTS,
326 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
331 SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
332 << (const char*) lpMsgBuf );
333 LocalFree( lpMsgBuf );
334 return int(lpNumberOfBytesWritten);
337 return int(lpNumberOfBytesWritten);
341 static bool error = false;
345 SG_LOG( SG_IO, SG_ALERT, "attempting serial write error recovery" );
346 // attempt some sort of error recovery
347 count = write(fd, "\n", 1);
349 // cout << "Serial error recover successful!\n";
356 count = write(fd, value.c_str(), value.length());
357 // cout << "write '" << value << "' " << count << " bytes" << endl;
359 if ( (int)count == (int)value.length() ) {
362 if ( errno == EAGAIN ) {
363 // ok ... in our context we don't really care if we can't
364 // write a string, we'll just get it the next time around
368 SG_LOG( SG_IO, SG_ALERT,
369 "Serial I/O on write, error number = " << errno );
380 int FGSerialPort::write_port(const char* buf, int len) {
381 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
383 LPCVOID lpBuffer = buf;
384 DWORD nNumberOfBytesToWrite = len;
385 DWORD lpNumberOfBytesWritten;
386 OVERLAPPED lpOverlapped;
390 nNumberOfBytesToWrite,
391 &lpNumberOfBytesWritten,
392 &lpOverlapped ) == 0 )
396 FORMAT_MESSAGE_ALLOCATE_BUFFER |
397 FORMAT_MESSAGE_FROM_SYSTEM |
398 FORMAT_MESSAGE_IGNORE_INSERTS,
401 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
406 SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
407 << (const char*) lpMsgBuf );
408 LocalFree( lpMsgBuf );
409 return int(lpNumberOfBytesWritten);
412 return int(lpNumberOfBytesWritten);
416 static bool error = false;
420 // attempt some sort of error recovery
421 count = write(fd, "\n", 1);
423 // cout << "Serial error recover successful!\n";
430 count = write(fd, buf, len);
431 // cout << "write '" << buf << "' " << count << " bytes" << endl;
433 if ( (int)count == len ) {
437 if ( errno == EAGAIN ) {
438 // ok ... in our context we don't really care if we can't
439 // write a string, we'll just get it the next time around
441 SG_LOG( SG_IO, SG_ALERT,
442 "Serial I/O on write, error number = " << errno );