/home/fwph/code/wurde/modules/sickLaser/serial.h

Go to the documentation of this file.
00001 /*********************************************************
00002  *
00003  * This source code is part of the Carnegie Mellon Robot
00004  * Navigation Toolkit (CARMEN)
00005  *
00006  * CARMEN Copyright (c) 2002 Michael Montemerlo, Nicholas
00007  * Roy, and Sebastian Thrun
00008  *
00009  * CARMEN is free software; you can redistribute it and/or 
00010  * modify it under the terms of the GNU General Public 
00011  * License as published by the Free Software Foundation; 
00012  * either version 2 of the License, or (at your option)
00013  * any later version.
00014  *
00015  * CARMEN is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied 
00017  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00018  * PURPOSE.  See the GNU General Public License for more 
00019  * details.
00020  *
00021  * You should have received a copy of the GNU General 
00022  * Public License along with CARMEN; if not, write to the
00023  * Free Software Foundation, Inc., 59 Temple Place, 
00024  * Suite 330, Boston, MA  02111-1307 USA
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      /* less than 1e6 */
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 /*__ATTRIBUTE__ ((unused))*/)
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   /* We generate mark and space parity ourself. */
00102   if(bit == '7' && (par[0] == 'M' || par[0] == 'S'))
00103     bit = '8';
00104   /* Check if 'baudr' is really a number */
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   /* Number of bits is ignored */
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   /* FIXME: huh? - MvS */
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   /* Set into raw, no echo mode */
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 /* Okay, this is better. XXX - Fix the above. */
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   /* Flow control. */
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 

Generated on Thu Feb 1 15:31:52 2007 for WURDE by  doxygen 1.5.1