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__ )
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_NONBLOCK);
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 // software flow control on
127 config.c_iflag |= IXON;
128 // config.c_iflag |= IXOFF;
130 // config.c_cflag |= CLOCAL;
133 // disable hardware flow control
134 config.c_cflag &= ~(CRTSCTS);
137 // cout << "config.c_iflag = " << config.c_iflag << endl;
139 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
140 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
149 bool SGSerialPort::close_port() {
150 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
162 bool SGSerialPort::set_baud(int baud) {
164 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
167 if ( GetCommState( fd, &dcb ) ) {
169 dcb.fOutxCtsFlow = FALSE;
170 dcb.fOutxDsrFlow = FALSE;
174 if ( !SetCommState( fd, &dcb ) ) {
177 FORMAT_MESSAGE_ALLOCATE_BUFFER |
178 FORMAT_MESSAGE_FROM_SYSTEM |
179 FORMAT_MESSAGE_IGNORE_INSERTS,
182 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
187 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings: "
188 << (const char*) lpMsgBuf );
189 LocalFree( lpMsgBuf );
195 FORMAT_MESSAGE_ALLOCATE_BUFFER |
196 FORMAT_MESSAGE_FROM_SYSTEM |
197 FORMAT_MESSAGE_IGNORE_INSERTS,
200 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
205 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings: "
206 << (const char*) lpMsgBuf );
207 LocalFree( lpMsgBuf );
215 struct termios config;
216 speed_t speed = B9600;
218 if ( tcgetattr( fd, &config ) != 0 ) {
219 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
225 } else if ( baud == 1200 ) {
227 } else if ( baud == 2400 ) {
229 } else if ( baud == 4800 ) {
231 } else if ( baud == 9600 ) {
233 } else if ( baud == 19200 ) {
235 } else if ( baud == 38400 ) {
237 } else if ( baud == 57600 ) {
239 } else if ( baud == 115200 ) {
241 #if defined( linux ) || defined( __FreeBSD__ )
242 } else if ( baud == 230400 ) {
246 SG_LOG( SG_IO, SG_ALERT, "Unsupported baud rate " << baud );
250 if ( cfsetispeed( &config, speed ) != 0 ) {
251 SG_LOG( SG_IO, SG_ALERT, "Problem setting input baud rate" );
255 if ( cfsetospeed( &config, speed ) != 0 ) {
256 SG_LOG( SG_IO, SG_ALERT, "Problem setting output baud rate" );
260 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
261 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
271 string SGSerialPort::read_port() {
273 const int max_count = 1024;
274 char buffer[max_count+1];
277 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
280 if ( ReadFile( fd, buffer, max_count, &count, 0 ) ) {
281 buffer[count] = '\0';
286 FORMAT_MESSAGE_ALLOCATE_BUFFER |
287 FORMAT_MESSAGE_FROM_SYSTEM |
288 FORMAT_MESSAGE_IGNORE_INSERTS,
291 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
296 SG_LOG( SG_IO, SG_ALERT, "Serial I/O read error: "
297 << (const char*) lpMsgBuf );
298 LocalFree( lpMsgBuf );
305 int count = read(fd, buffer, max_count);
306 // cout << "read " << count << " bytes" << endl;
310 if ( errno != EAGAIN ) {
311 SG_LOG( SG_IO, SG_ALERT,
312 "Serial I/O on read, error number = " << errno );
317 buffer[count] = '\0';
327 int SGSerialPort::read_port(char *buf, int len) {
329 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
332 if ( ReadFile( fd, buf, len, &count, 0 ) ) {
339 FORMAT_MESSAGE_ALLOCATE_BUFFER |
340 FORMAT_MESSAGE_FROM_SYSTEM |
341 FORMAT_MESSAGE_IGNORE_INSERTS,
344 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
349 SG_LOG( SG_IO, SG_ALERT, "Serial I/O read error: "
350 << (const char*) lpMsgBuf );
351 LocalFree( lpMsgBuf );
361 int count = read(fd, buf, len);
362 // cout << "read " << count << " bytes" << endl;
366 if ( errno != EAGAIN ) {
367 SG_LOG( SG_IO, SG_ALERT,
368 "Serial I/O on read, error number = " << errno );
384 int SGSerialPort::write_port(const string& value) {
386 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
388 LPCVOID lpBuffer = value.data();
389 DWORD nNumberOfBytesToWrite = value.length();
390 DWORD lpNumberOfBytesWritten;
394 nNumberOfBytesToWrite,
395 &lpNumberOfBytesWritten,
400 FORMAT_MESSAGE_ALLOCATE_BUFFER |
401 FORMAT_MESSAGE_FROM_SYSTEM |
402 FORMAT_MESSAGE_IGNORE_INSERTS,
405 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
410 SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
411 << (const char*) lpMsgBuf );
412 LocalFree( lpMsgBuf );
413 return int(lpNumberOfBytesWritten);
416 return int(lpNumberOfBytesWritten);
420 static bool error = false;
424 SG_LOG( SG_IO, SG_ALERT, "attempting serial write error recovery" );
425 // attempt some sort of error recovery
426 count = write(fd, "\n", 1);
428 // cout << "Serial error recover successful!\n";
435 count = write(fd, value.c_str(), value.length());
436 // cout << "write '" << value << "' " << count << " bytes" << endl;
438 if ( (int)count == (int)value.length() ) {
441 if ( errno == EAGAIN ) {
442 // ok ... in our context we don't really care if we can't
443 // write a string, we'll just get it the next time around
447 SG_LOG( SG_IO, SG_ALERT,
448 "Serial I/O on write, error number = " << errno );
459 int SGSerialPort::write_port(const char* buf, int len) {
460 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
462 LPCVOID lpBuffer = buf;
463 DWORD nNumberOfBytesToWrite = len;
464 DWORD lpNumberOfBytesWritten;
468 nNumberOfBytesToWrite,
469 &lpNumberOfBytesWritten,
474 FORMAT_MESSAGE_ALLOCATE_BUFFER |
475 FORMAT_MESSAGE_FROM_SYSTEM |
476 FORMAT_MESSAGE_IGNORE_INSERTS,
479 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
484 SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
485 << (const char*) lpMsgBuf );
486 LocalFree( lpMsgBuf );
487 return int(lpNumberOfBytesWritten);
490 return int(lpNumberOfBytesWritten);
494 static bool error = false;
498 // attempt some sort of error recovery
499 count = write(fd, "\n", 1);
501 // cout << "Serial error recover successful!\n";
508 count = write(fd, buf, len);
509 // cout << "write '" << buf << "' " << count << " bytes" << endl;
511 if ( (int)count == len ) {
515 if ( errno == EAGAIN ) {
516 // ok ... in our context we don't really care if we can't
517 // write a string, we'll just get it the next time around
519 SG_LOG( SG_IO, SG_ALERT,
520 "Serial I/O on write, error number = " << errno );