1 // serial.cxx -- Unix serial I/O support
3 // Written by Curtis Olson, started November 1998.
5 // Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
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__ )
37 # include <sys/types.h>
38 # include <sys/stat.h>
43 #include <simgear/debug/logstream.hxx>
47 SGSerialPort::SGSerialPort()
53 SGSerialPort::SGSerialPort(const string& device, int baud) {
61 SGSerialPort::~SGSerialPort() {
62 // closing the port here screws us up because if we would even so
63 // much as make a copy of an SGSerialPort object and then delete it,
64 // the file descriptor gets closed. Doh!!!
67 bool SGSerialPort::open_port(const string& device) {
69 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
71 fd = CreateFile( device.c_str(),
72 GENERIC_READ | GENERIC_WRITE,
74 NULL, // lpSecurityAttributes
78 if ( fd == INVALID_HANDLE_VALUE )
82 FORMAT_MESSAGE_ALLOCATE_BUFFER |
83 FORMAT_MESSAGE_FROM_SYSTEM |
84 FORMAT_MESSAGE_IGNORE_INSERTS,
87 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
92 SG_LOG( SG_IO, SG_ALERT, "Error opening serial device \""
93 << device << "\" " << (const char*) lpMsgBuf );
94 LocalFree( lpMsgBuf );
103 struct termios config;
105 fd = open(device.c_str(), O_RDWR | O_NOCTTY| O_NDELAY);
106 SG_LOG( SG_EVENT, SG_DEBUG, "Serial fd created = " << fd);
109 SG_LOG( SG_IO, SG_ALERT, "Cannot open " << device
110 << " for serial I/O" );
116 // set required port parameters
117 if ( tcgetattr( fd, &config ) != 0 ) {
118 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
122 // cfmakeraw( &config );
124 // cout << "config.c_iflag = " << config.c_iflag << endl;
126 // disable software flow control
127 config.c_iflag &= ~(IXON | IXOFF | IXANY);
129 // enable the receiver and set local mode
130 config.c_cflag |= (CLOCAL | CREAD);
132 #if !defined( sgi ) && !defined(_AIX)
133 // disable hardware flow control
134 config.c_cflag &= ~(CRTSCTS);
137 // cout << "config.c_iflag = " << config.c_iflag << endl;
139 // Raw (not cooked/canonical) input mode
140 config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
142 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
143 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
152 bool SGSerialPort::close_port() {
153 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
165 bool SGSerialPort::set_baud(int baud) {
167 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
170 if ( GetCommState( fd, &dcb ) ) {
172 dcb.fOutxCtsFlow = FALSE;
173 dcb.fOutxDsrFlow = FALSE;
177 if ( !SetCommState( fd, &dcb ) ) {
180 FORMAT_MESSAGE_ALLOCATE_BUFFER |
181 FORMAT_MESSAGE_FROM_SYSTEM |
182 FORMAT_MESSAGE_IGNORE_INSERTS,
185 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
190 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings: "
191 << (const char*) lpMsgBuf );
192 LocalFree( lpMsgBuf );
198 FORMAT_MESSAGE_ALLOCATE_BUFFER |
199 FORMAT_MESSAGE_FROM_SYSTEM |
200 FORMAT_MESSAGE_IGNORE_INSERTS,
203 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
208 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings: "
209 << (const char*) lpMsgBuf );
210 LocalFree( lpMsgBuf );
218 struct termios config;
219 speed_t speed = B9600;
221 if ( tcgetattr( fd, &config ) != 0 ) {
222 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
228 } else if ( baud == 1200 ) {
230 } else if ( baud == 2400 ) {
232 } else if ( baud == 4800 ) {
234 } else if ( baud == 9600 ) {
236 } else if ( baud == 19200 ) {
238 } else if ( baud == 38400 ) {
240 #if defined( linux ) || defined( __FreeBSD__ )
241 } else if ( baud == 57600 ) {
243 } else if ( baud == 115200 ) {
245 } else if ( baud == 230400 ) {
249 SG_LOG( SG_IO, SG_ALERT, "Unsupported baud rate " << baud );
253 if ( cfsetispeed( &config, speed ) != 0 ) {
254 SG_LOG( SG_IO, SG_ALERT, "Problem setting input baud rate" );
258 if ( cfsetospeed( &config, speed ) != 0 ) {
259 SG_LOG( SG_IO, SG_ALERT, "Problem setting output baud rate" );
263 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
264 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
274 string SGSerialPort::read_port() {
276 const int max_count = 1024;
277 char buffer[max_count+1];
280 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
283 if ( ReadFile( fd, buffer, max_count, &count, 0 ) ) {
284 buffer[count] = '\0';
289 FORMAT_MESSAGE_ALLOCATE_BUFFER |
290 FORMAT_MESSAGE_FROM_SYSTEM |
291 FORMAT_MESSAGE_IGNORE_INSERTS,
294 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
299 SG_LOG( SG_IO, SG_ALERT, "Serial I/O read error: "
300 << (const char*) lpMsgBuf );
301 LocalFree( lpMsgBuf );
308 int count = read(fd, buffer, max_count);
309 // cout << "read " << count << " bytes" << endl;
313 if ( errno != EAGAIN ) {
314 SG_LOG( SG_IO, SG_ALERT,
315 "Serial I/O on read, error number = " << errno );
320 buffer[count] = '\0';
330 int SGSerialPort::read_port(char *buf, int len) {
332 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
335 if ( ReadFile( fd, buf, len, &count, 0 ) ) {
342 FORMAT_MESSAGE_ALLOCATE_BUFFER |
343 FORMAT_MESSAGE_FROM_SYSTEM |
344 FORMAT_MESSAGE_IGNORE_INSERTS,
347 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
352 SG_LOG( SG_IO, SG_ALERT, "Serial I/O read error: "
353 << (const char*) lpMsgBuf );
354 LocalFree( lpMsgBuf );
364 int count = read(fd, buf, len);
365 // cout << "read " << count << " bytes" << endl;
369 if ( errno != EAGAIN ) {
370 SG_LOG( SG_IO, SG_ALERT,
371 "Serial I/O on read, error number = " << errno );
387 int SGSerialPort::write_port(const string& value) {
389 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
391 LPCVOID lpBuffer = value.data();
392 DWORD nNumberOfBytesToWrite = value.length();
393 DWORD lpNumberOfBytesWritten;
397 nNumberOfBytesToWrite,
398 &lpNumberOfBytesWritten,
403 FORMAT_MESSAGE_ALLOCATE_BUFFER |
404 FORMAT_MESSAGE_FROM_SYSTEM |
405 FORMAT_MESSAGE_IGNORE_INSERTS,
408 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
413 SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
414 << (const char*) lpMsgBuf );
415 LocalFree( lpMsgBuf );
416 return int(lpNumberOfBytesWritten);
419 return int(lpNumberOfBytesWritten);
423 static bool error = false;
427 SG_LOG( SG_IO, SG_ALERT, "attempting serial write error recovery" );
428 // attempt some sort of error recovery
429 count = write(fd, "\n", 1);
431 // cout << "Serial error recover successful!\n";
438 count = write(fd, value.c_str(), value.length());
439 // cout << "write '" << value << "' " << count << " bytes" << endl;
441 if ( (int)count == (int)value.length() ) {
444 if ( errno == EAGAIN ) {
445 // ok ... in our context we don't really care if we can't
446 // write a string, we'll just get it the next time around
450 SG_LOG( SG_IO, SG_ALERT,
451 "Serial I/O on write, error number = " << errno );
462 int SGSerialPort::write_port(const char* buf, int len) {
463 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
465 LPCVOID lpBuffer = buf;
466 DWORD nNumberOfBytesToWrite = len;
467 DWORD lpNumberOfBytesWritten;
471 nNumberOfBytesToWrite,
472 &lpNumberOfBytesWritten,
477 FORMAT_MESSAGE_ALLOCATE_BUFFER |
478 FORMAT_MESSAGE_FROM_SYSTEM |
479 FORMAT_MESSAGE_IGNORE_INSERTS,
482 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
487 SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
488 << (const char*) lpMsgBuf );
489 LocalFree( lpMsgBuf );
490 return int(lpNumberOfBytesWritten);
493 return int(lpNumberOfBytesWritten);
497 static bool error = false;
501 // attempt some sort of error recovery
502 count = write(fd, "\n", 1);
504 // cout << "Serial error recover successful!\n";
511 count = write(fd, buf, len);
512 // cout << "write '" << buf << "' " << count << " bytes" << endl;
514 if ( (int)count == len ) {
518 if ( errno == EAGAIN ) {
519 // ok ... in our context we don't really care if we can't
520 // write a string, we'll just get it the next time around
522 SG_LOG( SG_IO, SG_ALERT,
523 "Serial I/O on write, error number = " << errno );