head 4.4; access ; symbols ; locks oasisa:4.4; strict; comment @ * @; 4.4 date 2001.06.19.12.16.10; author oasisa; state Exp; branches ; next ; desc @New Repository; 6/19/2001 (klh) @ 4.4 log @New Repository; 6/19/2001 (klh) @ text @/****************************************************************************/ /* Copyright 1991 - 1995 MBARI */ /****************************************************************************/ /* $Header: userif.c,v 1.1 2001/06/19 11:45:10 oasisa Exp $ */ /* Summary : User Interface Routines for OASIS Mooring Controller */ /* Filename : userif.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 1.1 $ */ /* Created : 02/15/91 */ /* */ /* MBARI provides this documentation and code "as is", with no warranty, */ /* express or implied, of its quality or consistency. It is provided without*/ /* support and without obligation on the part of the Monterey Bay Aquarium */ /* Research Institute to assist in its use, correction, modification, or */ /* enhancement. This information should not be published or distributed to */ /* third parties without specific written permission from MBARI. */ /* */ /****************************************************************************/ /* Modification History: */ /* 15feb91 rah - created */ /* $Log: userif.c,v $ * Revision 1.1 2001/06/19 11:45:10 11:45:10 oasisa (Oasis users) * Initial revision * * Revision 4.3 99/06/16 10:21:38 10:21:38 bobh (Bob Herlien) * Mar/May '99 Deployments of M3/M2 * * Revision 4.2 98/09/09 10:48:08 10:48:08 bobh (Bob Herlien) * Sept/Oct '98 deployments of M1, Eqpac 1 & 2 * * Revision 3.7 97/07/23 11:18:21 11:18:21 bobh (Bob Herlien) * July '97 M1 deployment, new shutter code * * Revision 3.6 96/10/30 14:00:24 14:00:24 bobh (Bob Herlien) * Release for EqPac, M2 Test Replacement * * Revision 3.4 96/06/18 15:24:35 15:24:35 bobh (Bob Herlien) * June '96 deployment of M1 * * Revision 3.3 95/04/13 13:47:04 13:47:04 hebo (Bob Herlien) * Drifter Deployment for Coop (flip) cruise * * Revision 3.2 95/04/11 14:03:33 14:03:33 hebo (Bob Herlien) * Drifter Deployment on IronEx * * Revision 3.1 95/03/10 09:45:16 09:45:16 hebo (Bob Herlien) * March '95 Deployment of M1 * * Revision 3.0 95/02/21 18:42:50 18:42:50 hebo (Bob Herlien) * February '95 Deployment * * Revision 2.5 94/01/11 17:16:07 17:16:07 hebo (Bob Herlien) * Fixed bug in "getlog", changed PRR format * * Revision 2.4 93/10/29 11:12:49 11:12:49 hebo (Bob Herlien) * November 1993 Deployment * * Revision 2.0 92/08/22 18:57:13 18:57:13 hebo (Bob Herlien) * August 1992 Deployment * * Revision 1.3 92/03/03 16:41:28 16:41:28 hebo (Bob Herlien 408-647-3748) * New defaults, restart check, perm power stuff, analog command * */ /****************************************************************************/ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* OASIS controller definitions */ #include /* OASIS I/O definitions */ #include /* SHUTCAL definition */ #include /* User Command table and externals */ #include /* OASIS Multitasking definitions */ #include /* Standard ctype.h defs */ #include /* Standard I/O */ #include /* Standard string.h defs */ #define TNC_PWRUP_TIME (2 * TICKS_PER_SECOND) /* Wait 2 secs after pwr up */ #define TNC_REPLY_FLUSH_TIME (3*TICKS_PER_SECOND/10) /* Wait 300 ms to flush TNC replies */ /********************************/ /* External Functions */ /********************************/ Extern Void ser_break( Nat16 port,Int16 count ); Extern Int16 xgetc_tmout( Nat16 tmout ); Extern Void xputc( Int16 c ); Extern Void xputs( const char *s ); Extern Void xprintf( const char *format, ... ); Extern Int16 xgets( char *s, Int16 len ); Extern Int16 xgets_tmout( char *s, Int16 len, Nat16 tmout ); Extern Void xdrain_ser( Nat16 tmout ); Extern Void xflush_ser( Nat16 tmout ); Extern MBool delimit( Reg char c ); Extern MBool getnum( char **s, Int16 *result, Nat16 radix ); Extern Void drv_ser_port( Driver *dp ); /* Setup serial port */ Extern Void drv_ser_release( Driver *dp ); /* Release serial port */ Extern Void drv_pwron( Driver *dp ); Extern Void drv_pwroff( Driver *dp ); Extern char *cmp_ulc( char *s, char *cs ); Extern char *find_str( char *src, char *tgt ); Extern Void bzero( void *s, int n ); Extern Void bcopy( const Byte *src, Byte *dst, Nat16 len ); Extern char *tmpMalloc( Nat16 size ); Extern Void tmpFree( char *ptr ); Extern char *permMalloc( Nat16 size ); Extern Void permFree( char *ptr ); Extern MBool getparm( Nat16 *result, Nat16 radix, Byte *buffer ); /********************************/ /* External Data */ /********************************/ Extern Reg Nat16 tick; /* 10 ms ticker */ Extern Reg MBool ext_wake; /* TRUE if woken by /wake pin */ Extern Reg TimeOfDay tod; /* Current time in TimeOfDay format */ Extern Int16 tncchr; /* TNC command character */ Extern const char * const signon; /* Signon message */ Extern TimeOfDay radio_time; /* Last time connected on radio */ Extern char *tnc_name; /* TNC node name */ #ifdef TNC Extern MBool tnc_connected; /* TRUE if we're connected to TNC */ #endif /********************************/ /* Module Local Data */ /********************************/ MLocal LstHead funcList; /* Function list */ MLocal const char prompt[] = "OASIS> "; #ifdef TNC MLocal const char * const tnc_cmds[] = { "NO ON", "EC OFF", "AX ON", "AU OFF", "BBS ON", "P 0", "PACT After 3", "DW 33", "TXD 33", "FR 5", "MAXF 4", "CP ON", "CR OFF", "M 0", "CONM C", "SE $1A", "TXU OFF", "F OFF", "STR 0", "ADR OFF" }; #endif /************************************************************************/ /* Function : get_parms */ /* Purpose : Parse parameters from user command tail */ /* Inputs : Command tail ptr, Ptr to array of parms, ptr to funcEntry*/ /* Outputs : Bit vector of parameters found */ /************************************************************************/ Nat16 get_parms( char *tailp, Int16 *parmp, FuncNode *fnp ) { Reg Nat16 i, pmask, radix; pmask = 0; bzero( (void *)parmp, NPARMS * sizeof(Nat16) ); /* Init parms to 0 */ for ( i = 0; i < NPARMS; i++ ) { deblank( tailp ); if ( *tailp == '\0' ) break; if ( *tailp == ',' ) { tailp++; continue; } radix = 16; /* Init radix to hex */ parmp[i] = (Nat16)tailp; /* Init parm for string */ switch( fnp->fn_parmtype[i] ) { case STRING: /* String type. Go til next */ while ( !delimit(*tailp) ) /* delimiter */ tailp++; pmask |= (1 << i ); break; case ALL: /* Get all of command tail */ tailp += strlen(tailp); pmask |= (1 << i ); break; case DEC: /* Get decimal number */ radix = 10; /* NOTE FALL THRU! */ case HEX: /* Get hex number */ if ( getnum(&tailp, &parmp[i], radix) ) pmask |= (1 << i ); } if ( *tailp ) *tailp++ = '\0'; } return( pmask ); } /* get_parms() */ /************************************************************************/ /* Function : one_usr_cmd */ /* Purpose : Do one cycle of user cmd & response */ /* Inputs : Buffer ptr, len, timeout in seconds */ /* Outputs : OK, ERROR, or ABORT */ /************************************************************************/ Int16 one_usr_cmd( char *buffer, Nat16 buflen, Nat16 tmout ) { Reg FuncNode *fnp; /* FuncList node ptr */ Reg char *tail; /* Ptr to tail of cmd string*/ Reg Nat16 pmask; /* Parameter mask */ Reg Int16 rtn; /* Function return code */ Int16 parms[NPARMS]; /* Function parameters */ xputs( prompt ); /* Print prompt */ if ( (rtn = xgets_tmout(buffer, buflen, tmout)) == ERROR ) { /* If timed out, abort */ xputs("Timeout\n"); return( ABORT ); } if ( rtn == 0 ) /* If no command, return OK*/ return( OK ); for ( fnp = (FuncNode *)list_first(&funcList); fnp != FN_NULL; fnp = (FuncNode *)list_next((Node *)fnp) ) { /* Find funcList entry */ if ( (tail = cmp_ulc(buffer, fnp->fn_cs)) != NULL ) { pmask = get_parms(tail, parms, fnp ); if ( (rtn = (*fnp->fn_cmd)(pmask, parms[0], parms[1], parms[2], buffer)) != ERROR ) return( rtn ); break; } } xputs("Bad Command\n"); return( ERROR ); } /* one_usr_cmd() */ /************************************************************************/ /* Function : usrif */ /* Purpose : User I/F Main routine. Called by usr_drv or radio_drv */ /* Inputs : Timeout in seconds */ /* Outputs : OK, ERROR if got too many bad cmds, ABORT if no memory */ /************************************************************************/ Int16 usrif( Nat16 tmout ) { Int16 rtn; Nat16 badcnt; char *buffer; if ( (buffer = tmpMalloc(USR_BUFSIZE)) == NULL ) return( ABORT ); /* If no memory, return ABORT */ /* TNC Name=Deployment */ #ifndef FULL_SIGNON xputs(signon); #else xputs(signon); xputs(tnc_name); xputs("\n"); #endif /*xputs( signon );*/ /* Print signon message */ badcnt = 0; /* Init bad cmd counter */ while ( (rtn = one_usr_cmd(buffer, USR_BUFSIZE, tmout)) != ABORT ) { /* Do user interface */ if ( (rtn == ERROR) && (++badcnt > 50) ) break; /* Check for infinite loop */ } tmpFree( buffer ); /* Free buffer */ return( rtn ); } /* usrif() */ /************************************************************************/ /* Function : usr_drv */ /* Purpose : User I/F Main routine */ /* Inputs : Driver Pointer */ /* Outputs : None */ /************************************************************************/ Void usr_drv( Driver *dp ) { if ( !ext_wake ) return; drv_ser_port( dp ); /* Setup serial port */ usrif( dp->drv_parms[TIMEOUT] ); drv_ser_release( dp ); /* Release serial port */ ext_wake = FALSE; /* If called 2nd time, short tmout*/ } /* usr_drv() */ #ifdef TNC /************************************************************************/ /* Function : tnc_cmd_mode */ /* Purpose : Put TNC in Command mode */ /* Inputs : None */ /* Outputs : None */ /************************************************************************/ Void tnc_cmd_mode( Void ) { xputc( tncchr ); /* Go to cmd mode */ xflush_ser( TNC_REPLY_FLUSH_TIME ); /* Clear incoming buffer*/ } /* tnc_cmd_mode() */ /************************************************************************/ /* Function : tnc_converse */ /* Purpose : Put TNC in Converse mode */ /* Inputs : None */ /* Outputs : None */ /************************************************************************/ Void tnc_converse( Void ) { xputs("K\r"); /* Go to converse mode */ xflush_ser( TNC_REPLY_FLUSH_TIME ); /* Throw away reply */ } /* tnc_converse() */ /************************************************************************/ /* Function : sendTncCmd */ /* Purpose : Send a command to the TNC */ /* Inputs : Command string to send */ /* Outputs : None */ /************************************************************************/ Void sendTncCmd( char *cmd ) { tnc_cmd_mode(); xprintf("%s\r", cmd); xflush_ser( TNC_REPLY_FLUSH_TIME ); } /* sendTncCmd() */ /************************************************************************/ /* Function : tnc_status */ /* Purpose : Get STATus message from TNC */ /* Inputs : None */ /* Outputs : Status of TNC, or ERROR */ /* Comment : Leaves TNC in command mode */ /************************************************************************/ Int16 tnc_status( Void ) { char *p; Int16 res; char buff[32]; res = ERROR; /* Init result */ tnc_cmd_mode(); /* Go to command mode */ xputs("STAT\r"); /* Ask for status */ while ( xgets_tmout(buff, sizeof(buff), 1) != ERROR ) if ( (p = find_str(buff, "$")) != NULL ) if (getnum(&p, &res, 16)) break; xflush_ser( TNC_REPLY_FLUSH_TIME ); /* Throw away extra "cmd:"*/ return( res ); } /* tnc_status() */ /************************************************************************/ /* Function : wait_connect */ /* Purpose : Wait for (dis)connect status */ /* Inputs : Boolean (TRUE to look for connect, FALSE to look for */ /* disconnect), timeout in seconds */ /* Outputs : MBool, TRUE if found appropriate status */ /************************************************************************/ MBool wait_connect( MBool connect, Nat16 tmout ) { Nat16 startTick; for ( startTick = tick; (tick - startTick) < (tmout * TICKS_PER_SECOND); ) { task_delay( TICKS_PER_SECOND/2 ); if ( connect ) { if ( (tnc_status() & 0xfffd) == 4 ) return( TRUE ); } else { if ( tnc_status() == 0 ) return( TRUE ); } } return( FALSE ); } /* wait_connect() */ /************************************************************************/ /* Function : tnc_init */ /* Purpose : Initialize TNC parameters */ /* Inputs : None */ /* Outputs : None */ /************************************************************************/ Void tnc_init( Void ) { Nat16 i; tnc_cmd_mode(); /* Go to command mode */ xputs( "RESET\r" ); /* Go to command mode, Reset TNC*/ xflush_ser( TICKS_PER_SECOND/2 ); /* Clear incoming buffer */ for ( i = 0; i < Number(tnc_cmds); i++ ) { xprintf("%s\r", tnc_cmds[i]); /* Send command */ xflush_ser( TNC_REPLY_FLUSH_TIME ); /* Throw away reply */ } xprintf("MY %s\r", tnc_name); /* Set up TNC name string */ xflush_ser( TNC_REPLY_FLUSH_TIME ); /* Throw away reply */ } /* tnc_init() */ /************************************************************************/ /* Function : radio_drv */ /* Purpose : Packet Radio Driver */ /* Inputs : Driver Pointer */ /* Outputs : None */ /************************************************************************/ Void radio_drv( Driver *dp ) { drv_ser_port( dp ); /* Setup serial port */ task_delay( TNC_PWRUP_TIME ); /* Wait for TNC to come alive */ xflush_ser( TNC_REPLY_FLUSH_TIME ); /* Throw away signon message */ if ( (dp->drv_flags & DO_INIT) || (--dp->drv_cnt <= 0) ) { /* Initialize TNC if needed */ tnc_init(); /* Init TNC */ dp->drv_flags &= ~DO_INIT; /* Turn off init flag */ dp->drv_cnt = dp->drv_parms[PARM2]; } if ( wait_connect(TRUE, dp->drv_parms[PARM0]) ) { /* Wait for connection */ tnc_connected = TRUE; /* Show we're connected */ radio_time = tod; /* Remember when connected */ tnc_converse(); /* Go to converse mode */ if ( usrif(dp->drv_parms[TIMEOUT]) == ERROR ) /* Do the user interface */ dp->drv_flags |= DO_INIT; /* If lots of bad cmds, re-init */ while ( dp->drv_wakeup <= tod ) /* Reset wakeup */ dp->drv_wakeup += dp->drv_parms[INTERVAL]; if ( tnc_connected ) /* If still connected, disconnect*/ sendTncCmd( "DISC" ); /* Request disconnect */ wait_connect(FALSE, dp->drv_parms[PARM1]); task_delay( 3 * TICKS_PER_SECOND ); } drv_ser_release( dp ); /* Release serial port */ drv_pwroff( dp ); /* Turn off radio power */ } /* radio_drv() */ #endif /* TNC */ #ifdef RF9600 /************************************************************************/ /* Function : radio_drv */ /* Purpose : Packet Radio Driver */ /* Inputs : Driver Pointer */ /* Outputs : None */ /************************************************************************/ Void radio_drv( Driver *dp ) { drv_ser_port( dp ); /* Setup serial port */ task_delay( TNC_PWRUP_TIME ); /* Wait for TNC to come alive */ xflush_ser( TNC_REPLY_FLUSH_TIME ); /* Throw away signon message */ if ( xgetc_tmout(dp->drv_parms[PARM0]) != ERROR ) { /* Wait for connection */ radio_time = tod; /* Remember when connected */ usrif(dp->drv_parms[TIMEOUT]); /* Do the user interface */ while ( dp->drv_wakeup <= tod ) /* Reset wakeup */ dp->drv_wakeup += dp->drv_parms[INTERVAL]; } drv_ser_release( dp ); /* Release serial port */ drv_pwroff( dp ); /* Turn off radio power */ } /* radio_drv() */ #endif /* RF9600 */ /************************************************************************/ /* Function : usrColdInit */ /* Purpose : Reset userif module due to cold (full) init */ /* Inputs : None */ /* Outputs : None */ /************************************************************************/ Void usrColdInit( Void ) { Reg FuncNode *fnp; Reg const FuncEntry *fep; Reg Nat16 i; list_init( &funcList ); if ( (fnp = (FuncNode *)permMalloc(Number(functbl) * sizeof(FuncNode))) != FN_NULL ) for ( i = 0, fep = functbl; i < Number(functbl); i++, fnp++, fep++ ) { bcopy( (Byte *)fep, (Byte *)&fnp->fn_cs, sizeof(FuncEntry) ); list_add( &funcList, (Node *)fnp ); } } /* usrColdInit() */ /************************************************************************/ /* Function : help */ /* Purpose : User Help Function */ /* Inputs : None */ /* Outputs : OK */ /* Comments : Placed here, rather than in usrcmds.c, because it needs*/ /* access to the user function table */ /************************************************************************/ Int16 help( Void ) { FuncNode *fnp; for ( fnp = (FuncNode *)list_first(&funcList); fnp != FN_NULL; fnp = (FuncNode *)list_next((Node *)fnp) ) { if ( fnp->fn_info != NULL ) xprintf("%12s%s\n", fnp->fn_cs, fnp->fn_info); } return( OK ); } /* help() */ /************************************************************************/ /* Function : cmdAdd */ /* Purpose : Add User Function */ /* Inputs : None */ /* Outputs : OK */ /* Comments : Placed here, rather than in usrcmds.c, because it needs*/ /* access to the user function table */ /************************************************************************/ Int16 cmdAdd( Nat16 pmask, char *name, Int16 (*func)(), char *help, Byte *buffer ) { Reg FuncNode *fnp; Reg Nat16 namelen, helplen; Nat16 i, result; FuncNode *fnpsave; if ( (pmask & 3) != 3 ) return( ERROR ); namelen = strlen(name) + 1; helplen = strlen(help) + 1; if ( (fnp = (FuncNode *)permMalloc(sizeof(FuncNode) + namelen + helplen)) == FN_NULL ) return( ERROR ); fnpsave = fnp; fnp->fn_cmd = func; fnp->fn_cs = (char *)(fnp + 1); bcopy( (Byte *)name, (Byte *)fnp->fn_cs, namelen ); if ( helplen == 0 ) fnp->fn_info = NULL; else { fnp->fn_info = fnp->fn_cs + namelen; bcopy( (Byte *)help, (Byte *)fnp->fn_info, helplen ); } for ( i = 0; i < NPARMS; i++ ) { xprintf("Type of parameter %d: 0=NONE, 1=STRING, 2=ALL, 3=DEC, 4=HEX\n", i); if ( !getparm(&result, 10, buffer) ) { permFree( (char *)fnp ); return( ERROR ); } fnpsave->fn_parmtype[i] = result; } list_add( &funcList, (Node *)fnpsave ); return( OK ); } /* cmdAdd() */ @