Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

serial_helper.c

Go to the documentation of this file.
00001 #define VERSION "1.4 (April 7, 2004)"
00002 
00003 /*----------------------------------------------------------------------
00004  * serial_helper.c    - pass data from plug_realtime to serial port
00005  *
00006  * This program is meant to run as a tcp server.  The intention is
00007  * to read motion parameter data from the realtime plugin to afni,
00008  * and to write this data to a serial port.
00009  *
00010  * The basic outline is:
00011  *
00012  *     open tcp socket
00013  *     for ever
00014  *         wait for socket connection (listen())...
00015  *         open serial port
00016  *         while data is coming from tcp socket
00017  *             write data to serial port
00018  *         close serial port and data socket
00019  *
00020  * This program was written for Tom Ross.
00021  *----------------------------------------------------------------------
00022  */
00023 
00024 static char g_history[] =
00025  "----------------------------------------------------------------------\n"
00026  " history:\n"
00027  "\n"
00028  " 0.1  March 25, 2004  [tross]\n"
00029  "    - basic outline with serial functions\n"
00030  "\n"
00031  " 1.0  March 31, 2004  [rickr]\n"
00032  "    - initial full release\n"
00033  "\n"
00034  " 1.1  April 1, 2004  [rickr]\n"
00035  "    - added a little more to the -help section\n"
00036  "\n"
00037  " 1.2  April 1, 2004  [rickr]\n"
00038  "    - complain about bad options\n"
00039  "\n"
00040  " 1.3  April 2, 2004  [tross/rickr]\n"
00041  "    - set SH_DEF_MIN_FVAL to -12.7\n"
00042  "    - use -128 as the special value denoting start of serial data\n"
00043  "\n"
00044  " 1.4  April 7, 2004  [rickr]\n"
00045  "    - added 'sys/file.h' for solaris builds (thanks, Vince)\n"
00046  "\n"
00047  " 1.4a March 22, 2005  [rickr]\n"
00048  "    - removed all tabs\n"
00049  "----------------------------------------------------------------------\n";
00050 
00051 
00052 #include <stdio.h>   /* Standard input/output definitions */
00053 #include <string.h>  /* String function definitions */
00054 #include <termios.h> /* POSIX terminal control definitions */
00055 #include <unistd.h>  /* UNIX standard function definitions */
00056 #include <fcntl.h>   /* File control definitions */
00057 #include <errno.h>   /* Error number definitions */
00058 
00059 #include <stdlib.h>
00060 #include <signal.h>
00061 #include <sys/file.h>
00062 #include <sys/types.h>
00063 #include <sys/socket.h>
00064 #include <netinet/in.h>
00065 #include <arpa/inet.h>
00066 
00067 #define SH_MAX_VALS            6
00068 #define SH_DEF_MIN_FVAL    -12.7
00069 #define SH_DEF_MAX_FVAL     12.7
00070 #define SH_DEF_SOCKET      53214
00071 
00072 #define SH_USE_HIST            1
00073 #define SH_USE_VERSION         2
00074 #define SH_USE_SHORT           3
00075 #define SH_USE_LONG            4
00076 
00077 #define CHECK_NULL_STR(str) ( str ? str : "(NULL)" )
00078 
00079 typedef struct{
00080     char  * serial_port;
00081     int     no_serial;
00082     float   mp_min;
00083     float   mp_max;
00084     int     sock_num;
00085     int     swap;
00086     int     debug;
00087 } optiondata;
00088 
00089 typedef struct {
00090     int   nread;                /* number of instances processed */
00091     int   nvals;
00092     float data[SH_MAX_VALS];
00093 } motparm;
00094 
00095 typedef struct
00096 {
00097     int debug;                  /* for global access in cleanup() */
00098     int sport;
00099     int tdata_sd;
00100     int tserver_sd;
00101 } port_list;
00102 
00103 
00104 void  cleanup              ( int sig_num );
00105 int   close_data_ports     ( port_list * plist );
00106 int   disp_optiondata      ( char * info, optiondata * D );
00107 int   get_options          ( optiondata *opt, motparm * mp, port_list * plist,
00108                              int argc, char *argv[] );
00109 int   init_structs         ( optiondata *opt, motparm * mp, port_list * plist );
00110 int   open_incoming_socket ( optiondata *opt, port_list * plist );
00111 int   open_serial          ( optiondata *opt, port_list * plist );
00112 int   read_socket          ( optiondata *opt, port_list * plist, motparm * mp );
00113 void  send_serial          ( optiondata * opt, port_list * plist, motparm *mot);
00114 void  swap_4               ( void * data, int nswaps );
00115 int   usage                ( char * prog, int level );
00116 int   wait_for_socket      ( optiondata *opt, port_list * plist );
00117 
00118 /* global port numbers, for cleanup */
00119 static port_list g_ports;
00120 
00121 static char g_magic_hi [] = { 0xab, 0xcd, 0xef, 0xab, 0 };  /* w/termination */
00122 static char g_magic_bye[] = { 0xde, 0xad, 0xde, 0xad, 0 };
00123 static int  g_magic_len   = 4;
00124 
00125 int main(int argc, char *argv[])
00126 {
00127     optiondata  opt;
00128     motparm     mp;  
00129     port_list * plist = &g_ports;
00130     int         rv;
00131 
00132     if ( (rv = get_options(&opt, &mp, plist, argc, argv)) != 0 )
00133         return rv;
00134     
00135     /* register interrupt trap */
00136     signal( SIGTERM, cleanup );
00137     signal( SIGINT, cleanup );
00138     
00139     if ( (rv = open_incoming_socket(&opt, plist)) < 0 )
00140         return rv;
00141 
00142     while (1)           /* run until interrupt or error (consider restart?) */
00143     {
00144         mp.nread = 0;           /* reset our counter */
00145 
00146         /* wait for AFNI to talk to us */
00147         if ( (rv = wait_for_socket(&opt, plist)) < 0 )
00148             return rv;
00149 
00150         if ( ! opt.no_serial )
00151             if ( (rv = open_serial(&opt, plist)) != 0 )
00152                 return rv;
00153 
00154         /* read data while it is there */
00155         while (read_socket(&opt, plist, &mp) == 0)
00156             if ( ! opt.no_serial )
00157                 send_serial(&opt, plist, &mp);
00158 
00159         close_data_ports(plist);
00160     } 
00161 
00162     return 0;   /* should not be reached, of course */
00163 }
00164 
00165 
00166 /* ----------------------------------------------------------------------
00167  * close serial port and data socket
00168  * ----------------------------------------------------------------------
00169  */
00170 int close_data_ports( port_list * plist )
00171 {
00172     if ( plist->sport    != 0 ) close(plist->sport);
00173     if ( plist->tdata_sd != 0 ) close(plist->tdata_sd);
00174 
00175     plist->sport = plist->tdata_sd = 0;
00176 
00177     return 0;
00178 }
00179 
00180 
00181 /* ----------------------------------------------------------------------
00182  * block until data comes return the open socket
00183  *
00184  * we expect to read g_magic_hi 
00185  * ----------------------------------------------------------------------
00186  */
00187 int wait_for_socket(optiondata *opt, port_list * plist)
00188 {
00189     struct sockaddr_in sin;
00190     char               data[8];
00191     int                sd, len;
00192 
00193     len = sizeof(sin);
00194     /* block until a connection is made */
00195     if ( (sd = accept(plist->tserver_sd, (struct sockaddr *)&sin, &len)) == -1 )
00196     {
00197         perror("pe: accept");
00198         return -1;
00199     }
00200 
00201     plist->tdata_sd = sd;
00202 
00203     if ( opt->debug > 0 )
00204         fprintf(stderr,"++ accepting call from '%s'\n",inet_ntoa(sin.sin_addr));
00205 
00206     if ( (len = recv(sd, data, g_magic_len, 0)) == -1 )
00207     {
00208         perror("pe: recv");
00209         return -1;
00210     }
00211 
00212     if ( strncmp(data, g_magic_hi, g_magic_len) != 0 )
00213     {
00214         fprintf(stderr, "** bad data on socket: 0x%x%x%x%x\n",
00215                 data[0], data[1], data[2], data[3] );
00216         return -1;
00217     }
00218 
00219     /* Hey, they said the magic word! */
00220 
00221     if ( opt->debug > 0 )
00222         fprintf(stderr,"++ got hello string '%s', ready for data...\n",
00223                 g_magic_hi);
00224 
00225     return 0;
00226 }
00227 
00228 /* ---------------------------------------------------------------------- */
00229 /* create the socket, and announce that we are listening                  */
00230 int open_incoming_socket( optiondata * opt, port_list * plist )
00231 {
00232     struct sockaddr_in sin;
00233     int                sd;
00234 
00235     if ( opt->sock_num < 5000 || opt->sock_num > 65535 )
00236     {
00237         fprintf(stderr, "** bad socket number: %d\n", opt->sock_num);
00238         return -1;
00239     }
00240 
00241     if ( opt->debug > 1 )
00242         fprintf(stderr,"-- attempting to open port %d\n", opt->sock_num);
00243 
00244     /* create a comm. endpoint */
00245     if ( (sd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
00246     {
00247         perror("pe: socket");
00248         return sd;
00249     }
00250 
00251     memset( &sin, 0, sizeof(sin) );
00252     sin.sin_family      = AF_INET;
00253     sin.sin_addr.s_addr = INADDR_ANY;
00254     sin.sin_port        = htons(opt->sock_num);
00255 
00256     /* actually bind the port to the socket */
00257     if ( bind(sd, (struct sockaddr *)&sin, sizeof(sin)) == -1 )
00258     {
00259         perror("pe: bind");
00260         return -1;
00261     }
00262 
00263     /* announce that we are ready to accept connections */
00264     if ( listen(sd, 3) == -1 )
00265     {
00266         perror("pe: listen");
00267         return -1;
00268     }
00269 
00270     /* if we get here, all is well to start accepting communication */
00271 
00272     /* store the socket descriptor and return success */
00273     plist->tserver_sd = sd;
00274 
00275     if ( opt->debug > 0 )
00276         fprintf(stderr,"++ port %d open (sd = %d), listening...\n",
00277                 opt->sock_num, sd);
00278 
00279     return 0;
00280 }
00281 
00282 /* ----------------------------------------------------------------------
00283  * initialize data structures
00284  * ----------------------------------------------------------------------
00285  */
00286 int init_structs( optiondata *opt, motparm * mp, port_list * plist )
00287 {
00288     memset(opt,   0, sizeof(*opt)  );
00289     memset(plist, 0, sizeof(*plist));
00290     memset(mp,    0, sizeof(*mp)   );
00291 
00292     opt->serial_port = NULL;
00293     opt->mp_min      = SH_DEF_MIN_FVAL;
00294     opt->mp_max      = SH_DEF_MAX_FVAL;
00295     opt->sock_num    = SH_DEF_SOCKET;
00296 
00297     return 0;
00298 }
00299 
00300 
00301 /* close any open ports (to possibly catch an interrupt) */
00302 void cleanup(int sig_num)
00303 {
00304     if ( g_ports.debug > 0 )
00305     {
00306         fputs("-- final check: closing ports\n", stderr);
00307         if ( g_ports.debug > 1 )
00308         {
00309             fprintf(stderr,"   descriptors: ser = %d, data = %d, serv = %d\n",
00310                     g_ports.sport, g_ports.tdata_sd, g_ports.tserver_sd);
00311             fprintf(stderr,"-- sig_num = %d\n", sig_num);
00312         }
00313     }
00314 
00315     if ( g_ports.sport != 0)
00316         close(g_ports.sport);
00317     if (g_ports.tdata_sd != 0)
00318         close(g_ports.tdata_sd);
00319     if (g_ports.tserver_sd != 0)
00320         close(g_ports.tserver_sd);
00321 
00322     g_ports.sport = g_ports.tdata_sd = g_ports.tserver_sd = 0;
00323 }
00324         
00325 #define CHECK_ARG_COUNT(ac,str)         \
00326         do {                            \
00327             if ((ac+1) >= argc) {       \
00328                 fputs(str,stderr);      \
00329                 return -1;              \
00330             }                           \
00331         } while (0)                     \
00332 
00333 int get_options(optiondata *opt, motparm * mp, port_list * plist,
00334                 int argc, char *argv[])
00335 {
00336     char * prog = argv[0];
00337     int    ac;
00338 
00339     init_structs(opt, mp, plist);
00340 
00341     if ( argc < 2 )
00342         return usage(prog, SH_USE_SHORT);
00343 
00344     for ( ac = 1; ac < argc; ac++ )   /* help, hist first, rest alphabetical */
00345     {
00346         if ( !strncmp(argv[ac], "-help", 5) )
00347             return usage(prog, SH_USE_LONG);
00348         if ( !strncmp(argv[ac], "-hist", 5) )
00349             return usage(prog, SH_USE_HIST);
00350         else if ( !strncmp(argv[ac], "-debug", 6) )
00351         {
00352             CHECK_ARG_COUNT(ac, "opt use: -debug DEBUG_LEVEL\n");
00353             opt->debug = atoi(argv[++ac]);
00354         }
00355         else if ( !strncmp(argv[ac], "-mp_max", 6) )
00356         {
00357             CHECK_ARG_COUNT(ac, "opt use: -mp_max MAX_MP_VAL\n");
00358             opt->mp_max = atof(argv[++ac]);
00359         }
00360         else if ( !strncmp(argv[ac], "-mp_min", 6) )
00361         {
00362             CHECK_ARG_COUNT(ac, "opt use: -mp_min MIN_MP_VAL\n");
00363             opt->mp_min = atof(argv[++ac]);
00364         }
00365         else if ( !strncmp(argv[ac], "-no_serial", 7) )
00366             opt->no_serial = 1;
00367         else if ( !strncmp(argv[ac], "-serial_port", 7) )
00368         {
00369             CHECK_ARG_COUNT(ac, "opt use: -serial_port SERIAL_FILENAME\n");
00370             opt->serial_port = argv[++ac];
00371         }
00372         else if ( !strncmp(argv[ac], "-sock_num", 7) )
00373         {
00374             CHECK_ARG_COUNT(ac, "opt use: -sock_num SOCKET_NUMBER\n");
00375             opt->sock_num = atoi(argv[++ac]);
00376         }
00377         else if ( !strncmp(argv[ac], "-swap", 5) )
00378             opt->swap = 1;
00379         else if ( !strncmp(argv[ac], "-ver", 4) )
00380             return usage(prog, SH_USE_VERSION);
00381         else
00382         {
00383             fprintf(stderr,"** invalid option '%s', exiting...\n", argv[ac]);
00384             return -1;
00385         }
00386     }
00387 
00388     /* check basic options */
00389     if ( opt->sock_num <= 0 || opt->sock_num > 65536 )
00390     {
00391         fprintf(stderr,"** socket number %d is out of range\n", opt->sock_num);
00392         return -1;
00393     }
00394     if ( ! opt->serial_port && opt->no_serial == 0 )
00395     {
00396         fprintf(stderr,"** missing option '-serial_port'\n");
00397         return -1;
00398     }
00399 
00400     if ( opt->debug > 1 )
00401         disp_optiondata( "options read: ", opt );
00402 
00403     plist->debug = opt->debug;          /* for cleanup() */
00404     mp->nvals    = 6;
00405 
00406     return 0;
00407 }
00408 
00409 
00410 /* ----------------------------------------------------------------------
00411  * display usage
00412  *
00413  * SH_USE_SHORT   : most basic usage info
00414  * SH_USE_VERSION : display version number
00415  * SH_USE_LONG    : display complete description of program and options
00416  * ----------------------------------------------------------------------
00417  */
00418 int usage( char * prog, int level )
00419 {
00420     if ( level == SH_USE_SHORT )
00421         printf( "usage: %s -help\n"
00422                 "usage: %s [options] -serial_port FILENAME\n", prog, prog );
00423     else if ( level == SH_USE_HIST )
00424         fputs( g_history, stdout );
00425     else if ( level == SH_USE_VERSION )
00426         printf( "%s, version %s, compiled %s\n", prog, VERSION, __DATE__ );
00427     else if ( level == SH_USE_LONG )
00428     {
00429         printf(
00430             "------------------------------------------------------------\n"
00431             "%s - pass motion parameters from socket to serial port\n"
00432             "\n"
00433             "    This program is meant to receive registration (motion?)\n"
00434             "    correction parameters from afni's realtime plugin, and to\n"
00435             "    pass that data on to a serial port.\n"
00436             "\n"
00437             "    The program is meant to run as a tcp server.  It listens\n"
00438             "    for a connection, then processes data until a termination\n"
00439             "    flag is received (sending data from the tcp socket to the\n"
00440             "    serial port), closes the new connection, and goes back\n"
00441             "    to a listening state.\n"
00442             "\n"
00443             "    The basic outline is:\n"
00444             "\n"
00445             "    open tcp server socket\n"
00446             "    repeat forever:\n"
00447             "        wait for a tcp client connection\n"
00448             "        open a serial port\n"
00449             "        while the client sends new data\n"
00450             "            write that data to the serial port\n"
00451             "        close the serial port and client socket\n"
00452             "\n"
00453             "    The expected client is the realtime plugin to afni,\n"
00454             "    plug_realtime.so.  If the afni user has their environment\n"
00455             "    variable AFNI_REALTIME_MP_HOST_PORT set as HOST:PORT,\n"
00456             "    then for EACH RUN, the realtime plugin will open a tcp\n"
00457             "    connection to the given HOST and PORT, pass the magic hello\n"
00458             "    data (0xabcdefab), pass the 6 motion parameters for each\n"
00459             "    time point, and signal a closure by passing the magic bye\n"
00460             "    data (0xdeaddead).\n"
00461             "\n"
00462             "    On this server end, the 'repeat forever' loop will do the\n"
00463             "    following.  First it will establish the connection by\n"
00464             "    checking for the magic hello data.  If that data is found,\n"
00465             "    the serial port will be opened.\n"
00466             "\n"
00467             "    Then it will repeatedly check the incoming data for the\n"
00468             "    magic bye data.  As long as that check fails, the data is\n"
00469             "    assumed to be valid motion parameters.  And so 6 floats at a\n"
00470             "    time are read from the incoming socket and passed to the\n"
00471             "    serial port.\n"
00472             "\n"
00473             "  usage: %s [options] -serial_port FILENAME\n"
00474             "------------------------------------------------------------\n"
00475             "  examples:\n"
00476             "\n"
00477             "    1. display this help :\n"
00478             "\n"
00479             "        %s -help\n"
00480             "\n"
00481             "    2. display the module history :\n"
00482             "\n"
00483             "        %s -hist\n"
00484             "\n"
00485             "    3. display the current version number :\n"
00486             "\n"
00487             "        %s -ver\n"
00488             "\n"
00489             "  * 4. run normally, using the serial port file /dev/ttyS0 :\n"
00490             "\n"
00491             "        %s -serial_port /dev/ttyS0\n"
00492             "\n"
00493             "  * 5. same as 4, but specify socket number 53214 :\n"
00494             "\n"
00495             "        %s -serial_port /dev/ttyS0 -sock_num 53214\n"
00496             "\n"
00497             "    6. same as 5, but specify minmum and maximum bounds on\n"
00498             "       the values :\n"
00499             "\n"
00500             "        %s                       \\\n"
00501             "            -serial_port /dev/ttyS0            \\\n"
00502             "            -sock_num 53214                    \\\n"
00503             "            -mp_min -12.7                      \\\n"
00504             "            -mp_max  12.7\n"
00505             "\n"
00506             "    7. run the program in socket test mode, without serial\n"
00507             "       communication, and printing all the incoming data\n"
00508             "\n"
00509             "        %s -no_serial -debug 3\n"
00510             "\n"
00511             "    8. same as 4, but use debug level 3 to see the parameters\n"
00512             "       that will be passed on, and duplicate all output to the\n"
00513             "       file, helper.output\n"
00514             "\n"
00515             "       note: this command is for the t-shell, and will not work\n"
00516             "             under bash (for bash do the 2>&1 thingy...)\n"
00517             "\n"
00518             "        %s -serial_port /dev/ttyS0 -debug 3 |& tee helper.out\n"
00519             "------------------------------------------------------------\n"
00520             "  program setup:\n"
00521             "\n"
00522             "    1. Start '%s' on the computer with the serial port that\n"
00523             "       the motion parameters should be written to.  Example 3\n"
00524             "       is the most likely case, though it might be useful to\n"
00525             "       use example 8.\n"
00526             "\n"
00527             "    2. On the computer which will be used to run 'afni -rt',\n"
00528             "       set the environment variable AFNI_REALTIME_MP_HOST_PORT\n"
00529             "       to the appropriate host:port pair.  See the '-sock_num'\n"
00530             "       option below for more details.\n"
00531             "\n"
00532             "       This variable can also be set in the ~/.cshrc file, or\n"
00533             "       as part of the AFNI environment via the ~/.afnirc file.\n"
00534             "\n"
00535             "    3. Start 'afni -rt'.  Be sure to request 'realtime' graphing\n"
00536             "       of the '3D: realtime' Registration parameters.\n"
00537             "\n"
00538             "    4. Start receiving data (sending it to the realtime plugin).\n"
00539             "\n"
00540             "       Note that for testing purposes, I may work well to get a\n"
00541             "       set of I-files (say, in directories 003, 023, etc.), and\n"
00542             "       to use Imon to send not-so-real-time data to afni.  An\n"
00543             "       example of Imon for this purpose might be:\n"
00544             "\n"
00545             "           Imon -start_dir 003 -quit -rt -host localhost\n"
00546             "\n"
00547             "       See 'Imon -help' for more information.\n"
00548             "------------------------------------------------------------\n"
00549             "  'required' parameter:\n"
00550             "\n"
00551             "    -serial_port FILENAME : specify output serial port\n"
00552             "                          : -serial_port /dev/ttyS0\n"
00553             "\n"
00554             "        If the user is not using any of the 'special' options,\n"
00555             "        below, then this parameter is required.\n"
00556             "\n"
00557             "        The FILENAME is the device file for the serial port\n"
00558             "        which will be used for output.\n"
00559             "------------------------------\n"
00560             "  special options (for information or testing):\n"
00561             "\n"
00562             "    -help            : show this help information\n"
00563             "\n"
00564             "    -hist            : show the module history\n"
00565             "\n"
00566             "    -debug LEVEL     : set the debugging level to LEVEL\n"
00567             "                     : e.g. -debug 2\n"
00568             "                     : default is 0, max is 3\n"
00569             "\n"
00570             "    -no_serial       : turn of serial port output\n"
00571             "\n"
00572             "        This option is used for testing the incoming data,\n"
00573             "        when output to a serial port is not desired.  The\n"
00574             "        program will otherwise operate normally.\n"
00575             "\n"
00576             "    -version         : show the current version number\n"
00577             "------------------------------\n"
00578             "  'normal' options:\n"
00579             "\n"
00580             "    -mp_max MAX_VAL  : limit the maximum value of the MP data\n"
00581             "                     : e.g. -mp_max 12.7\n"
00582             "                     : default is 12.7\n"
00583             "\n"
00584             "        If any incoming data is greater than this value, it will\n"
00585             "        be set to this value.  The default of 12.7 is used to\n"
00586             "        scale incoming floats to signed bytes.\n"
00587             "\n"
00588             "    -mp_min MIN_VAL  : limit the minimum value of the MP data\n"
00589             "                     : e.g. -mp_min -12.7\n"
00590             "                     : default is -12.7\n"
00591             "\n"
00592             "        If any incoming data is less than this value, it will\n"
00593             "        be set to this value.  The default of -12.7 is used to\n"
00594             "        scale incoming floats to signed bytes.\n"
00595             "\n"
00596             "    -sock_num SOCK   : specify socket number to serve\n"
00597             "                     : e.g. -sock_num 53214\n"
00598             "                     : default is 53214\n"
00599             "\n"
00600             "        This is the socket the program will use to listen for\n"
00601             "        new connections.  This is the socket number that should\n"
00602             "        be provided to the realtime plugin via the environment\n"
00603             "        variable, AFNI_REALTIME_MP_HOST_PORT.\n"
00604             "\n"
00605             "        On the machine the user run afni from, that environment\n"
00606             "        variable should have the form HOST:PORT, where a basic\n"
00607             "        example might be localhost:53214.\n"
00608             "------------------------------------------------------------\n"
00609             "  Authors: R. Reynolds, T. Ross  (March, 2004)\n"
00610             "------------------------------------------------------------\n",
00611             prog, prog,
00612             prog, prog, prog, prog, prog, prog, prog, prog,
00613             prog
00614             );
00615     }
00616     else
00617         fprintf(stderr,"** usage error: invalid level %d\n", level);
00618 
00619     return 1;
00620 }
00621 
00622 
00623 /* ----------------------------------------------------------------------
00624  * check for close requeset
00625  *
00626  * return  1 : close
00627  *         0 : continue
00628  *        -1 : error
00629  * ----------------------------------------------------------------------
00630  */
00631 int test_socket(int sd)
00632 {
00633     char data[16];
00634     int  len;
00635 
00636     if ( (len = recv(sd, data, g_magic_len, MSG_PEEK)) == -1 )
00637     {
00638         fputs("** test_socket_failure\n", stderr);
00639         perror("pe: recv");
00640         return -1;
00641     }
00642 
00643     if ( strncmp(data, g_magic_bye, g_magic_len) == 0 )
00644         return 1;
00645 
00646     return 0;
00647 }
00648 
00649 /* ----------------------------------------------------------------------
00650  * read one set of motion parameters and store in structure
00651  *
00652  * return 1 : finished
00653  *        0 : have data: continue
00654  *       -1 : error
00655  * ----------------------------------------------------------------------
00656  */
00657 int read_socket(optiondata * opt, port_list * plist, motparm * mp)
00658 {
00659     int    rv, len;
00660 
00661     if ( (rv = test_socket(plist->tdata_sd)) < 0 )
00662         return -1;
00663     else if ( rv == 1 )
00664     {
00665         if ( opt->debug > 0 )
00666             fprintf(stderr,"++ found close request, mpcount = %d\n", mp->nread);
00667         return 1;
00668     }
00669 
00670     len = mp->nvals * sizeof(float);
00671     if ( (rv = recv(plist->tdata_sd, (void *)mp->data, len, 0)) < len )
00672     {
00673         fprintf(stderr,"** read only %d of %d bytes on socket\n", rv, len);
00674         perror("pe: recv");
00675         return -1;
00676     }
00677 
00678     if ( opt->swap )
00679         swap_4(mp->data, mp->nvals);
00680 
00681     mp->nread++;
00682 
00683     if ( opt->debug > 2 )  /* display the data */
00684     {
00685         int c;
00686         fprintf(stderr,"++ recv floats:");
00687         for ( c = 0; c < mp->nvals; c++ )
00688             fprintf(stderr,"  %f", mp->data[c]);
00689         fputc('\n', stderr);
00690     }
00691 
00692     return 0;
00693 }
00694 
00695 void send_serial(optiondata * opt, port_list * plist, motparm *mot)
00696 {
00697     static char outdata[7];
00698     int i;
00699     
00700     outdata[0] = -128;
00701     for (i=0; i<6; i++) {
00702         if (mot->data[i] > opt->mp_max) 
00703             mot->data[i] = opt->mp_max;
00704         if (mot->data[i] < opt->mp_min)
00705             mot->data[i] = opt->mp_min;
00706         outdata[i+1] = (char) (mot->data[i] * 10.0);
00707     }
00708     i = write(plist->sport, outdata, 7);
00709     if (i<7)
00710         fprintf(stderr, "warning: only wrote %d bytes to serial port\n", i);
00711 } 
00712 
00713 
00714 int open_serial(optiondata *opt, port_list * plist)
00715 {
00716         int sport;
00717         struct termios options;
00718         
00719         sport = open(opt->serial_port, O_RDWR | O_NOCTTY | O_NDELAY); 
00720         if (sport == -1) {
00721                 perror("pe: Failed to open the serial port ");
00722                 return -1;
00723         }
00724         
00725         /*******************
00726          set up the port 
00727          *******************/
00728          
00729         fcntl(sport, F_SETFL, FNDELAY);  /* nonblocking reads */
00730 
00731     /* Get the current options for the port...*/
00732     tcgetattr(sport, &options);
00733 
00734     /* Set the baud rates to 9600 */
00735     cfsetispeed(&options, B9600);
00736     cfsetospeed(&options, B9600);
00737 
00738     /* Enable the receiver and set local mode */
00739         options.c_cflag |= (CLOCAL | CREAD );
00740         
00741         /* set 8 bit N parity */
00742         options.c_cflag &= ~PARENB;
00743         options.c_cflag &= ~CSTOPB;
00744         options.c_cflag &= ~CSIZE;
00745         options.c_cflag |= CS8;
00746 
00747         /* raw data input and output */
00748     options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
00749     options.c_oflag &= ~OPOST;
00750 
00751     /*Set the new options for the port*/
00752     if (tcsetattr(sport, TCSANOW, &options) == -1) {
00753                 perror("pe: Failed to set attributes on the serial port ");
00754                 close(sport);
00755                 return -1;
00756         }
00757         
00758     plist->sport = sport;
00759     return 0;
00760 }
00761 
00762 
00763 /* ----------------------------------------------------------------------
00764  * swap 4 bytes at a time
00765  * ----------------------------------------------------------------------
00766  */
00767 void swap_4( void * data, int nswaps )
00768 {
00769     char * cp, tmp;
00770     int    c;
00771     for ( c = 0, cp = (char *)data; c < nswaps; c++, cp += 4 )
00772     {
00773         tmp = cp[0];  cp[0] = cp[3];  cp[3] = tmp;
00774         tmp = cp[1];  cp[1] = cp[2];  cp[2] = tmp;
00775     }
00776 }
00777 
00778 
00779 /* ----------------------------------------------------------------------
00780  * display contents of optiondata struct
00781  * ----------------------------------------------------------------------
00782  */
00783 int disp_optiondata( char * info, optiondata * D )
00784 {
00785     if ( info )
00786         fputs(info, stderr);
00787     
00788     if ( ! D )
00789     {
00790         fprintf(stderr,"** disp_optiondata: D == NULL\n");
00791         return -1;
00792     }
00793 
00794     fprintf(stderr,
00795             " optiondata at %p :\n"
00796             "    serial_port     = %s\n"
00797             "    no_serial       = %d\n"
00798             "    mp_min, mp_max  = %f, %f\n"
00799             "    sock_num        = %d\n"
00800             "    swap, debug     = %d, %d\n",
00801             D, CHECK_NULL_STR(D->serial_port), D->no_serial,
00802             D->mp_min, D->mp_max, D->sock_num, D->swap, D->debug);
00803 
00804     return 0;
00805 }
 

Powered by Plone

This site conforms to the following standards: