00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdio.h>
00020 #include <errno.h>
00021 #include <unistd.h>
00022 #include <fcntl.h>
00023 #include <linux/serial.h>
00024 #include <termios.h>
00025 #include <sys/stat.h>
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <sys/time.h>
00029 #include <sys/ioctl.h>
00030
00031
00032 #include "LOW_portSerial_Linux.h"
00033 #include "LOW_helper_msglog.h"
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 LOW_portSerial_Linux::LOW_portSerial_Linux( const string inSerialPort) :
00044 serialPortPath( inSerialPort)
00045 {
00046
00047 if ( (serialFD=open( serialPortPath.c_str(), O_RDWR)) == -1 ) {
00048 throw portSerial_error( errno, "Error opening tty " + serialPortPath, __FILE__, __LINE__);
00049 }
00050 }
00051
00052
00053 LOW_portSerial_Linux::~LOW_portSerial_Linux()
00054 {
00055 close( serialFD);
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065 void LOW_portSerial_Linux::tty_configure( const flowControl_t inFlowCtl, const dataBitsSite_t inDataBits,
00066 const parity_t inParity, const stopBits_t inStopBits, const speed_t inSpeed) const
00067 {
00068 struct serial_struct serial;
00069 struct termios term;
00070
00071
00072 if ( ioctl( serialFD, TIOCGSERIAL, &serial) < 0 )
00073 throw portSerial_error( errno, "TIOCGSERIAL failed", __FILE__, __LINE__);
00074
00075
00076 if( tcgetattr( serialFD, &term) < 0 )
00077 throw portSerial_error( errno, "Error with tcgetattr", __FILE__, __LINE__);
00078
00079
00080 term.c_iflag = IGNBRK;
00081 term.c_oflag = 0;
00082 term.c_cflag = CREAD | HUPCL;
00083 term.c_lflag = 0;
00084
00085
00086
00087 switch ( inFlowCtl ) {
00088
00089 case none_flowControl:
00090 term.c_cflag |= CLOCAL;
00091 break;
00092
00093 case xonxoff_flowControl:
00094 term.c_iflag |= IXON | IXOFF;
00095 term.c_cflag |= CLOCAL;
00096 break;
00097
00098 case rtscts_flowControl:
00099 term.c_cflag |= CRTSCTS;
00100 break;
00101
00102 default:
00103 throw portSerial_error( "Unknown control parameter value", __FILE__, __LINE__);
00104 break;
00105 }
00106
00107 switch ( inParity ) {
00108
00109 case no_parity:
00110 term.c_iflag |= IGNPAR;
00111 break;
00112
00113 case odd_parity:
00114 term.c_iflag |= INPCK;
00115 term.c_cflag |= PARENB | PARODD;
00116 break;
00117
00118 case even_parity:
00119 term.c_iflag |= INPCK;
00120 term.c_cflag |= PARENB;
00121 break;
00122
00123 default:
00124 throw portSerial_error( "Unknown control parameter value", __FILE__, __LINE__);
00125 break;
00126 }
00127
00128 switch ( inDataBits ) {
00129
00130 case bit5_size:
00131 term.c_cflag |= CS5;
00132 break;
00133
00134 case bit6_size:
00135 term.c_cflag |= CS6;
00136 break;
00137
00138 case bit7_size:
00139 term.c_cflag |= CS7;
00140 break;
00141
00142 case bit8_size:
00143 term.c_cflag |= CS8;
00144 break;
00145
00146 default:
00147 throw portSerial_error( "Unknown control parameter value", __FILE__, __LINE__);
00148 break;
00149 }
00150
00151 switch ( inStopBits ) {
00152
00153 case bit1_stopBit:
00154 break;
00155
00156 case bit2_stopBit:
00157 term.c_cflag |= CSTOPB;
00158 break;
00159
00160 default:
00161 throw portSerial_error( "Unknown control parameter value", __FILE__, __LINE__);
00162 break;
00163 }
00164
00165 int speed = 0;
00166 switch ( inSpeed ) {
00167 case B50_speed: speed = B50; break;
00168 case B75_speed: speed = B75; break;
00169 case B110_speed: speed = B110; break;
00170 case B134_speed: speed = B134; break;
00171 case B150_speed: speed = B150; break;
00172 case B200_speed: speed = B200; break;
00173 case B300_speed: speed = B300; break;
00174 case B600_speed: speed = B600; break;
00175 case B1200_speed: speed = B1200; break;
00176 case B1800_speed: speed = B1800; break;
00177 case B2400_speed: speed = B2400; break;
00178 case B4800_speed: speed = B4800; break;
00179 case B9600_speed: speed = B9600; break;
00180 case B19200_speed: speed = B19200; break;
00181 case B38400_speed: speed = B38400; break;
00182 case B57600_speed: speed = B57600; break;
00183 case B115200_speed: speed = B115200; break;
00184
00185 case B10472_speed: speed = B38400; break;
00186
00187 default:
00188 throw portSerial_error( "Unknown control parameter value", __FILE__, __LINE__);
00189 break;
00190 }
00191 cfsetospeed( &term, speed);
00192 cfsetispeed( &term, speed);
00193
00194 if ( inSpeed == B10472_speed ) {
00195 serial.flags = (serial.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
00196 serial.custom_divisor = 11;
00197 }
00198 else {
00199 serial.flags = (serial.flags & ~ASYNC_SPD_MASK);
00200 }
00201
00202
00203 term.c_cc[VMIN] = 1;
00204 term.c_cc[VTIME] = 0;
00205
00206 if ( ioctl( serialFD, TIOCSSERIAL, &serial) < 0 )
00207 throw portSerial_error( errno, "TIOCSSERIAL failed", __FILE__, __LINE__);
00208
00209 if( tcsetattr( serialFD, TCSAFLUSH, &term ) < 0 )
00210 throw portSerial_error( errno, "Error with tcsetattr", __FILE__, __LINE__);
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 void LOW_portSerial_Linux::tty_flush( const bool inFlushIn, const bool inFlushOut) const
00283 {
00284 if ( inFlushIn && !inFlushOut ) {
00285 tcflush( serialFD, TCIFLUSH);
00286 }
00287 else if ( !inFlushIn && inFlushOut ) {
00288 tcflush( serialFD, TCOFLUSH);
00289 }
00290 else if ( inFlushIn && inFlushOut ) {
00291 tcflush( serialFD, TCIOFLUSH);
00292 }
00293 }
00294
00295
00296 void LOW_portSerial_Linux::tty_break() const
00297 {
00298 tcsendbreak( serialFD, 20);
00299 }
00300
00301
00302 uint8_t LOW_portSerial_Linux::tty_readByte( const bool inTrashExtraReply) const
00303 {
00304 fd_set readset;
00305 struct timeval wait_tm;
00306 int selRet;
00307 uint8_t retVal = 0;
00308
00309 for( int a=0; a<((inTrashExtraReply==true)?2:1); a++) {
00310
00311 while ( true ) {
00312
00313
00314 wait_tm.tv_usec = 0;
00315 wait_tm.tv_sec = serialTimeout;
00316 FD_ZERO( &readset);
00317 FD_SET( serialFD, &readset);
00318
00319
00320 selRet = select( serialFD+1, &readset, NULL, NULL, &wait_tm);
00321 if( selRet > 0 ) {
00322
00323 if( FD_ISSET( serialFD, &readset) )
00324 {
00325 uint8_t readByte;
00326
00327 if ( read( serialFD, &readByte, 1) != 1 )
00328 throw portSerial_error( "Unexpected short read", __FILE__, __LINE__);
00329
00330 if ( a == 0 )
00331 retVal = readByte;
00332
00333 LOW_helper_msglog::printDebug( LOW_helper_msglog::portSerial_dl, "LOW_linkDS2480B: TTY READ: %02x read cycle: %d\n", readByte, a);
00334
00335 break;
00336 }
00337
00338 }
00339 else if ( selRet == 0 ) {
00340 throw portSerial_error( "TTY operation timed out", __FILE__, __LINE__);
00341 }
00342 else {
00343 throw portSerial_error( errno, "Unexpected error in select call", __FILE__, __LINE__);
00344 }
00345
00346 }
00347 }
00348
00349 return retVal;
00350 }
00351
00352
00353 void LOW_portSerial_Linux::tty_read( byteVec_t &outReadBytes, const bool inTrashExtraReply) const
00354 {
00355 for( unsigned int a=0; a<outReadBytes.size(); a++) {
00356 outReadBytes[a] = tty_readByte( inTrashExtraReply);
00357 }
00358 }
00359
00360
00361 void LOW_portSerial_Linux::tty_write( const uint8_t inWriteByte) const
00362 {
00363 int written;
00364
00365 LOW_helper_msglog::printDebug( LOW_helper_msglog::portSerial_dl, "LOW_linkDS2480B: TTY WRITE: %02x\n", inWriteByte);
00366 do {
00367 written = write( serialFD, &inWriteByte, 1);
00368 if ( written == -1 )
00369 throw portSerial_error( errno, "Error writing single byte to TTY", __FILE__, __LINE__);
00370 tcdrain( serialFD);
00371 }
00372 while ( written != 1 );
00373 }
00374
00375
00376 void LOW_portSerial_Linux::tty_write( const byteVec_t &inWriteBytes) const
00377 {
00378 unsigned int total = inWriteBytes.size();
00379 uint8_t *buffer = (uint8_t*)malloc( total);;
00380
00381 try {
00382
00383 for( unsigned int a=0; a<total; a++) {
00384 buffer[a] = inWriteBytes[a];
00385 LOW_helper_msglog::printDebug( LOW_helper_msglog::portSerial_dl, "LOW_linkDS2480B: TTY WRITE: %02x\n", buffer[a]);
00386 }
00387
00388 int written = 0;
00389 unsigned int remaining = total;
00390 uint8_t *writePtr = buffer;
00391 do {
00392
00393 written = write( serialFD, writePtr, (remaining<4)?remaining:4);
00394 if ( written == -1 )
00395 throw portSerial_error( errno, "Error writing byte block to TTY", __FILE__, __LINE__);
00396 tcdrain( serialFD);
00397 remaining -= written;
00398 writePtr += written;
00399 }
00400 while ( remaining != 0);
00401 }
00402 catch( ... ) {
00403 free( buffer);
00404 throw;
00405 }
00406
00407 free( buffer);
00408 }
00409