Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages | Examples

common.c

Go to the documentation of this file.
00001 /************************************************************************************************/
00002 /*! \file common.c
00003 *  \brief Communicate with serial device.
00004 *  \author $Author: jayhawk_hokie $
00005 *  \version $Revision: 1.6 $
00006 *  \date    $Date: 2007/08/02 23:18:28 $
00007 ************************************************************************************************/
00008 /*!
00009 *
00010 ************************************************************************************************/
00011 
00012 
00013 #include "satctl.h"
00014 #include "common.h"
00015 
00016 /*! \brief Initialize serial port \n
00017  *      The presumption was that we'd always be talking
00018  *      exclusively to devices in 8N1.  Now, to use 2 stop bits, we had to use
00019  *      a define to avoid rewriting all the code that uses init_serial as it is
00020  *      already written.  Any major version change should incorporate an option
00021  *      for doing this properly in the code.
00022  *      @param *portfn pointer to port file name
00023  *      @param brate
00024  *      @param *portfd pointer to port file descripter 
00025  *      @return int 0 if successful 
00026 */
00027 int init_serial(char *portfn, speed_t brate, int *portfd) {
00028         struct termios tty;             /* tty termios attrib structure */
00029         int mcs;                        /* Modem-control settings flags */
00030 
00031         portfd[0] = open( portfn, O_RDWR | O_NOCTTY );  /* Open the port - a more common call to open port */
00032         /* portfd[0] = open( portfn, O_RDWR ); */                       /* Open the port - orginally set */
00033         if (portfd[0] == -1) return(-1);
00034 
00035         tcgetattr(portfd[0], &tty);             /* Get the port attributes */
00036         cfsetospeed(&tty, brate);               /* Put outrate in tty struct */
00037         cfsetispeed(&tty, brate);               /* Put inrate in tty struct */
00038 /* This was an oversight.  The presumption was that we'd always be talking
00039  * exclusively to devices in 8N1.  Now, to use 2 stop bits, we had to use
00040  * a define to avoid rewriting all the code that uses init_serial as it is
00041  * already written.  Any major version change should incorporate an option
00042  * for doing this properly in the code.
00043  */
00044 #ifndef TSB
00045   tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;   /* Set 8 data bits */
00046 #else
00047   tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8 | CSTOPB;
00048                                         /* Set 8 data bits & 2 stop bits */
00049 #endif
00050 
00051         /* Set raw, no echo mode */
00052         tty.c_iflag = (IGNBRK | IXON | IXOFF | IXANY); /* Set ingore-breaks - added for software flow control 
00053                 (MIGHT CAUSE PROBLEMS FOR OTHER DEVICES) */
00054         /* tty.c_iflag = IGNBRK; */                     /* Set ingore-breaks */
00055         tty.c_lflag = 0;                        /* Clear local modes flag */
00056         tty.c_oflag = 0;                        /* Clear output modes flag */
00057         tty.c_cflag |= CLOCAL | CREAD;  /* Ignore modem ctrl/ enable rcvr */
00058         tcsetattr(portfd[0], TCSANOW, &tty);    /* Effect flags, active now */
00059 
00060         /* Set RTS line */
00061         ioctl(portfd[0], TIOCMGET, &mcs);       /* Get modem-control flags */
00062         mcs |= TIOCM_RTS | TIOCM_DTR;           /* Modify modem-control flags */
00063         ioctl(portfd[0], TIOCMSET, &mcs);       /* Put modem-control flags */
00064 
00065         /* Port is ready for use */
00066         return(0);
00067 }
00068 
00069 /*! \brief Send data string to serial port
00070  *      @param fd file descriptor for port
00071  *      @param *str pointer to return string
00072 *       @return int 0 if successful 
00073 */
00074 int say(int fd, char *str) {
00075         static int wrote;                       /* Number of bytes written */
00076         static int slen;                        /* Length of submitted string */
00077 
00078         slen = strlen(str);                     /* Get # bytes to write */
00079         /* Debug */  
00080                 /*if (debug>4)
00081                 fprintf(stderr, "writing \"%s\" (len: %d) to %d\n", str, slen+2, fd);*/
00082   
00083                 /*tmp = (char *)malloc(slen+3);         * Allocate buffer accordingly */
00084                 /*strcpy(tmp, str);                     * Copy and add 2 EOL's & a NULL */
00085                 /*tmp[slen++] = eol[0];
00086                 tmp[slen++] = eol[0];
00087                 tmp[slen] = 0;
00088                 */
00089  
00090         wrote = write(fd, str, slen);           /* Hocus Pocus !!! */
00091         /* TODO: Here's the first thing that could stand fixing.  This writing
00092         * is all but blind.  Granted, we return what we wrote, but we don't
00093         * loop to write the rest.  At this point, writing commands on the order
00094         * of 10 bytes max, this should suffice.  Later on, this routine will
00095         * probably need to be made more robust.
00096         */
00097         if (!wrote) perror("say():write() failed");
00098         /* if (debug>4)
00099                 fprintf(stderr, "wrote %d bytes\n", wrote);
00100         free(tmp);*/
00101         return(0);
00102 }
00103 
00104 /*! \brief hear function reads data from serial port \n
00105  *      @param fd file descriptor for port
00106  *      @param *str pointer to return string
00107  *      @param maxlen maximum length of return string
00108  *      @param minlen minimum length of return string ( 0 = end string at character return, 
00109  *              !0 = minimum length)
00110  *      @param maxbtime maximum blocking time for select function 
00111  *              (select function looks for ports to read)
00112  *      @param term termination character to search for if minlen = 0
00113  *      @return int 0 if successful 
00114 */
00115 int hear(int fd, char *str, int maxlen, int minlen, int maxbtime, char term) {
00116         int tbr = 0;                    /* Total bytes read (cumulative) */
00117         int i;                          /* A loop variable */
00118         struct timeval rtmr;            /* Time to block in select() call */
00119         fd_set rfds;                    /* fd set containing our port fd */
00120         char *ptr; 
00121         static char *left = NULL;
00122         static int useleft = 0;
00123         char *buffer;
00124         buffer = (char *) malloc(100);
00125 
00126         if (!left)
00127                 left = (char *)malloc(maxlen+1);
00128         bzero(str, maxlen);             /* Zero out the target string (& illicit
00129                                          * any segfaults now in case someone didn't
00130                                          * properly initialize this.  Sneaky, eh?) */
00131         FD_ZERO(&rfds);                 /* Setup the fd set */ 
00132         FD_SET(fd, &rfds);
00133 
00134         rtmr.tv_sec = maxbtime/1000000;  /* Setup the block timer */
00135         rtmr.tv_usec = maxbtime - (rtmr.tv_sec * 1000000);
00136         /* First, check for leftovers from last time... */
00137         if (useleft) 
00138         {
00139                 strcpy(str, left);
00140                 tbr = strlen(left);
00141                 left[0] = 0;
00142         }
00143   /* This is not too straightforward, but should be sufficiently sophisticated.
00144    * Regardless, it's complicated enough to warrant explanation.
00145    * This loop will run the shortest of:
00146    * 1) 2 un-reset loops (2 loops of maxbtime usec w/o read data)
00147    * 2) IF minlen, then until tbr >= minlen (i.e. minlen bytes get read)
00148    * 3) IF NOT minlen, then until tbr[last]=term (i.e. the term char gets read)
00149    * 4) maxlen characters already read
00150    */
00151   for ( i = 0;
00152         /* Run while i < 3 (until i reaches 3) and.... */       
00153         (i < 3) &&      
00154         /*(i < 3) && */
00155         /* If minlen, then while tbr < minlen, else until we get a term char */
00156         /*(minlen ? (tbr<minlen) : (str[tbr?(tbr-1):0]!=term) ) &&*/
00157         /* if minlen is false (i.e. minlen = 0) then if no terminate found then 
00158                 do maxlen > tbr . */
00159         (minlen ? (tbr<minlen) : !strchr(str, term)) &&
00160         (maxlen > tbr) ;
00161         i++) 
00162         {
00163                 if (select(fd+1, &rfds, NULL, NULL, &rtmr)) 
00164                 {    /* Data to read? */
00165                         tbr += read(fd, str+tbr, maxlen-tbr);          /* Read returned data */
00166                         i = 0;
00167                 } 
00168                 else 
00169                 {
00170                 }
00171         }       
00172   if (!minlen)
00173           if ((ptr=strchr(str, term))) {        /* Assignment intentional */
00174                   if (ptr != str+tbr-1) {       /* The term character is being used, but is NOT the last character read */
00175                           /* strcpy(left, ptr+1); */    /* So copy the rest into the leftover buffer */
00176                           /* useleft = 1; */            /* Mark the marker. */
00177                           /* tbr -= (int)((str+tbr)-ptr);*/     /* and reduce tbr to the right value */
00178                           /* ptr[1] = 0; */             /* Finally, terminate the return string at the right place */
00179                   }
00180           }
00181   if (tbr == 0) {
00182     return(1);
00183   }
00184   return(0);
00185 }
00186 
00187 /* Do not change the comments below - they will be added automatically by CVS*/
00188 /*****************************************************************************
00189 *       $Log: common.c,v $
00190 *       Revision 1.6  2007/08/02 23:18:28  jayhawk_hokie
00191 *       Fixed Warnings.
00192 *       
00193 *       Revision 1.5  2006/08/11 20:07:47  bwilliam
00194 *       Updated init_serial and hear functions. Modified so magnetometer can function.
00195 *       
00196 *       
00197 *
00198 ******************************************************************************/
00199 

Generated on Wed Sep 5 12:54:18 2007 for DSACSS Operational Code by  doxygen 1.3.9.1