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 SGSerialPort::SGSerialPort()
55 SGSerialPort::SGSerialPort(const string& device, int baud) {
63 SGSerialPort::~SGSerialPort() {
64 // closing the port here screws us up because if we would even so
65 // much as make a copy of an SGSerialPort object and then delete it,
66 // the file descriptor gets closed. Doh!!!
69 bool SGSerialPort::open_port(const string& device) {
71 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
73 fd = CreateFile( device.c_str(),
74 GENERIC_READ | GENERIC_WRITE,
76 NULL, // lpSecurityAttributes
80 if ( fd == INVALID_HANDLE_VALUE )
84 FORMAT_MESSAGE_ALLOCATE_BUFFER |
85 FORMAT_MESSAGE_FROM_SYSTEM |
86 FORMAT_MESSAGE_IGNORE_INSERTS,
89 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
94 SG_LOG( SG_IO, SG_ALERT, "Error opening serial device \""
95 << device << "\" " << (const char*) lpMsgBuf );
96 LocalFree( lpMsgBuf );
105 struct termios config;
107 fd = open(device.c_str(), O_RDWR | O_NONBLOCK);
108 SG_LOG( SG_EVENT, SG_DEBUG, "Serial fd created = " << fd);
111 SG_LOG( SG_IO, SG_ALERT, "Cannot open " << device
112 << " for serial I/O" );
118 // set required port parameters
119 if ( tcgetattr( fd, &config ) != 0 ) {
120 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
124 // cfmakeraw( &config );
126 // cout << "config.c_iflag = " << config.c_iflag << endl;
128 // software flow control on
129 config.c_iflag |= IXON;
130 // config.c_iflag |= IXOFF;
132 // config.c_cflag |= CLOCAL;
135 // disable hardware flow control
136 config.c_cflag &= ~(CRTSCTS);
139 // cout << "config.c_iflag = " << config.c_iflag << endl;
141 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
142 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
151 bool SGSerialPort::close_port() {
152 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
164 bool SGSerialPort::set_baud(int baud) {
166 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
172 struct termios config;
173 speed_t speed = B9600;
175 if ( tcgetattr( fd, &config ) != 0 ) {
176 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
182 } else if ( baud == 1200 ) {
184 } else if ( baud == 2400 ) {
186 } else if ( baud == 4800 ) {
188 } else if ( baud == 9600 ) {
190 } else if ( baud == 19200 ) {
192 } else if ( baud == 38400 ) {
194 } else if ( baud == 57600 ) {
196 } else if ( baud == 115200 ) {
198 #if defined( linux ) || defined( __FreeBSD__ )
199 } else if ( baud == 230400 ) {
203 SG_LOG( SG_IO, SG_ALERT, "Unsupported baud rate " << baud );
207 if ( cfsetispeed( &config, speed ) != 0 ) {
208 SG_LOG( SG_IO, SG_ALERT, "Problem setting input baud rate" );
212 if ( cfsetospeed( &config, speed ) != 0 ) {
213 SG_LOG( SG_IO, SG_ALERT, "Problem setting output baud rate" );
217 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
218 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
228 string SGSerialPort::read_port() {
230 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
237 const int max_count = 1024;
238 char buffer[max_count+1];
242 count = read(fd, buffer, max_count);
243 // cout << "read " << count << " bytes" << endl;
247 if ( errno != EAGAIN ) {
248 SG_LOG( SG_IO, SG_ALERT,
249 "Serial I/O on read, error number = " << errno );
254 buffer[count] = '\0';
264 int SGSerialPort::read_port(char *buf, int len) {
266 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
275 int count = read(fd, buf, len);
276 // cout << "read " << count << " bytes" << endl;
280 if ( errno != EAGAIN ) {
281 SG_LOG( SG_IO, SG_ALERT,
282 "Serial I/O on read, error number = " << errno );
298 int SGSerialPort::write_port(const string& value) {
300 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
302 LPCVOID lpBuffer = value.c_str();
303 DWORD nNumberOfBytesToWrite = value.length();
304 DWORD lpNumberOfBytesWritten;
305 OVERLAPPED lpOverlapped;
309 nNumberOfBytesToWrite,
310 &lpNumberOfBytesWritten,
311 &lpOverlapped ) == 0 )
315 FORMAT_MESSAGE_ALLOCATE_BUFFER |
316 FORMAT_MESSAGE_FROM_SYSTEM |
317 FORMAT_MESSAGE_IGNORE_INSERTS,
320 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
325 SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
326 << (const char*) lpMsgBuf );
327 LocalFree( lpMsgBuf );
328 return int(lpNumberOfBytesWritten);
331 return int(lpNumberOfBytesWritten);
335 static bool error = false;
339 SG_LOG( SG_IO, SG_ALERT, "attempting serial write error recovery" );
340 // attempt some sort of error recovery
341 count = write(fd, "\n", 1);
343 // cout << "Serial error recover successful!\n";
350 count = write(fd, value.c_str(), value.length());
351 // cout << "write '" << value << "' " << count << " bytes" << endl;
353 if ( (int)count == (int)value.length() ) {
356 if ( errno == EAGAIN ) {
357 // ok ... in our context we don't really care if we can't
358 // write a string, we'll just get it the next time around
362 SG_LOG( SG_IO, SG_ALERT,
363 "Serial I/O on write, error number = " << errno );
374 int SGSerialPort::write_port(const char* buf, int len) {
375 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
377 LPCVOID lpBuffer = buf;
378 DWORD nNumberOfBytesToWrite = len;
379 DWORD lpNumberOfBytesWritten;
380 OVERLAPPED lpOverlapped;
384 nNumberOfBytesToWrite,
385 &lpNumberOfBytesWritten,
386 &lpOverlapped ) == 0 )
390 FORMAT_MESSAGE_ALLOCATE_BUFFER |
391 FORMAT_MESSAGE_FROM_SYSTEM |
392 FORMAT_MESSAGE_IGNORE_INSERTS,
395 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
400 SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
401 << (const char*) lpMsgBuf );
402 LocalFree( lpMsgBuf );
403 return int(lpNumberOfBytesWritten);
406 return int(lpNumberOfBytesWritten);
410 static bool error = false;
414 // attempt some sort of error recovery
415 count = write(fd, "\n", 1);
417 // cout << "Serial error recover successful!\n";
424 count = write(fd, buf, len);
425 // cout << "write '" << buf << "' " << count << " bytes" << endl;
427 if ( (int)count == len ) {
431 if ( errno == EAGAIN ) {
432 // ok ... in our context we don't really care if we can't
433 // write a string, we'll just get it the next time around
435 SG_LOG( SG_IO, SG_ALERT,
436 "Serial I/O on write, error number = " << errno );