00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <simgear/compiler.h>
00025
00026 #include STL_IOSTREAM
00027
00028 #ifdef SG_HAVE_STD_INCLUDE
00029 # include <cerrno>
00030 #else
00031 # include <errno.h>
00032 #endif
00033
00034 #if !defined( WIN32 ) || defined( __CYGWIN__) || defined( __CYGWIN32__ )
00035 # include <termios.h>
00036 # include <sys/types.h>
00037 # include <sys/stat.h>
00038 # include <fcntl.h>
00039 # include <unistd.h>
00040 #endif
00041
00042 #include <simgear/debug/logstream.hxx>
00043
00044 #include "serial.hxx"
00045
00046 SGSerialPort::SGSerialPort()
00047 : dev_open(false)
00048 {
00049
00050 }
00051
00052 SGSerialPort::SGSerialPort(const string& device, int baud) {
00053 open_port(device);
00054
00055 if ( dev_open ) {
00056 set_baud(baud);
00057 }
00058 }
00059
00060 SGSerialPort::~SGSerialPort() {
00061
00062
00063
00064 }
00065
00066 bool SGSerialPort::open_port(const string& device) {
00067
00068 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
00069
00070 fd = CreateFile( device.c_str(),
00071 GENERIC_READ | GENERIC_WRITE,
00072 0,
00073 NULL,
00074 OPEN_EXISTING,
00075 0,
00076 NULL );
00077 if ( fd == INVALID_HANDLE_VALUE )
00078 {
00079 LPVOID lpMsgBuf;
00080 FormatMessage(
00081 FORMAT_MESSAGE_ALLOCATE_BUFFER |
00082 FORMAT_MESSAGE_FROM_SYSTEM |
00083 FORMAT_MESSAGE_IGNORE_INSERTS,
00084 NULL,
00085 GetLastError(),
00086 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00087 (LPTSTR) &lpMsgBuf,
00088 0,
00089 NULL );
00090
00091 SG_LOG( SG_IO, SG_ALERT, "Error opening serial device \""
00092 << device << "\" " << (const char*) lpMsgBuf );
00093 LocalFree( lpMsgBuf );
00094 return false;
00095 }
00096
00097 dev_open = true;
00098 return true;
00099
00100 #else
00101
00102 struct termios config;
00103
00104 fd = open(device.c_str(), O_RDWR | O_NOCTTY| O_NDELAY);
00105 SG_LOG( SG_EVENT, SG_DEBUG, "Serial fd created = " << fd);
00106
00107 if ( fd == -1 ) {
00108 SG_LOG( SG_IO, SG_ALERT, "Cannot open " << device
00109 << " for serial I/O" );
00110 return false;
00111 } else {
00112 dev_open = true;
00113 }
00114
00115
00116 if ( tcgetattr( fd, &config ) != 0 ) {
00117 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
00118 return false;
00119 }
00120
00121
00122
00123
00124
00125
00126 config.c_oflag &= ~(ONLCR);
00127
00128
00129 config.c_iflag &= ~(IXON | IXOFF | IXANY);
00130
00131
00132 config.c_cflag |= (CLOCAL | CREAD);
00133
00134 #if !defined( sgi ) && !defined(_AIX)
00135
00136 config.c_cflag &= ~(CRTSCTS);
00137 #endif
00138
00139
00140
00141
00142 config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
00143
00144 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
00145 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
00146 return false;
00147 }
00148
00149 return true;
00150 #endif
00151 }
00152
00153
00154 bool SGSerialPort::close_port() {
00155 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
00156 CloseHandle( fd );
00157 #else
00158 close(fd);
00159 #endif
00160
00161 dev_open = false;
00162
00163 return true;
00164 }
00165
00166
00167 bool SGSerialPort::set_baud(int baud) {
00168
00169 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
00170
00171 DCB dcb;
00172 if ( GetCommState( fd, &dcb ) ) {
00173 dcb.BaudRate = baud;
00174 dcb.fOutxCtsFlow = FALSE;
00175 dcb.fOutxDsrFlow = FALSE;
00176 dcb.fOutX = TRUE;
00177 dcb.fInX = TRUE;
00178
00179 if ( !SetCommState( fd, &dcb ) ) {
00180 LPVOID lpMsgBuf;
00181 FormatMessage(
00182 FORMAT_MESSAGE_ALLOCATE_BUFFER |
00183 FORMAT_MESSAGE_FROM_SYSTEM |
00184 FORMAT_MESSAGE_IGNORE_INSERTS,
00185 NULL,
00186 GetLastError(),
00187 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00188 (LPTSTR) &lpMsgBuf,
00189 0,
00190 NULL );
00191
00192 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings: "
00193 << (const char*) lpMsgBuf );
00194 LocalFree( lpMsgBuf );
00195 return false;
00196 }
00197 } else {
00198 LPVOID lpMsgBuf;
00199 FormatMessage(
00200 FORMAT_MESSAGE_ALLOCATE_BUFFER |
00201 FORMAT_MESSAGE_FROM_SYSTEM |
00202 FORMAT_MESSAGE_IGNORE_INSERTS,
00203 NULL,
00204 GetLastError(),
00205 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00206 (LPTSTR) &lpMsgBuf,
00207 0,
00208 NULL );
00209
00210 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings: "
00211 << (const char*) lpMsgBuf );
00212 LocalFree( lpMsgBuf );
00213 return false;
00214 }
00215
00216 return true;
00217
00218 #else
00219
00220 struct termios config;
00221 speed_t speed = B9600;
00222
00223 if ( tcgetattr( fd, &config ) != 0 ) {
00224 SG_LOG( SG_IO, SG_ALERT, "Unable to poll port settings" );
00225 return false;
00226 }
00227
00228 if ( baud == 300 ) {
00229 speed = B300;
00230 } else if ( baud == 1200 ) {
00231 speed = B1200;
00232 } else if ( baud == 2400 ) {
00233 speed = B2400;
00234 } else if ( baud == 4800 ) {
00235 speed = B4800;
00236 } else if ( baud == 9600 ) {
00237 speed = B9600;
00238 } else if ( baud == 19200 ) {
00239 speed = B19200;
00240 } else if ( baud == 38400 ) {
00241 speed = B38400;
00242 #if defined( linux ) || defined( __FreeBSD__ )
00243 } else if ( baud == 57600 ) {
00244 speed = B57600;
00245 } else if ( baud == 115200 ) {
00246 speed = B115200;
00247 } else if ( baud == 230400 ) {
00248 speed = B230400;
00249 #endif
00250 } else {
00251 SG_LOG( SG_IO, SG_ALERT, "Unsupported baud rate " << baud );
00252 return false;
00253 }
00254
00255 if ( cfsetispeed( &config, speed ) != 0 ) {
00256 SG_LOG( SG_IO, SG_ALERT, "Problem setting input baud rate" );
00257 return false;
00258 }
00259
00260 if ( cfsetospeed( &config, speed ) != 0 ) {
00261 SG_LOG( SG_IO, SG_ALERT, "Problem setting output baud rate" );
00262 return false;
00263 }
00264
00265 if ( tcsetattr( fd, TCSANOW, &config ) != 0 ) {
00266 SG_LOG( SG_IO, SG_ALERT, "Unable to update port settings" );
00267 return false;
00268 }
00269
00270 return true;
00271
00272 #endif
00273
00274 }
00275
00276 string SGSerialPort::read_port() {
00277
00278 const int max_count = 1024;
00279 char buffer[max_count+1];
00280 string result;
00281
00282 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
00283
00284 DWORD count;
00285 if ( ReadFile( fd, buffer, max_count, &count, 0 ) ) {
00286 buffer[count] = '\0';
00287 result = buffer;
00288 } else {
00289 LPVOID lpMsgBuf;
00290 FormatMessage(
00291 FORMAT_MESSAGE_ALLOCATE_BUFFER |
00292 FORMAT_MESSAGE_FROM_SYSTEM |
00293 FORMAT_MESSAGE_IGNORE_INSERTS,
00294 NULL,
00295 GetLastError(),
00296 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00297 (LPTSTR) &lpMsgBuf,
00298 0,
00299 NULL );
00300
00301 SG_LOG( SG_IO, SG_ALERT, "Serial I/O read error: "
00302 << (const char*) lpMsgBuf );
00303 LocalFree( lpMsgBuf );
00304 }
00305
00306 return result;
00307
00308 #else
00309
00310 int count = read(fd, buffer, max_count);
00311
00312
00313 if ( count < 0 ) {
00314
00315 if ( errno != EAGAIN ) {
00316 SG_LOG( SG_IO, SG_ALERT,
00317 "Serial I/O on read, error number = " << errno );
00318 }
00319
00320 return "";
00321 } else {
00322 buffer[count] = '\0';
00323 result = buffer;
00324
00325 return result;
00326 }
00327
00328 #endif
00329
00330 }
00331
00332 int SGSerialPort::read_port(char *buf, int len) {
00333
00334 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
00335
00336 DWORD count;
00337 if ( ReadFile( fd, buf, len, &count, 0 ) ) {
00338 buf[count] = '\0';
00339
00340 return count;
00341 } else {
00342 LPVOID lpMsgBuf;
00343 FormatMessage(
00344 FORMAT_MESSAGE_ALLOCATE_BUFFER |
00345 FORMAT_MESSAGE_FROM_SYSTEM |
00346 FORMAT_MESSAGE_IGNORE_INSERTS,
00347 NULL,
00348 GetLastError(),
00349 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00350 (LPTSTR) &lpMsgBuf,
00351 0,
00352 NULL );
00353
00354 SG_LOG( SG_IO, SG_ALERT, "Serial I/O read error: "
00355 << (const char*) lpMsgBuf );
00356 LocalFree( lpMsgBuf );
00357
00358 buf[0] = '\0';
00359 return 0;
00360 }
00361
00362 #else
00363
00364 string result;
00365
00366 int count = read(fd, buf, len);
00367
00368
00369 if ( count < 0 ) {
00370
00371 if ( errno != EAGAIN ) {
00372 SG_LOG( SG_IO, SG_ALERT,
00373 "Serial I/O on read, error number = " << errno );
00374 }
00375
00376 buf[0] = '\0';
00377 return 0;
00378 } else {
00379 buf[count] = '\0';
00380
00381 return count;
00382 }
00383
00384 #endif
00385
00386 }
00387
00388
00389 int SGSerialPort::write_port(const string& value) {
00390
00391 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
00392
00393 LPCVOID lpBuffer = value.data();
00394 DWORD nNumberOfBytesToWrite = value.length();
00395 DWORD lpNumberOfBytesWritten;
00396
00397 if ( WriteFile( fd,
00398 lpBuffer,
00399 nNumberOfBytesToWrite,
00400 &lpNumberOfBytesWritten,
00401 0 ) == 0 )
00402 {
00403 LPVOID lpMsgBuf;
00404 FormatMessage(
00405 FORMAT_MESSAGE_ALLOCATE_BUFFER |
00406 FORMAT_MESSAGE_FROM_SYSTEM |
00407 FORMAT_MESSAGE_IGNORE_INSERTS,
00408 NULL,
00409 GetLastError(),
00410 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00411 (LPTSTR) &lpMsgBuf,
00412 0,
00413 NULL );
00414
00415 SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
00416 << (const char*) lpMsgBuf );
00417 LocalFree( lpMsgBuf );
00418 return int(lpNumberOfBytesWritten);
00419 }
00420
00421 return int(lpNumberOfBytesWritten);
00422
00423 #else
00424
00425 static bool error = false;
00426 int count;
00427
00428 if ( error ) {
00429 SG_LOG( SG_IO, SG_ALERT, "attempting serial write error recovery" );
00430
00431 count = write(fd, "\n", 1);
00432 if ( count == 1 ) {
00433
00434 error = false;
00435 } else {
00436 return 0;
00437 }
00438 }
00439
00440 count = write(fd, value.c_str(), value.length());
00441
00442
00443 if ( (int)count == (int)value.length() ) {
00444 error = false;
00445 } else {
00446 if ( errno == EAGAIN ) {
00447
00448
00449 error = false;
00450 } else {
00451 error = true;
00452 SG_LOG( SG_IO, SG_ALERT,
00453 "Serial I/O on write, error number = " << errno );
00454 }
00455 }
00456
00457 return count;
00458
00459 #endif
00460
00461 }
00462
00463
00464 int SGSerialPort::write_port(const char* buf, int len) {
00465 #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined( __CYGWIN32__ )
00466
00467 LPCVOID lpBuffer = buf;
00468 DWORD nNumberOfBytesToWrite = len;
00469 DWORD lpNumberOfBytesWritten;
00470
00471 if ( WriteFile( fd,
00472 lpBuffer,
00473 nNumberOfBytesToWrite,
00474 &lpNumberOfBytesWritten,
00475 0 ) == 0 )
00476 {
00477 LPVOID lpMsgBuf;
00478 FormatMessage(
00479 FORMAT_MESSAGE_ALLOCATE_BUFFER |
00480 FORMAT_MESSAGE_FROM_SYSTEM |
00481 FORMAT_MESSAGE_IGNORE_INSERTS,
00482 NULL,
00483 GetLastError(),
00484 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00485 (LPTSTR) &lpMsgBuf,
00486 0,
00487 NULL );
00488
00489 SG_LOG( SG_IO, SG_ALERT, "Serial I/O write error: "
00490 << (const char*) lpMsgBuf );
00491 LocalFree( lpMsgBuf );
00492 return int(lpNumberOfBytesWritten);
00493 }
00494
00495 return int(lpNumberOfBytesWritten);
00496
00497 #else
00498
00499 static bool error = false;
00500 int count;
00501
00502 if ( error ) {
00503
00504 count = write(fd, "\n", 1);
00505 if ( count == 1 ) {
00506
00507 error = false;
00508 } else {
00509 return 0;
00510 }
00511 }
00512
00513 count = write(fd, buf, len);
00514
00515
00516 if ( (int)count == len ) {
00517 error = false;
00518 } else {
00519 error = true;
00520 if ( errno == EAGAIN ) {
00521
00522
00523 } else {
00524 SG_LOG( SG_IO, SG_ALERT,
00525 "Serial I/O on write, error number = " << errno );
00526 }
00527 }
00528
00529 return count;
00530
00531 #endif
00532
00533 }