#define VERSION "1.6 (November 15, 2006)"
/*----------------------------------------------------------------------
* serial_helper.c - pass data from plug_realtime to serial port
*
* This program is meant to run as a tcp server. The intention is
* to read motion parameter data from the realtime plugin to afni,
* and to write this data to a serial port.
*
* The basic outline is:
*
* open tcp socket
* for ever
* wait for socket connection (listen())...
* open serial port
* while data is coming from tcp socket
* write data to serial port
* close serial port and data socket
*
* This program was written for Tom Ross.
*----------------------------------------------------------------------
*/
static char g_history[] =
"----------------------------------------------------------------------\n"
" history:\n"
"\n"
" 0.1 March 25, 2004 [tross]\n"
" - basic outline with serial functions\n"
"\n"
" 1.0 March 31, 2004 [rickr]\n"
" - initial full release\n"
"\n"
" 1.1 April 1, 2004 [rickr]\n"
" - added a little more to the -help section\n"
"\n"
" 1.2 April 1, 2004 [rickr]\n"
" - complain about bad options\n"
"\n"
" 1.3 April 2, 2004 [tross/rickr]\n"
" - set SH_DEF_MIN_FVAL to -12.7\n"
" - use -128 as the special value denoting start of serial data\n"
"\n"
" 1.4 April 7, 2004 [rickr]\n"
" - added 'sys/file.h' for solaris builds (thanks, Vince)\n"
"\n"
" 1.4a March 22, 2005 [rickr]\n"
" - removed all tabs\n"
"\n"
" 1.5 November 11, 2006 [rickr]\n"
" - added -num_extras option, for processing extra floats per TR\n"
"\n"
" 1.6 November 15, 2006 [rickr]\n"
" - encode nex in handshake byte written to serial port each TR\n"
"----------------------------------------------------------------------\n";
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <stdlib.h>
#include <signal.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SH_MAX_VALS 6
#define SH_DEF_MIN_FVAL -12.7
#define SH_DEF_MAX_FVAL 12.7
#define SH_DEF_SOCKET 53214
#define SH_USE_HIST 1
#define SH_USE_VERSION 2
#define SH_USE_SHORT 3
#define SH_USE_LONG 4
#define CHECK_NULL_STR(str) ( str ? str : "(NULL)" )
typedef struct{
char * serial_port;
int no_serial;
float mp_min;
float mp_max;
int sock_num;
int num_extra; /* number of extra data values per TR */
int swap;
int debug;
} optiondata;
typedef struct {
int nread; /* number of instances processed */
int nvals;
int nex; /* opt->num_extra */
float data[SH_MAX_VALS];
float * extras; /* extra data values received per TR */
} motparm;
typedef struct
{
int debug; /* for global access in cleanup() */
int sport;
int tdata_sd;
int tserver_sd;
} port_list;
void cleanup ( int sig_num );
int close_data_ports ( port_list * plist );
int disp_optiondata ( char * info, optiondata * D );
int get_options ( optiondata *opt, motparm * mp, port_list * plist,
int argc, char *argv[] );
int init_structs ( optiondata *opt, motparm * mp, port_list * plist );
int open_incoming_socket ( optiondata *opt, port_list * plist );
int open_serial ( optiondata *opt, port_list * plist );
int read_socket ( optiondata *opt, port_list * plist, motparm * mp );
void send_serial ( optiondata * opt, port_list * plist, motparm *mot);
void swap_4 ( void * data, int nswaps );
int usage ( char * prog, int level );
int wait_for_socket ( optiondata *opt, port_list * plist );
/* global port numbers, for cleanup */
static port_list g_ports;
static char g_magic_hi [] = { 0xab, 0xcd, 0xef, 0xab, 0 }; /* w/termination */
static char g_magic_bye[] = { 0xde, 0xad, 0xde, 0xad, 0 };
static int g_magic_len = 4;
int main(int argc, char *argv[])
{
optiondata opt;
motparm mp;
port_list * plist = &g_ports;
int rv;
if ( (rv = get_options(&opt, &mp, plist, argc, argv)) != 0 )
return rv;
/* register interrupt trap */
signal( SIGTERM, cleanup );
signal( SIGINT, cleanup );
if ( (rv = open_incoming_socket(&opt, plist)) < 0 )
return rv;
while (1) /* run until interrupt or error (consider restart?) */
{
mp.nread = 0; /* reset our counter */
/* wait for AFNI to talk to us */
if ( (rv = wait_for_socket(&opt, plist)) < 0 )
return rv;
if ( ! opt.no_serial )
if ( (rv = open_serial(&opt, plist)) != 0 )
return rv;
/* read data while it is there */
while (read_socket(&opt, plist, &mp) == 0)
if ( ! opt.no_serial )
send_serial(&opt, plist, &mp);
close_data_ports(plist);
}
return 0; /* should not be reached, of course */
}
/* ----------------------------------------------------------------------
* close serial port and data socket
* ----------------------------------------------------------------------
*/
int close_data_ports( port_list * plist )
{
if ( plist->sport != 0 ) close(plist->sport);
if ( plist->tdata_sd != 0 ) close(plist->tdata_sd);
plist->sport = plist->tdata_sd = 0;
return 0;
}
/* ----------------------------------------------------------------------
* block until data comes return the open socket
*
* we expect to read g_magic_hi
* ----------------------------------------------------------------------
*/
int wait_for_socket(optiondata *opt, port_list * plist)
{
struct sockaddr_in sin;
char data[8];
int sd, len;
len = sizeof(sin);
/* block until a connection is made */
if ( (sd = accept(plist->tserver_sd, (struct sockaddr *)&sin, &len)) == -1 )
{
perror("pe: accept");
return -1;
}
plist->tdata_sd = sd;
if ( opt->debug > 0 )
fprintf(stderr,"++ accepting call from '%s'\n",inet_ntoa(sin.sin_addr));
if ( (len = recv(sd, data, g_magic_len, 0)) == -1 )
{
perror("pe: recv");
return -1;
}
if ( strncmp(data, g_magic_hi, g_magic_len) != 0 )
{
fprintf(stderr, "** bad data on socket: 0x%x%x%x%x\n",
data[0], data[1], data[2], data[3] );
return -1;
}
/* Hey, they said the magic word! */
if ( opt->debug > 0 )
fprintf(stderr,"++ got hello string '%s', ready for data...\n",
g_magic_hi);
return 0;
}
/* ---------------------------------------------------------------------- */
/* create the socket, and announce that we are listening */
int open_incoming_socket( optiondata * opt, port_list * plist )
{
struct sockaddr_in sin;
int sd;
if ( opt->sock_num < 5000 || opt->sock_num > 65535 )
{
fprintf(stderr, "** bad socket number: %d\n", opt->sock_num);
return -1;
}
if ( opt->debug > 1 )
fprintf(stderr,"-- attempting to open port %d\n", opt->sock_num);
/* create a comm. endpoint */
if ( (sd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
perror("pe: socket");
return sd;
}
memset( &sin, 0, sizeof(sin) );
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(opt->sock_num);
/* actually bind the port to the socket */
if ( bind(sd, (struct sockaddr *)&sin, sizeof(sin)) == -1 )
{
perror("pe: bind");
return -1;
}
/* announce that we are ready to accept connections */
if ( listen(sd, 3) == -1 )
{
perror("pe: listen");
return -1;
}
/* if we get here, all is well to start accepting communication */
/* store the socket descriptor and return success */
plist->tserver_sd = sd;
if ( opt->debug > 0 )
fprintf(stderr,"++ port %d open (sd = %d), listening...\n",
opt->sock_num, sd);
return 0;
}
/* ----------------------------------------------------------------------
* initialize data structures
* ----------------------------------------------------------------------
*/
int init_structs( optiondata *opt, motparm * mp, port_list * plist )
{
memset(opt, 0, sizeof(*opt) );
memset(plist, 0, sizeof(*plist));
memset(mp, 0, sizeof(*mp) );
opt->serial_port = NULL;
opt->mp_min = SH_DEF_MIN_FVAL;
opt->mp_max = SH_DEF_MAX_FVAL;
opt->sock_num = SH_DEF_SOCKET;
return 0;
}
/* close any open ports (to possibly catch an interrupt) */
void cleanup(int sig_num)
{
if ( g_ports.debug > 0 )
{
fputs("-- final check: closing ports\n", stderr);
if ( g_ports.debug > 1 )
{
fprintf(stderr," descriptors: ser = %d, data = %d, serv = %d\n",
g_ports.sport, g_ports.tdata_sd, g_ports.tserver_sd);
fprintf(stderr,"-- sig_num = %d\n", sig_num);
}
}
if ( g_ports.sport != 0)
close(g_ports.sport);
if (g_ports.tdata_sd != 0)
close(g_ports.tdata_sd);
if (g_ports.tserver_sd != 0)
close(g_ports.tserver_sd);
g_ports.sport = g_ports.tdata_sd = g_ports.tserver_sd = 0;
}
#define CHECK_ARG_COUNT(ac,str) \
do { \
if ((ac+1) >= argc) { \
fputs(str,stderr); \
return -1; \
} \
} while (0) \
int get_options(optiondata *opt, motparm * mp, port_list * plist,
int argc, char *argv[])
{
char * prog = argv[0];
int ac;
init_structs(opt, mp, plist);
if ( argc < 2 )
return usage(prog, SH_USE_SHORT);
for ( ac = 1; ac < argc; ac++ ) /* help, hist first, rest alphabetical */
{
if ( !strncmp(argv[ac], "-help", 5) )
return usage(prog, SH_USE_LONG);
if ( !strncmp(argv[ac], "-hist", 5) )
return usage(prog, SH_USE_HIST);
else if ( !strncmp(argv[ac], "-debug", 6) )
{
CHECK_ARG_COUNT(ac, "opt use: -debug DEBUG_LEVEL\n");
opt->debug = atoi(argv[++ac]);
}
else if ( !strncmp(argv[ac], "-mp_max", 6) )
{
CHECK_ARG_COUNT(ac, "opt use: -mp_max MAX_MP_VAL\n");
opt->mp_max = atof(argv[++ac]);
}
else if ( !strncmp(argv[ac], "-mp_min", 6) )
{
CHECK_ARG_COUNT(ac, "opt use: -mp_min MIN_MP_VAL\n");
opt->mp_min = atof(argv[++ac]);
}
else if ( !strncmp(argv[ac], "-no_serial", 7) )
opt->no_serial = 1;
else if ( !strncmp(argv[ac], "-num_extra", 7) )
{
CHECK_ARG_COUNT(ac, "opt use: -num_extra NVALS\n");
opt->num_extra = atoi(argv[++ac]);
}
else if ( !strncmp(argv[ac], "-serial_port", 7) )
{
CHECK_ARG_COUNT(ac, "opt use: -serial_port SERIAL_FILENAME\n");
opt->serial_port = argv[++ac];
}
else if ( !strncmp(argv[ac], "-sock_num", 7) )
{
CHECK_ARG_COUNT(ac, "opt use: -sock_num SOCKET_NUMBER\n");
opt->sock_num = atoi(argv[++ac]);
}
else if ( !strncmp(argv[ac], "-swap", 5) )
opt->swap = 1;
else if ( !strncmp(argv[ac], "-ver", 4) )
return usage(prog, SH_USE_VERSION);
else
{
fprintf(stderr,"** invalid option '%s', exiting...\n", argv[ac]);
return -1;
}
}
/* check basic options */
if ( opt->sock_num <= 0 || opt->sock_num > 65536 )
{
fprintf(stderr,"** socket number %d is out of range\n", opt->sock_num);
return -1;
}
if ( ! opt->serial_port && opt->no_serial == 0 )
{
fprintf(stderr,"** missing option '-serial_port'\n");
return -1;
}
if ( opt->num_extra < 0 || opt->num_extra > 1000 )
{
fprintf(stderr,"** -num_extra %d is out of range [0,1000]\n",
opt->num_extra);
return -1;
}
if ( opt->debug > 1 )
disp_optiondata( "options read: ", opt );
plist->debug = opt->debug; /* for cleanup() */
mp->nvals = 6;
/* allocate space for extra data */
if ( opt->num_extra > 0 )
{
mp->nex = opt->num_extra;
mp->extras = (float *)malloc(mp->nex * sizeof(float));
if( !mp->extras )
{
fprintf(stderr,"** failed to alloc for %d extra floats\n", mp->nex);
return -1;
}
}
return 0;
}
/* ----------------------------------------------------------------------
* display usage
*
* SH_USE_SHORT : most basic usage info
* SH_USE_VERSION : display version number
* SH_USE_LONG : display complete description of program and options
* ----------------------------------------------------------------------
*/
int usage( char * prog, int level )
{
if ( level == SH_USE_SHORT )
printf( "usage: %s -help\n"
"usage: %s [options] -serial_port FILENAME\n", prog, prog );
else if ( level == SH_USE_HIST )
fputs( g_history, stdout );
else if ( level == SH_USE_VERSION )
printf( "%s, version %s, compiled %s\n", prog, VERSION, __DATE__ );
else if ( level == SH_USE_LONG )
{
printf(
"------------------------------------------------------------\n"
"%s - pass motion parameters from socket to serial port\n"
"\n"
" This program is meant to receive registration (motion?)\n"
" correction parameters from afni's realtime plugin, and to\n"
" pass that data on to a serial port.\n"
"\n"
" The program is meant to run as a tcp server. It listens\n"
" for a connection, then processes data until a termination\n"
" flag is received (sending data from the tcp socket to the\n"
" serial port), closes the new connection, and goes back\n"
" to a listening state.\n"
"\n"
" The basic outline is:\n"
"\n"
" open tcp server socket\n"
" repeat forever:\n"
" wait for a tcp client connection\n"
" open a serial port\n"
" while the client sends new data\n"
" write that data to the serial port\n"
" close the serial port and client socket\n"
"\n"
" The expected client is the realtime plugin to afni,\n"
" plug_realtime.so. If the afni user has their environment\n"
" variable AFNI_REALTIME_MP_HOST_PORT set as HOST:PORT,\n"
" then for EACH RUN, the realtime plugin will open a tcp\n"
" connection to the given HOST and PORT, pass the magic hello\n"
" data (0xabcdefab), pass the 6 motion parameters for each\n"
" time point, and signal a closure by passing the magic bye\n"
" data (0xdeaddead).\n"
"\n"
" On this server end, the 'repeat forever' loop will do the\n"
" following. First it will establish the connection by\n"
" checking for the magic hello data. If that data is found,\n"
" the serial port will be opened.\n"
"\n"
" Then it will repeatedly check the incoming data for the\n"
" magic bye data. As long as that check fails, the data is\n"
" assumed to be valid motion parameters. And so 6 floats at a\n"
" time are read from the incoming socket and passed to the\n"
" serial port.\n"
"\n"
" usage: %s [options] -serial_port FILENAME\n"
"------------------------------------------------------------\n"
" examples:\n"
"\n"
" 1. display this help :\n"
"\n"
" %s -help\n"
"\n"
" 2. display the module history :\n"
"\n"
" %s -hist\n"
"\n"
" 3. display the current version number :\n"
"\n"
" %s -ver\n"
"\n"
" * 4. run normally, using the serial port file /dev/ttyS0 :\n"
"\n"
" %s -serial_port /dev/ttyS0\n"
"\n"
" * 5. same as 4, but specify socket number 53214 :\n"
"\n"
" %s -serial_port /dev/ttyS0 -sock_num 53214\n"
"\n"
" 6. same as 5, but specify minmum and maximum bounds on\n"
" the values :\n"
"\n"
" %s \\\n"
" -serial_port /dev/ttyS0 \\\n"
" -sock_num 53214 \\\n"
" -mp_min -12.7 \\\n"
" -mp_max 12.7\n"
"\n"
" 7. run the program in socket test mode, without serial\n"
" communication, and printing all the incoming data\n"
"\n"
" %s -no_serial -debug 3\n"
"\n"
" 8. same as 4, but use debug level 3 to see the parameters\n"
" that will be passed on, and duplicate all output to the\n"
" file, helper.output\n"
"\n"
" note: this command is for the t-shell, and will not work\n"
" under bash (for bash do the 2>&1 thingy...)\n"
"\n"
" %s -serial_port /dev/ttyS0 -debug 3 |& tee helper.out\n"
"\n"
" 9. same as 4, but will receive 3 extra floats per TR\n"
"\n"
" %s -serial_port /dev/ttyS0 -num_extra 3\n"
"\n"
"------------------------------------------------------------\n"
" program setup:\n"
"\n"
" 1. Start '%s' on the computer with the serial port that\n"
" the motion parameters should be written to. Example 3\n"
" is the most likely case, though it might be useful to\n"
" use example 8.\n"
"\n"
" 2. On the computer which will be used to run 'afni -rt',\n"
" set the environment variable AFNI_REALTIME_MP_HOST_PORT\n"
" to the appropriate host:port pair. See the '-sock_num'\n"
" option below for more details.\n"
"\n"
" This variable can also be set in the ~/.cshrc file, or\n"
" as part of the AFNI environment via the ~/.afnirc file.\n"
"\n"
" 3. Start 'afni -rt'. Be sure to request 'realtime' graphing\n"
" of the '3D: realtime' Registration parameters.\n"
"\n"
" 4. Start receiving data (sending it to the realtime plugin).\n"
"\n"
" Note that for testing purposes, I may work well to get a\n"
" set of I-files (say, in directories 003, 023, etc.), and\n"
" to use Imon to send not-so-real-time data to afni. An\n"
" example of Imon for this purpose might be:\n"
"\n"
" Imon -start_dir 003 -quit -rt -host localhost\n"
"\n"
" See 'Imon -help' for more information.\n"
"------------------------------------------------------------\n"
" 'required' parameter:\n"
"\n"
" -serial_port FILENAME : specify output serial port\n"
" : -serial_port /dev/ttyS0\n"
"\n"
" If the user is not using any of the 'special' options,\n"
" below, then this parameter is required.\n"
"\n"
" The FILENAME is the device file for the serial port\n"
" which will be used for output.\n"
"------------------------------\n"
" special options (for information or testing):\n"
"\n"
" -help : show this help information\n"
"\n"
" -hist : show the module history\n"
"\n"
" -debug LEVEL : set the debugging level to LEVEL\n"
" : e.g. -debug 2\n"
" : default is 0, max is 3\n"
"\n"
" -no_serial : turn of serial port output\n"
"\n"
" This option is used for testing the incoming data,\n"
" when output to a serial port is not desired. The\n"
" program will otherwise operate normally.\n"
"\n"
" -version : show the current version number\n"
"------------------------------\n"
" 'normal' options:\n"
"\n"
" -mp_max MAX_VAL : limit the maximum value of the MP data\n"
" : e.g. -mp_max 12.7\n"
" : default is 12.7\n"
"\n"
" If any incoming data is greater than this value, it will\n"
" be set to this value. The default of 12.7 is used to\n"
" scale incoming floats to signed bytes.\n"
"\n"
" -mp_min MIN_VAL : limit the minimum value of the MP data\n"
" : e.g. -mp_min -12.7\n"
" : default is -12.7\n"
"\n"
" If any incoming data is less than this value, it will\n"
" be set to this value. The default of -12.7 is used to\n"
" scale incoming floats to signed bytes.\n"
"\n"
" -sock_num SOCK : specify socket number to serve\n"
" : e.g. -sock_num 53214\n"
" : default is 53214\n"
"\n"
" This is the socket the program will use to listen for\n"
" new connections. This is the socket number that should\n"
" be provided to the realtime plugin via the environment\n"
" variable, AFNI_REALTIME_MP_HOST_PORT.\n"
"\n"
" On the machine the user run afni from, that environment\n"
" variable should have the form HOST:PORT, where a basic\n"
" example might be localhost:53214.\n"
"\n"
" -num_extra NVALS : will receive NVALS extra floats per TR\n"
" : e.g. -num_extra 5\n"
" : default is 0\n"
"\n"
" Extra floats may arrive if, for instance, afni's RT\n"
" plugin has a mask with 3 ROIs in it (numbered 1,2,3).\n"
" The plugin would compute averages over each ROI per TR,\n"
" and send that data after the MP vals.\n"
" \n"
" In such a case, specify '-num_extra 3', so the program\n"
" knows 3 floats will be received after the MP data.\n"
"------------------------------------------------------------\n"
" Authors: R. Reynolds, T. Ross (March, 2004)\n"
"------------------------------------------------------------\n",
prog, prog,
prog, prog, prog, prog, prog, prog, prog, prog, prog,
prog
);
}
else
fprintf(stderr,"** usage error: invalid level %d\n", level);
return 1;
}
/* ----------------------------------------------------------------------
* check for close requeset
*
* return 1 : close
* 0 : continue
* -1 : error
* ----------------------------------------------------------------------
*/
int test_socket(int sd)
{
char data[16];
int len;
if ( (len = recv(sd, data, g_magic_len, MSG_PEEK)) == -1 )
{
fputs("** test_socket_failure\n", stderr);
perror("pe: recv");
return -1;
}
if ( strncmp(data, g_magic_bye, g_magic_len) == 0 )
return 1;
return 0;
}
/* ----------------------------------------------------------------------
* read one set of motion parameters (extras?) and store in structure
*
* return 1 : finished
* 0 : have data: continue
* -1 : error
* ----------------------------------------------------------------------
*/
int read_socket(optiondata * opt, port_list * plist, motparm * mp)
{
int rv, len;
if ( (rv = test_socket(plist->tdata_sd)) < 0 )
return -1;
else if ( rv == 1 )
{
if ( opt->debug > 0 )
fprintf(stderr,"++ found close request, mpcount = %d\n", mp->nread);
return 1;
}
/* get motion params */
len = mp->nvals * sizeof(float);
if ( (rv = recv(plist->tdata_sd, (void *)mp->data, len, 0)) < len )
{
fprintf(stderr,"** read only %d of %d bytes on socket\n", rv, len);
perror("pe: recv");
return -1;
}
if ( opt->swap ) swap_4(mp->data, mp->nvals);
/* get extra floats */
if( mp->nex > 0 )
{
len = mp->nex * sizeof(float);
if ( (rv = recv(plist->tdata_sd, (void *)mp->extras, len, 0)) < len )
{
fprintf(stderr,"** read only %d of %d Ebytes on socket\n", rv, len);
perror("pe: recv");
return -1;
}
if ( opt->swap ) swap_4(mp->extras, mp->nex);
}
mp->nread++;
if ( opt->debug > 2 ) /* display the data */
{
int c;
fprintf(stderr,"++ recv floats:");
for ( c = 0; c < mp->nvals; c++ )
fprintf(stderr," %f", mp->data[c]);
fputc('\n', stderr);
fprintf(stderr,"++ recv %d extra floats:", mp->nex);
for ( c = 0; c < mp->nex; c++ )
fprintf(stderr," %f", mp->extras[c]);
fputc('\n', stderr);
}
return 0;
}
/* Here we convert each mp data value to a char after multiplying by 10.
For now, I'm not sure what to do with the extras, send as is... */
void send_serial(optiondata * opt, port_list * plist, motparm *mot)
{
static char outdata[7];
int i, len;
outdata[0] = (char)(-128 + mot->nex); /* encode nex in handshake byte */
for(i = 0; i < 6; i++)
{
if (mot->data[i] > opt->mp_max)
mot->data[i] = opt->mp_max;
if (mot->data[i] < opt->mp_min)
mot->data[i] = opt->mp_min;
outdata[i+1] = (char) (mot->data[i] * 10.0);
}
i = write(plist->sport, outdata, 7);
if( i < 7 )
fprintf(stderr, "** warning: wrote %d of 7 bytes to serial port\n",i);
if( mot->nex > 0 )
{
len = mot->nex * sizeof(float);
i = write(plist->sport, mot->extras, len);
if( i < len )
fprintf(stderr,"** warning: wrote %d of %d Ebytes to serial port\n",
i, len);
}
}
int open_serial(optiondata *opt, port_list * plist)
{
int sport;
struct termios options;
sport = open(opt->serial_port, O_RDWR | O_NOCTTY | O_NDELAY);
if (sport == -1) {
perror("pe: Failed to open the serial port ");
return -1;
}
/*******************
set up the port
*******************/
fcntl(sport, F_SETFL, FNDELAY); /* nonblocking reads */
/* Get the current options for the port...*/
tcgetattr(sport, &options);
/* Set the baud rates to 9600 */
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
/* Enable the receiver and set local mode */
options.c_cflag |= (CLOCAL | CREAD );
/* set 8 bit N parity */
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
/* raw data input and output */
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
/*Set the new options for the port*/
if (tcsetattr(sport, TCSANOW, &options) == -1) {
perror("pe: Failed to set attributes on the serial port ");
close(sport);
return -1;
}
plist->sport = sport;
return 0;
}
/* ----------------------------------------------------------------------
* swap 4 bytes at a time
* ----------------------------------------------------------------------
*/
void swap_4( void * data, int nswaps )
{
char * cp, tmp;
int c;
for ( c = 0, cp = (char *)data; c < nswaps; c++, cp += 4 )
{
tmp = cp[0]; cp[0] = cp[3]; cp[3] = tmp;
tmp = cp[1]; cp[1] = cp[2]; cp[2] = tmp;
}
}
/* ----------------------------------------------------------------------
* display contents of optiondata struct
* ----------------------------------------------------------------------
*/
int disp_optiondata( char * info, optiondata * D )
{
if ( info )
fputs(info, stderr);
if ( ! D )
{
fprintf(stderr,"** disp_optiondata: D == NULL\n");
return -1;
}
fprintf(stderr,
" optiondata at %p :\n"
" serial_port = %s\n"
" no_serial = %d\n"
" mp_min, mp_max = %f, %f\n"
" sock_num = %d\n"
" num_extra = %d\n"
" swap, debug = %d, %d\n",
D, CHECK_NULL_STR(D->serial_port), D->no_serial,
D->mp_min, D->mp_max, D->sock_num, D->num_extra, D->swap, D->debug);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1