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