00001 #define VERSION "1.4 (April 7, 2004)"
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
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>   
00053 #include <string.h>  
00054 #include <termios.h> 
00055 #include <unistd.h>  
00056 #include <fcntl.h>   
00057 #include <errno.h>   
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;                
00091     int   nvals;
00092     float data[SH_MAX_VALS];
00093 } motparm;
00094 
00095 typedef struct
00096 {
00097     int debug;                  
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 
00119 static port_list g_ports;
00120 
00121 static char g_magic_hi [] = { 0xab, 0xcd, 0xef, 0xab, 0 };  
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     
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)           
00143     {
00144         mp.nread = 0;           
00145 
00146         
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         
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;   
00163 }
00164 
00165 
00166 
00167 
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 
00183 
00184 
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     
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     
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 
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     
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     
00257     if ( bind(sd, (struct sockaddr *)&sin, sizeof(sin)) == -1 )
00258     {
00259         perror("pe: bind");
00260         return -1;
00261     }
00262 
00263     
00264     if ( listen(sd, 3) == -1 )
00265     {
00266         perror("pe: listen");
00267         return -1;
00268     }
00269 
00270     
00271 
00272     
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 
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 
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++ )   
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     
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;          
00404     mp->nvals    = 6;
00405 
00406     return 0;
00407 }
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
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 
00625 
00626 
00627 
00628 
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 
00651 
00652 
00653 
00654 
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 )  
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 
00727 
00728          
00729         fcntl(sport, F_SETFL, FNDELAY);  
00730 
00731     
00732     tcgetattr(sport, &options);
00733 
00734     
00735     cfsetispeed(&options, B9600);
00736     cfsetospeed(&options, B9600);
00737 
00738     
00739         options.c_cflag |= (CLOCAL | CREAD );
00740         
00741         
00742         options.c_cflag &= ~PARENB;
00743         options.c_cflag &= ~CSTOPB;
00744         options.c_cflag &= ~CSIZE;
00745         options.c_cflag |= CS8;
00746 
00747         
00748     options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
00749     options.c_oflag &= ~OPOST;
00750 
00751     
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 
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 
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 }