00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <math.h>
00031 #include <termios.h>
00032 #include <unistd.h>
00033 #include <fcntl.h>
00034 #include <errno.h>
00035 #include <string.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <sys/ioctl.h>
00039 #include <sys/time.h>
00040
00041 #define READ_TIMEOUT 250000
00042 #define _POSIX
00043
00044 int carmen_serial_connect(int *dev_fd, char *dev_name)
00045 {
00046 int BAUDRATE = B9600;
00047 struct termios newtio;
00048
00049 *dev_fd = open(dev_name, O_RDWR | O_SYNC | O_NOCTTY, 0);
00050 if(*dev_fd < 0) {
00051 fprintf(stderr,"Serial I/O Error: Could not open port %s\n", dev_name);
00052 return -1;
00053 }
00054 tcgetattr(*dev_fd, &newtio);
00055 cfsetispeed(&newtio, BAUDRATE);
00056 cfsetospeed(&newtio, BAUDRATE);
00057 newtio.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
00058 newtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF);
00059 newtio.c_cflag &= ~(CSIZE | PARENB | PARODD);
00060 newtio.c_cflag |= (CS8);
00061 newtio.c_oflag &= ~(OPOST);
00062 newtio.c_cc[VTIME] = 1;
00063 newtio.c_cc[VMIN] = 0;
00064 tcflush(*dev_fd, TCIFLUSH);
00065 tcsetattr(*dev_fd, TCSANOW, &newtio);
00066 return 0;
00067 }
00068
00069 #if (defined(TIOCM_RTS) && defined(TIOCMODG)) || defined(_COHERENT)
00070 void carmen_serial_setrts(int fd)
00071 #else
00072 void carmen_serial_setrts(int fd )
00073 #endif
00074 {
00075 #if defined(TIOCM_RTS) && defined(TIOCMODG)
00076 int mcs = 0;
00077
00078 ioctl(fd, TIOCMODG, &mcs);
00079 mcs |= TIOCM_RTS;
00080 ioctl(fd, TIOCMODS, &mcs);
00081 #endif
00082 #ifdef _COHERENT
00083 ioctl(fd, TIOCSRTS, 0);
00084 #endif
00085 }
00086
00087 void carmen_serial_setparms(int fd, char *baudr, char *par, char *bits,
00088 int hwf, int swf)
00089 {
00090 int spd = -1;
00091 int newbaud = 0;
00092 int bit = bits[0];
00093 #ifdef _POSIX
00094 struct termios tty;
00095 tcgetattr(fd, &tty);
00096 #else
00097 struct sgttyb tty;
00098 ioctl(fd, TIOCGETP, &tty);
00099 #endif
00100
00101
00102 if(bit == '7' && (par[0] == 'M' || par[0] == 'S'))
00103 bit = '8';
00104
00105 if((newbaud = (atol(baudr) / 100)) == 0 && baudr[0] != '0')
00106 newbaud = -1;
00107
00108 switch(newbaud) {
00109 case 0:
00110 #ifdef B0
00111 spd = B0; break;
00112 #else
00113 spd = 0; break;
00114 #endif
00115 case 3:
00116 spd = B300; break;
00117 case 6:
00118 spd = B600; break;
00119 case 12:
00120 spd = B1200; break;
00121 case 24:
00122 spd = B2400; break;
00123 case 48:
00124 spd = B4800; break;
00125 case 96:
00126 spd = B9600; break;
00127 #ifdef B19200
00128 case 192:
00129 spd = B19200; break;
00130 #else
00131 #ifdef EXTA
00132 case 192:
00133 spd = EXTA; break;
00134 #else
00135 case 192:
00136 spd = B9600; break;
00137 #endif
00138 #endif
00139 #ifdef B38400
00140 case 384:
00141 spd = B38400; break;
00142 #else
00143 #ifdef EXTB
00144 case 384:
00145 spd = EXTB; break;
00146 #else
00147 case 384:
00148 spd = B9600; break;
00149 #endif
00150 #endif
00151 #ifdef B57600
00152 case 576:
00153 spd = B57600; break;
00154 #endif
00155 #ifdef B115200
00156 case 1152:
00157 spd = B115200; break;
00158 #endif
00159 #ifdef B500000
00160 case 5000:
00161 spd = B500000; break;
00162 #endif
00163 }
00164
00165 #if defined (_BSD43) && !defined(_POSIX)
00166 if(spd != -1) tty.sg_ispeed = tty.sg_ospeed = spd;
00167
00168 tty.sg_flags = RAW | TANDEM;
00169 if(par[0] == 'E')
00170 tty.sg_flags |= EVENP;
00171 else if(par[0] == 'O')
00172 tty.sg_flags |= ODDP;
00173 else
00174 tty.sg_flags |= PASS8 | ANYP;
00175 ioctl(fd, TIOCSETP, &tty);
00176 #ifdef TIOCSDTR
00177
00178 ioctl(fd, TIOCSDTR, 0);
00179 #endif
00180 #endif
00181
00182 #if defined (_V7) && !defined(_POSIX)
00183 if(spd != -1) tty.sg_ispeed = tty.sg_ospeed = spd;
00184 tty.sg_flags = RAW;
00185 if(par[0] == 'E')
00186 tty.sg_flags |= EVENP;
00187 else if(par[0] == 'O')
00188 tty.sg_flags |= ODDP;
00189 ioctl(fd, TIOCSETP, &tty);
00190 #endif
00191
00192 #ifdef _POSIX
00193 if(spd != -1) {
00194 cfsetospeed(&tty, (speed_t)spd);
00195 cfsetispeed(&tty, (speed_t)spd);
00196 }
00197 switch (bit) {
00198 case '5':
00199 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5;
00200 break;
00201 case '6':
00202 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6;
00203 break;
00204 case '7':
00205 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7;
00206 break;
00207 case '8':
00208 default:
00209 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
00210 break;
00211 }
00212
00213 #if !defined(_DGUX_SOURCE)
00214 tty.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC |
00215 IXANY | IXON | IXOFF | INPCK | ISTRIP);
00216 tty.c_iflag |= (BRKINT | IGNPAR);
00217 tty.c_oflag &= ~OPOST;
00218 tty.c_lflag = ~(ICANON | ISIG | ECHO | ECHONL | ECHOE | ECHOK | IEXTEN);
00219 tty.c_cflag |= CREAD | CRTSCTS;
00220 #else
00221 tty.c_iflag = IGNBRK;
00222 tty.c_lflag = 0;
00223 tty.c_oflag = 0;
00224 tty.c_cflag |= CLOCAL | CREAD;
00225 #endif
00226 tty.c_cc[VMIN] = 1;
00227 tty.c_cc[VTIME] = 5;
00228
00229
00230 if(hwf) {
00231 tty.c_cflag |= CRTSCTS;
00232 tty.c_cflag &= ~CLOCAL;
00233 }
00234 else {
00235 tty.c_cflag &= ~CRTSCTS;
00236 tty.c_cflag |= CLOCAL;
00237 }
00238
00239 if(swf) {
00240 tty.c_iflag |= (IXON | IXOFF);
00241 }
00242 else {
00243 tty.c_iflag &= ~(IXON | IXOFF);
00244 }
00245
00246 tty.c_cflag &= ~(PARENB | PARODD);
00247
00248 if(par[0] == 'E')
00249 tty.c_cflag |= PARENB;
00250 else if(par[0] == 'O')
00251 tty.c_cflag |= PARODD;
00252
00253 tcsetattr(fd, TCSANOW, &tty);
00254
00255 carmen_serial_setrts(fd);
00256 #ifdef _DGUX_SOURCE
00257 serial_sethwf(fd, hwf);
00258 #endif
00259 #endif
00260 }
00261
00262 void carmen_serial_configure(int dev_fd, int baudrate, char *parity)
00263 {
00264 switch(baudrate) {
00265 case 9600:
00266 carmen_serial_setparms(dev_fd, "9600", parity, "8", 0, 0);
00267 break;
00268 case 19200:
00269 carmen_serial_setparms(dev_fd, "19200", parity, "8", 0, 0);
00270 break;
00271 case 38400:
00272 carmen_serial_setparms(dev_fd, "38400", parity, "8", 0, 0);
00273 break;
00274 case 57600:
00275 case 55555:
00276 carmen_serial_setparms(dev_fd, "57600", parity, "8", 0, 0);
00277 break;
00278 case 500000:
00279 carmen_serial_setparms(dev_fd, "500000", parity, "8", 0, 0);
00280 break;
00281 }
00282 }
00283
00284 long carmen_serial_numChars(int dev_fd)
00285 {
00286 long available = 0;
00287
00288 if(ioctl(dev_fd, FIONREAD, &available) == 0)
00289 return available;
00290 else
00291 return -1;
00292 }
00293
00294 int carmen_serial_ClearInputBuffer(int dev_fd)
00295 {
00296 unsigned char buffer[4096];
00297 int val = 0;
00298
00299 val = carmen_serial_numChars(dev_fd);
00300 if(val > 0)
00301 read(dev_fd, &buffer, val);
00302 return(val);
00303 }
00304
00305 int carmen_serial_writen(int dev_fd, char *buf, int nChars)
00306 {
00307 int amountWritten = 0;
00308
00309 while(nChars > 0) {
00310 amountWritten = write(dev_fd, buf, nChars);
00311 if(amountWritten < 0) {
00312 if(errno == EWOULDBLOCK) {
00313 fprintf(stderr, "\nWARNING: writeN: EWOULDBLOCK: trying again!\n");
00314 }
00315 else {
00316 return -1;
00317 }
00318 }
00319 else {
00320 nChars -= amountWritten;
00321 buf += amountWritten;
00322 }
00323 }
00324 return 0;
00325 }
00326
00327 int carmen_serial_readn(int dev_fd, char *buf, int nChars)
00328 {
00329 int amountRead = 0, bytes_read = 0;
00330 struct timeval t;
00331 fd_set set;
00332 int err;
00333
00334 while(nChars > 0) {
00335 t.tv_sec = 0;
00336 t.tv_usec = READ_TIMEOUT;
00337 FD_ZERO(&set);
00338 FD_SET(dev_fd, &set);
00339 err = select(dev_fd + 1, &set, NULL, NULL, &t);
00340 if(err == 0)
00341 return -2;
00342
00343 amountRead = read(dev_fd, buf, nChars);
00344 if(amountRead < 0 && errno != EWOULDBLOCK)
00345 return -1;
00346 else if(amountRead > 0) {
00347 bytes_read += amountRead;
00348 nChars -= amountRead;
00349 buf += amountRead;
00350 }
00351 }
00352 return bytes_read;
00353 }
00354