Fri Sep 29 11:12:53 2006

Asterisk developer's documentation


app_rpt.c File Reference

#include "asterisk.h"
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <search.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/io.h>
#include <math.h>
#include <tonezone.h>
#include <linux/zaptel.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/callerid.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/features.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/localtime.h"

Include dependency graph for app_rpt.c:

Go to the source code of this file.

Data Structures

struct  function_table_tag
struct  morse_bits
struct  rpt
struct  rpt_link
struct  rpt_tele
struct  telem_defaults

Defines

#define ACTIONSIZE   32
#define DEFAULT_IOBASE   0x378
#define DISC_TIME   10000
#define DTMF_TIMEOUT   3
#define ENDCHAR   '#'
#define FUNCCHAR   '*'
#define FUNCTDELAY   1500
#define FUNCTIONS   "functions"
#define HANGTIME   5000
#define IDTIME   300000
#define MAX_RETRIES   5
#define MAXCONNECTTIME   5000
#define MAXDTMF   32
#define MAXNODESTR   300
#define MAXREMSTR   15
#define MAXRPTS   20
#define MEMORY   "memory"
#define MORSE   "morse"
#define MSWAIT   200
#define NODES   "nodes"
#define POLITEID   30000
#define RECONNECT_KLUDGE
#define REDUNDANT_TX_TIME   2000
#define REM_SCANTIME   100
#define RETRY_TIMER_MS   5000
#define TELEMETRY   "telemetry"
#define TELEPARAMSIZE   256
#define TOTIME   180000

Enumerations

enum  { REM_OFF, REM_MONITOR, REM_TX }
enum  {
  ID, PROC, TERM, COMPLETE,
  UNKEY, REMDISC, REMALREADY, REMNOTFOUND,
  REMGO, CONNECTED, CONNFAIL, STATUS,
  TIMEOUT, ID1, STATS_TIME, STATS_VERSION,
  IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH
}
enum  { REM_SIMPLEX, REM_MINUS, REM_PLUS }
enum  { REM_LOWPWR, REM_MEDPWR, REM_HIPWR }
enum  {
  DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE,
  DC_DOKEY
}
enum  {
  SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE,
  SOURCE_DPHONE
}
enum  { DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM }
enum  { REM_MODE_FM, REM_MODE_USB, REM_MODE_LSB, REM_MODE_AM }
enum  {
  HF_SCAN_OFF, HF_SCAN_DOWN_SLOW, HF_SCAN_DOWN_QUICK, HF_SCAN_DOWN_FAST,
  HF_SCAN_UP_SLOW, HF_SCAN_UP_QUICK, HF_SCAN_UP_FAST
}

Functions

static int attempt_reconnect (struct rpt *myrpt, struct rpt_link *l)
static int check_freq (struct rpt *myrpt, int m, int d, int *defmode)
static int check_freq_ft897 (int m, int d, int *defmode)
static int check_freq_rbi (int m, int d, int *defmode)
static int closerem (struct rpt *myrpt)
static int closerem_ft897 (struct rpt *myrpt)
static int collect_function_digits (struct rpt *myrpt, char *digits, int command_source, struct rpt_link *mylink)
char * description (void)
 Provides a description of the module.
static int function_autopatchdn (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
static int function_autopatchup (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
static int function_cop (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
static int function_ilink (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
static int function_remote (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
static int function_status (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
static int get_wait_interval (struct rpt *myrpt, int type)
static void handle_link_data (struct rpt *myrpt, struct rpt_link *mylink, char *str)
static void handle_link_phone_dtmf (struct rpt *myrpt, struct rpt_link *mylink, char c)
static int handle_remote_data (struct rpt *myrpt, char *str)
static int handle_remote_dtmf_digit (struct rpt *myrpt, char c, char *keyed, int phonemode)
static int handle_remote_phone_dtmf (struct rpt *myrpt, char c, char *keyed, int phonemode)
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
static int multimode_bump_freq (struct rpt *myrpt, int interval)
static int multimode_bump_freq_ft897 (struct rpt *myrpt, int interval)
static int multimode_capable (struct rpt *myrpt)
static int myatoi (char *str)
static int play_silence (struct ast_channel *chan, int duration)
static int play_tone (struct ast_channel *chan, int freq, int duration, int amplitude)
static int play_tone_pair (struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
static int rbi_mhztoband (char *str)
static void rbi_out (struct rpt *myrpt, unsigned char *data)
static void rbi_out_parallel (struct rpt *myrpt, unsigned char *data)
static int rbi_pltocode (char *str)
static int retrieve_astcfgint (char *category, char *name, int min, int max, int defl)
static int rmt_saycharstr (struct rpt *myrpt, struct ast_channel *chan, int delay, char *charstr)
static int rmt_sayfile (struct rpt *myrpt, struct ast_channel *chan, int delay, char *filename)
static int rmt_telem_finish (struct rpt *myrpt, struct ast_channel *chan)
static int rmt_telem_start (struct rpt *myrpt, struct ast_channel *chan, int delay)
static void * rpt (void *this)
static void * rpt_call (void *this)
static int rpt_do_debug (int fd, int argc, char *argv[])
static int rpt_exec (struct ast_channel *chan, void *data)
static void * rpt_master (void *ignore)
static void * rpt_tele_thread (void *this)
static void rpt_telemetry (struct rpt *myrpt, int mode, void *data)
static int saycharstr (struct ast_channel *mychannel, char *str)
static int sayfile (struct ast_channel *mychannel, char *fname)
static int saynum (struct ast_channel *mychannel, int num)
static void send_link_dtmf (struct rpt *myrpt, char c)
static int send_morse (struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
static int send_tone_telemetry (struct ast_channel *chan, char *tonestring)
static int serial_remote_io (struct rpt *myrpt, char *txbuf, int txbytes, char *rxbuf, int rxmaxbytes, int asciiflag)
static int service_scan (struct rpt *myrpt)
static int set_ctcss_freq_ft897 (struct rpt *myrpt, char *txtone, char *rxtone)
static int set_ctcss_mode_ft897 (struct rpt *myrpt, char txplon, char rxplon)
static int set_freq_ft897 (struct rpt *myrpt, char *newfreq)
static int set_ft897 (struct rpt *myrpt)
static int set_mode_ft897 (struct rpt *myrpt, char newmode)
static int set_offset_ft897 (struct rpt *myrpt, char offset)
static int setrbi (struct rpt *myrpt)
static int setrem (struct rpt *myrpt)
static int simple_command_ft897 (struct rpt *myrpt, char command)
static int split_ctcss_freq (char *hertz, char *decimal, char *freq)
static int split_freq (char *mhz, char *decimals, char *freq)
static void stop_scan (struct rpt *myrpt, int flag)
static int telem_any (struct ast_channel *chan, char *entry)
static int telem_lookup (struct ast_channel *chan, char *node, char *name)
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.
static void wait_interval (struct rpt *myrpt, int type, struct ast_channel *chan)

Variables

static char * app = "Rpt"
ast_configcfg
static struct ast_cli_entry cli_debug
static int debug = 0
static char debug_usage []
static char * descrip
char * discstr = "!!DISCONNECT!!"
static struct function_table_tag function_table []
 LOCAL_USER_DECL
static int nrpts = 0
static char * remote_rig_ft897 = "ft897"
static char * remote_rig_rbi = "rbi"
static pthread_t rpt_master_thread
static struct rpt rpt_vars [MAXRPTS]
 STANDARD_LOCAL_USER
static char * synopsis = "Radio Repeater/Remote Base Control System"
static char * tdesc = "Radio Repeater / Remote Base version 0.37 11/03/2005"
static struct telem_defaults tele_defs []


Define Documentation

#define ACTIONSIZE   32

Definition at line 131 of file app_rpt.c.

#define DEFAULT_IOBASE   0x378

Definition at line 125 of file app_rpt.c.

Referenced by rpt_master().

#define DISC_TIME   10000

Definition at line 108 of file app_rpt.c.

Referenced by rpt().

#define DTMF_TIMEOUT   3

Definition at line 106 of file app_rpt.c.

Referenced by handle_remote_dtmf_digit(), and rpt().

#define ENDCHAR   '#'

Definition at line 123 of file app_rpt.c.

Referenced by rpt_master().

#define FUNCCHAR   '*'

Definition at line 122 of file app_rpt.c.

Referenced by rpt_master().

#define FUNCTDELAY   1500

Definition at line 259 of file app_rpt.c.

#define FUNCTIONS   "functions"

Definition at line 119 of file app_rpt.c.

Referenced by rpt_master().

#define HANGTIME   5000

Definition at line 254 of file app_rpt.c.

Referenced by rpt_master().

#define IDTIME   300000

Definition at line 256 of file app_rpt.c.

Referenced by rpt_master().

#define MAX_RETRIES   5

Definition at line 109 of file app_rpt.c.

Referenced by function_ilink(), handle_link_data(), rpt(), and rpt_exec().

#define MAXCONNECTTIME   5000

Definition at line 127 of file app_rpt.c.

Referenced by rpt().

#define MAXDTMF   32

Definition at line 105 of file app_rpt.c.

Referenced by handle_link_data(), handle_link_phone_dtmf(), handle_remote_dtmf_digit(), and rpt().

#define MAXNODESTR   300

Definition at line 129 of file app_rpt.c.

Referenced by function_ilink(), and rpt_exec().

#define MAXREMSTR   15

Definition at line 115 of file app_rpt.c.

Referenced by function_remote(), multimode_bump_freq_ft897(), service_scan(), set_ctcss_freq_ft897(), set_freq_ft897(), setrbi(), split_ctcss_freq(), and split_freq().

#define MAXRPTS   20

Definition at line 257 of file app_rpt.c.

#define MEMORY   "memory"

Definition at line 118 of file app_rpt.c.

Referenced by function_remote().

#define MORSE   "morse"

Definition at line 121 of file app_rpt.c.

Referenced by telem_any().

#define MSWAIT   200

Definition at line 253 of file app_rpt.c.

Referenced by rpt(), rpt_call(), and rpt_exec().

#define NODES   "nodes"

Definition at line 117 of file app_rpt.c.

Referenced by rpt_master().

#define POLITEID   30000

Definition at line 258 of file app_rpt.c.

Referenced by rpt_master().

#define RECONNECT_KLUDGE

Definition at line 101 of file app_rpt.c.

#define REDUNDANT_TX_TIME   2000

Definition at line 111 of file app_rpt.c.

Referenced by rpt(), and rpt_exec().

#define REM_SCANTIME   100

Definition at line 135 of file app_rpt.c.

Referenced by function_remote().

#define RETRY_TIMER_MS   5000

Definition at line 113 of file app_rpt.c.

Referenced by rpt().

#define TELEMETRY   "telemetry"

Definition at line 120 of file app_rpt.c.

Referenced by telem_lookup().

#define TELEPARAMSIZE   256

Definition at line 133 of file app_rpt.c.

Referenced by rpt_telemetry().

#define TOTIME   180000

Definition at line 255 of file app_rpt.c.

Referenced by rpt_master().


Enumeration Type Documentation

anonymous enum

Enumerator:
REM_OFF 
REM_MONITOR 
REM_TX 

Definition at line 138 of file app_rpt.c.

anonymous enum

Enumerator:
ID 
PROC 
TERM 
COMPLETE 
UNKEY 
REMDISC 
REMALREADY 
REMNOTFOUND 
REMGO 
CONNECTED 
CONNFAIL 
STATUS 
TIMEOUT 
ID1 
STATS_TIME 
STATS_VERSION 
IDTALKOVER 
ARB_ALPHA 
TEST_TONE 
REV_PATCH 

Definition at line 140 of file app_rpt.c.

anonymous enum

Enumerator:
REM_SIMPLEX 
REM_MINUS 
REM_PLUS 

Definition at line 144 of file app_rpt.c.

anonymous enum

Enumerator:
REM_LOWPWR 
REM_MEDPWR 
REM_HIPWR 

Definition at line 146 of file app_rpt.c.

anonymous enum

Enumerator:
DC_INDETERMINATE 
DC_REQ_FLUSH 
DC_ERROR 
DC_COMPLETE 
DC_DOKEY 

Definition at line 148 of file app_rpt.c.

anonymous enum

Enumerator:
SOURCE_RPT 
SOURCE_LNK 
SOURCE_RMT 
SOURCE_PHONE 
SOURCE_DPHONE 

Definition at line 150 of file app_rpt.c.

anonymous enum

Enumerator:
DLY_TELEM 
DLY_ID 
DLY_UNKEY 
DLY_CALLTERM 

Definition at line 152 of file app_rpt.c.

anonymous enum

Enumerator:
REM_MODE_FM 
REM_MODE_USB 
REM_MODE_LSB 
REM_MODE_AM 

Definition at line 154 of file app_rpt.c.

anonymous enum

Enumerator:
HF_SCAN_OFF 
HF_SCAN_DOWN_SLOW 
HF_SCAN_DOWN_QUICK 
HF_SCAN_DOWN_FAST 
HF_SCAN_UP_SLOW 
HF_SCAN_UP_QUICK 
HF_SCAN_UP_FAST 

Definition at line 156 of file app_rpt.c.


Function Documentation

static int attempt_reconnect ( struct rpt myrpt,
struct rpt_link l 
) [static]

Definition at line 4467 of file app_rpt.c.

References ast_call(), AST_FORMAT_SLINEAR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_set_read_format(), ast_set_write_format(), ast_variable_retrieve(), ast_verbose(), cfg, free, rpt::links, rpt::lock, LOG_NOTICE, rpt::name, rpt_link::name, rpt_link::next, rpt::nodes, option_verbose, s, strdup, strsep(), and VERBOSE_PREFIX_3.

Referenced by rpt().

04468 {
04469    char *val, *s, *s1, *s2, *tele;
04470    char tmp[300], deststr[300] = "";
04471 
04472    val = ast_variable_retrieve(cfg, myrpt->nodes, l->name);
04473    if (!val)
04474    {
04475       fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
04476       return -1;
04477    }
04478 
04479    ast_mutex_lock(&myrpt->lock);
04480    /* remove from queue */
04481    remque((struct qelem *) l);
04482    ast_mutex_unlock(&myrpt->lock);
04483    strncpy(tmp,val,sizeof(tmp) - 1);
04484    s = tmp;
04485    s1 = strsep(&s,",");
04486    s2 = strsep(&s,",");
04487    snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
04488    tele = strchr(deststr, '/');
04489    if (!tele) {
04490       fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
04491       return -1;
04492    }
04493    *tele++ = 0;
04494    l->elaptime = 0;
04495    l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
04496    if (l->chan){
04497       ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
04498       ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
04499       l->chan->whentohangup = 0;
04500       l->chan->appl = "Apprpt";
04501       l->chan->data = "(Remote Rx)";
04502       if (option_verbose > 2)
04503          ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
04504             deststr, tele, l->chan->name);
04505       if(l->chan->cid.cid_num)
04506          free(l->chan->cid.cid_num);
04507       l->chan->cid.cid_num = strdup(myrpt->name);
04508                 ast_call(l->chan,tele,999); 
04509 
04510    }
04511    else 
04512    {
04513       if (option_verbose > 2)
04514          ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
04515             deststr,tele,l->chan->name);
04516       return -1;
04517    }
04518    ast_mutex_lock(&myrpt->lock);
04519    /* put back in queue queue */
04520    insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
04521    ast_mutex_unlock(&myrpt->lock);
04522    ast_log(LOG_NOTICE,"Reconnect Attempt to %s in process\n",l->name);
04523    return 0;
04524 }

static int check_freq ( struct rpt myrpt,
int  m,
int  d,
int *  defmode 
) [static]

Definition at line 3436 of file app_rpt.c.

References check_freq_ft897(), check_freq_rbi(), and rpt::remote.

Referenced by function_remote().

03437 {
03438    if(!strcmp(myrpt->remote, remote_rig_ft897))
03439       return check_freq_ft897(m, d, defmode);
03440    else if(!strcmp(myrpt->remote, remote_rig_rbi))
03441       return check_freq_rbi(m, d, defmode);
03442    else
03443       return -1;
03444 }

static int check_freq_ft897 ( int  m,
int  d,
int *  defmode 
) [static]

Definition at line 3041 of file app_rpt.c.

References REM_MODE_FM, REM_MODE_LSB, and REM_MODE_USB.

Referenced by check_freq(), and multimode_bump_freq_ft897().

03042 {
03043    int dflmd = REM_MODE_FM;
03044 
03045    if(m == 1){ /* 160 meters */
03046       dflmd =  REM_MODE_LSB; 
03047       if(d < 80001)
03048          return -1;
03049    }
03050    else if(m == 3){ /* 80 meters */
03051       dflmd = REM_MODE_LSB;
03052       if(d < 75001)
03053          return -1;
03054    }
03055    else if(m == 7){ /* 40 meters */
03056       dflmd = REM_MODE_LSB;
03057       if((d < 15001) || (d > 29999))
03058          return -1;
03059    }
03060    else if(m == 14){ /* 20 meters */
03061       dflmd = REM_MODE_USB;
03062       if((d < 15001) || (d > 34999))
03063          return -1;
03064    }
03065    else if(m == 18){ /* 17 meters */
03066       dflmd = REM_MODE_USB;
03067       if((d < 11001) || (d > 16797))
03068          return -1;
03069    }
03070    else if(m == 21){ /* 15 meters */
03071       dflmd = REM_MODE_USB;
03072       if((d < 20001) || (d > 44999))
03073          return -1;
03074    }
03075    else if(m == 24){ /* 12 meters */
03076       dflmd = REM_MODE_USB;
03077       if((d < 93001) || (d > 98999))
03078          return -1;
03079    }
03080    else if(m == 28){ /* 10 meters */
03081       dflmd = REM_MODE_USB;
03082       if(d < 30001)
03083          return -1;
03084    }
03085    else if(m == 29){ 
03086       if(d >= 51000)
03087          dflmd = REM_MODE_FM;
03088       else
03089          dflmd = REM_MODE_USB;
03090       if(d > 69999)
03091          return -1;
03092    }
03093    else if(m == 50){ /* 6 meters */
03094       if(d < 10100)
03095          return -1;
03096       if(d >= 30000)
03097          dflmd = REM_MODE_FM;
03098       else
03099          dflmd = REM_MODE_USB;
03100 
03101    }
03102    else if((m >= 51) && ( m < 54)){
03103       dflmd = REM_MODE_FM;
03104    }
03105    else if(m == 144){ /* 2 meters */
03106       if(d < 10100)
03107          return -1;
03108       if(d >= 30000)
03109          dflmd = REM_MODE_FM;
03110       else
03111          dflmd = REM_MODE_USB;
03112    }
03113    else if((m >= 145) && (m < 148)){
03114       dflmd = REM_MODE_FM;
03115    }
03116    else if((m >= 430) && (m < 450)){ /* 70 centimeters */
03117       if(m  < 438)
03118          dflmd = REM_MODE_USB;
03119       else
03120          dflmd = REM_MODE_FM;
03121       ;
03122    }
03123    else
03124       return -1;
03125 
03126    if(defmode)
03127       *defmode = dflmd;
03128 
03129    return 0;
03130 }

static int check_freq_rbi ( int  m,
int  d,
int *  defmode 
) [static]

Definition at line 2950 of file app_rpt.c.

References REM_MODE_FM.

Referenced by check_freq().

02951 {
02952    int dflmd = REM_MODE_FM;
02953 
02954    if(m == 50){ /* 6 meters */
02955       if(d < 10100)
02956          return -1;
02957    }
02958    else if((m >= 51) && ( m < 54)){
02959                 ;
02960    }
02961    else if(m == 144){ /* 2 meters */
02962       if(d < 10100)
02963          return -1;
02964    }
02965    else if((m >= 145) && (m < 148)){
02966       ;
02967    }
02968    else if((m >= 222) && (m < 225)){ /* 1.25 meters */
02969       ;
02970    }
02971    else if((m >= 430) && (m < 450)){ /* 70 centimeters */
02972       ;
02973    }
02974    else if((m >= 1240) && (m < 1300)){ /* 23 centimeters */
02975       ;
02976    }
02977    else
02978       return -1;
02979    
02980    if(defmode)
02981       *defmode = dflmd; 
02982 
02983 
02984    return 0;
02985 }

static int closerem ( struct rpt myrpt  )  [static]

Definition at line 3424 of file app_rpt.c.

References closerem_ft897(), and rpt::remote.

03425 {
03426    if(!strcmp(myrpt->remote, remote_rig_ft897))
03427       return closerem_ft897(myrpt);
03428    else
03429       return 0;
03430 }

static int closerem_ft897 ( struct rpt myrpt  )  [static]

Definition at line 3358 of file app_rpt.c.

References simple_command_ft897().

Referenced by closerem().

03359 {
03360    simple_command_ft897(myrpt, 0x88); /* PTT off */
03361    return 0;
03362 }  

static int collect_function_digits ( struct rpt myrpt,
char *  digits,
int  command_source,
struct rpt_link mylink 
) [static]

Definition at line 2260 of file app_rpt.c.

References ast_variable_browse(), cfg, DC_ERROR, DC_INDETERMINATE, rpt::dphone_functions, rpt::dphone_longestfunc, function_table, rpt::functions, rpt::link_functions, rpt::link_longestfunc, rpt::longestfunc, n, ast_variable::name, ast_variable::next, rpt::phone_functions, rpt::phone_longestfunc, SOURCE_DPHONE, SOURCE_LNK, SOURCE_PHONE, strsep(), and ast_variable::value.

Referenced by handle_link_data(), handle_link_phone_dtmf(), handle_remote_dtmf_digit(), and rpt().

02262 {
02263    int i;
02264    char *stringp,*action,*param,*functiondigits;
02265    char function_table_name[30] = "";
02266    char workstring[80];
02267    
02268    struct ast_variable *vp;
02269    
02270    if(debug)   
02271       printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
02272    
02273    if (command_source == SOURCE_DPHONE) {
02274       if (!myrpt->dphone_functions) return DC_INDETERMINATE;
02275       strncpy(function_table_name, myrpt->dphone_functions, sizeof(function_table_name) - 1);
02276       }
02277    else if (command_source == SOURCE_PHONE) {
02278       if (!myrpt->phone_functions) return DC_INDETERMINATE;
02279       strncpy(function_table_name, myrpt->phone_functions, sizeof(function_table_name) - 1);
02280       }
02281    else if (command_source == SOURCE_LNK)
02282       strncpy(function_table_name, myrpt->link_functions, sizeof(function_table_name) - 1);
02283    else
02284       strncpy(function_table_name, myrpt->functions, sizeof(function_table_name) - 1);
02285    vp = ast_variable_browse(cfg, function_table_name);
02286    while(vp) {
02287       if(!strncasecmp(vp->name, digits, strlen(vp->name)))
02288          break;
02289       vp = vp->next;
02290    }  
02291    if(!vp) {
02292       int n;
02293 
02294       n = myrpt->longestfunc;
02295       if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
02296       else 
02297       if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
02298       else 
02299       if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
02300       
02301       if(strlen(digits) >= n)
02302          return DC_ERROR;
02303       else
02304          return DC_INDETERMINATE;
02305    }  
02306    /* Found a match, retrieve value part and parse */
02307    strncpy(workstring, vp->value, sizeof(workstring) - 1 );
02308    stringp = workstring;
02309    action = strsep(&stringp, ",");
02310    param = stringp;
02311    if(debug)
02312       printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
02313    /* Look up the action */
02314    for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
02315       if(!strncasecmp(action, function_table[i].action, strlen(action)))
02316          break;
02317    }
02318    if(debug)
02319       printf("@@@@ table index i = %d\n",i);
02320    if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
02321       /* Error, action not in table */
02322       return DC_ERROR;
02323    }
02324    if(function_table[i].function == NULL){
02325       /* Error, function undefined */
02326       if(debug)
02327          printf("@@@@ NULL for action: %s\n",action);
02328       return DC_ERROR;
02329    }
02330    functiondigits = digits + strlen(vp->name);
02331    return (*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
02332 }

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 6544 of file app_rpt.c.

06545 {
06546    return tdesc;
06547 }

static int function_autopatchdn ( struct rpt myrpt,
char *  param,
char *  digitbuf,
int  command_source,
struct rpt_link mylink 
) [static]

Definition at line 2164 of file app_rpt.c.

References ast_mutex_lock(), ast_mutex_unlock(), rpt::callmode, DC_COMPLETE, DC_ERROR, rpt::enable, rpt::lock, rpt_telemetry(), and TERM.

02165 {
02166    if (!myrpt->enable)
02167       return DC_ERROR;
02168    
02169    if(debug)
02170       printf("@@@@ Autopatch down\n");
02171       
02172    ast_mutex_lock(&myrpt->lock);
02173    
02174    if (!myrpt->callmode){
02175       ast_mutex_unlock(&myrpt->lock);
02176       return DC_COMPLETE;
02177    }
02178    
02179    myrpt->callmode = 0;
02180    ast_mutex_unlock(&myrpt->lock);
02181    rpt_telemetry(myrpt, TERM, NULL);
02182    return DC_COMPLETE;
02183 }

static int function_autopatchup ( struct rpt myrpt,
char *  param,
char *  digitbuf,
int  command_source,
struct rpt_link mylink 
) [static]

Definition at line 2128 of file app_rpt.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, rpt::callmode, rpt::cidx, DC_COMPLETE, DC_ERROR, rpt::enable, rpt::exten, rpt::funcchar, rpt::lock, rpt::mydtmf, rpt_call(), and rpt::rpt_call_thread.

02129 {
02130    pthread_attr_t attr;
02131    
02132       
02133    if (!myrpt->enable)
02134       return DC_ERROR;
02135       
02136    if(debug)
02137       printf("@@@@ Autopatch up\n");
02138 
02139    ast_mutex_lock(&myrpt->lock);
02140    
02141    /* if on call, force * into current audio stream */
02142    
02143    if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
02144       myrpt->mydtmf = myrpt->funcchar;
02145    }
02146    if (myrpt->callmode){
02147       ast_mutex_unlock(&myrpt->lock);
02148       return DC_COMPLETE;
02149    }
02150    myrpt->callmode = 1;
02151    myrpt->cidx = 0;
02152    myrpt->exten[myrpt->cidx] = 0;
02153    ast_mutex_unlock(&myrpt->lock);
02154    pthread_attr_init(&attr);
02155    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02156    ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
02157    return DC_COMPLETE;
02158 }

static int function_cop ( struct rpt myrpt,
char *  param,
char *  digitbuf,
int  command_source,
struct rpt_link mylink 
) [static]

Definition at line 2221 of file app_rpt.c.

References ARB_ALPHA, DC_COMPLETE, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, rpt::disgorgetime, rpt::enable, myatoi(), rpt_telemetry(), SOURCE_PHONE, and TEST_TONE.

02222 {
02223    if(!param)
02224       return DC_ERROR;
02225    
02226    switch(myatoi(param)){
02227       case 1: /* System reset */
02228          system("killall -9 asterisk"); /* FIXME to drastic? */
02229          return DC_COMPLETE;
02230 
02231       case 2:
02232          myrpt->enable = 1;
02233          rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
02234          return DC_COMPLETE;
02235          
02236       case 3:
02237          myrpt->enable = 0;
02238          return DC_COMPLETE;
02239          
02240       case 4: /* test tone on */
02241          rpt_telemetry(myrpt, TEST_TONE, NULL);
02242          return DC_COMPLETE;
02243 
02244       case 5: /* Disgorge variables to log for debug purposes */
02245          myrpt->disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
02246          return DC_COMPLETE;
02247 
02248       case 6: /* Simulate COR being activated (phone only) */
02249          if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
02250          return DC_DOKEY;  
02251 
02252    }  
02253    return DC_INDETERMINATE;
02254 }

static int function_ilink ( struct rpt myrpt,
char *  param,
char *  digitbuf,
int  command_source,
struct rpt_link mylink 
) [static]

Definition at line 1766 of file app_rpt.c.

References ast_call(), AST_FORMAT_SLINEAR, AST_FRAME_TEXT, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_safe_sleep(), ast_set_read_format(), ast_set_write_format(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_true(), ast_variable_retrieve(), ast_verbose(), ast_write(), cfg, rpt_link::chan, rpt::cmdnode, COMPLETE, rpt::conf, CONNFAIL, ast_frame::data, ast_frame::datalen, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt_link::disced, rpt::enable, ast_frame::frametype, free, rpt::lastlinknode, rpt::links, rpt::lock, LOG_WARNING, rpt::longestnode, malloc, ast_frame::mallocd, MAX_RETRIES, MAXNODESTR, rpt_link::mode, myatoi(), rpt::name, rpt_link::name, rpt_link::next, rpt::nodes, ast_frame::offset, option_verbose, REMALREADY, REMGO, rpt_link::retries, rpt_telemetry(), s, ast_frame::samples, SOURCE_DPHONE, SOURCE_PHONE, SOURCE_RPT, STATUS, strdup, strsep(), ast_frame::subclass, and VERBOSE_PREFIX_3.

01767 {
01768 
01769    char *val, *s, *s1, *s2, *tele;
01770    char tmp[300], deststr[300] = "",modechange = 0;
01771    char digitbuf[MAXNODESTR];
01772    struct rpt_link *l;
01773    ZT_CONFINFO ci;  /* conference info */
01774 
01775    if(!param)
01776       return DC_ERROR;
01777       
01778          
01779    if (!myrpt->enable)
01780       return DC_ERROR;
01781 
01782    strncpy(digitbuf,digits,MAXNODESTR - 1);
01783 
01784    if(debug)
01785       printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
01786       
01787    switch(myatoi(param)){
01788       case 1: /* Link off */
01789          if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
01790             strcpy(digitbuf,myrpt->lastlinknode);
01791          val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
01792          if (!val){
01793             if(strlen(digitbuf) >= myrpt->longestnode)
01794                return DC_ERROR;
01795             break;
01796          }
01797          strncpy(tmp,val,sizeof(tmp) - 1);
01798          s = tmp;
01799          s1 = strsep(&s,",");
01800          s2 = strsep(&s,",");
01801          ast_mutex_lock(&myrpt->lock);
01802          l = myrpt->links.next;
01803          /* try to find this one in queue */
01804          while(l != &myrpt->links){
01805             if (l->name[0] == '0') 
01806             {
01807                l = l->next;
01808                continue;
01809             }
01810             /* if found matching string */
01811             if (!strcmp(l->name, digitbuf))
01812                break;
01813             l = l->next;
01814          }
01815          if (l != &myrpt->links){ /* if found */
01816             struct   ast_frame wf;
01817 
01818             strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
01819             l->retries = MAX_RETRIES + 1;
01820             l->disced = 1;
01821             ast_mutex_unlock(&myrpt->lock);
01822             wf.frametype = AST_FRAME_TEXT;
01823             wf.subclass = 0;
01824             wf.offset = 0;
01825             wf.mallocd = 1;
01826             wf.datalen = strlen(discstr) + 1;
01827             wf.samples = 0;
01828             wf.data = strdup(discstr);
01829             if (l->chan)
01830             {
01831                ast_write(l->chan,&wf);
01832                if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
01833                ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
01834             }
01835             rpt_telemetry(myrpt, COMPLETE, NULL);
01836             return DC_COMPLETE;
01837          }
01838          ast_mutex_unlock(&myrpt->lock);  
01839          return DC_COMPLETE;
01840       case 2: /* Link Monitor */
01841          if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
01842             strcpy(digitbuf,myrpt->lastlinknode);
01843          val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
01844          if (!val){
01845             if(strlen(digitbuf) >= myrpt->longestnode)
01846                return DC_ERROR;
01847             break;
01848          }
01849          strncpy(tmp,val,sizeof(tmp) - 1);
01850          s = tmp;
01851          s1 = strsep(&s,",");
01852          s2 = strsep(&s,",");
01853          ast_mutex_lock(&myrpt->lock);
01854          l = myrpt->links.next;
01855          /* try to find this one in queue */
01856          while(l != &myrpt->links){
01857             if (l->name[0] == '0') 
01858             {
01859                l = l->next;
01860                continue;
01861             }
01862             /* if found matching string */
01863             if (!strcmp(l->name, digitbuf))
01864                break;
01865             l = l->next;
01866          }
01867          /* if found */
01868          if (l != &myrpt->links) 
01869          {
01870             /* if already in this mode, just ignore */
01871             if ((!l->mode) || (!l->chan)) {
01872                ast_mutex_unlock(&myrpt->lock);
01873                rpt_telemetry(myrpt,REMALREADY,NULL);
01874                return DC_COMPLETE;
01875                
01876             }
01877             ast_mutex_unlock(&myrpt->lock);
01878             if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
01879             l->retries = MAX_RETRIES + 1;
01880             l->disced = 2;
01881             modechange = 1;
01882          } else
01883             ast_mutex_unlock(&myrpt->lock);
01884          strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
01885          /* establish call in monitor mode */
01886          l = malloc(sizeof(struct rpt_link));
01887          if (!l){
01888             ast_log(LOG_WARNING, "Unable to malloc\n");
01889             return DC_ERROR;
01890          }
01891          /* zero the silly thing */
01892          memset((char *)l,0,sizeof(struct rpt_link));
01893          snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
01894          tele = strchr(deststr,'/');
01895          if (!tele){
01896             fprintf(stderr,"link2:Dial number (%s) must be in format tech/number\n",deststr);
01897             return DC_ERROR;
01898          }
01899          *tele++ = 0;
01900          l->isremote = (s && ast_true(s));
01901          strncpy(l->name, digitbuf, MAXNODESTR - 1);
01902          l->chan = ast_request(deststr,AST_FORMAT_SLINEAR,tele,NULL);
01903          if (modechange) l->connected = 1;
01904          if (l->chan){
01905             ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
01906             ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
01907             l->chan->whentohangup = 0;
01908             l->chan->appl = "Apprpt";
01909             l->chan->data = "(Remote Rx)";
01910             if (option_verbose > 2)
01911                ast_verbose(VERBOSE_PREFIX_3 "rpt (remote) initiating call to %s/%s on %s\n",
01912                   deststr,tele,l->chan->name);
01913             if(l->chan->cid.cid_num)
01914                free(l->chan->cid.cid_num);
01915             l->chan->cid.cid_num = strdup(myrpt->name);
01916             ast_call(l->chan,tele,0);
01917          }
01918          else
01919          {
01920             rpt_telemetry(myrpt,CONNFAIL,l);
01921             free(l);
01922             if (option_verbose > 2)
01923                ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
01924                   deststr,tele,l->chan->name);
01925             return DC_ERROR;
01926          }
01927          /* allocate a pseudo-channel thru asterisk */
01928          l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
01929          if (!l->pchan){
01930             fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
01931             ast_hangup(l->chan);
01932             free(l);
01933             return DC_ERROR;
01934          }
01935          ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
01936          ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
01937          /* make a conference for the pseudo-one */
01938          ci.chan = 0;
01939          ci.confno = myrpt->conf;
01940          ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
01941          /* first put the channel on the conference in proper mode */
01942          if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
01943          {
01944             ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01945             ast_hangup(l->chan);
01946             ast_hangup(l->pchan);
01947             free(l);
01948             return DC_ERROR;
01949          }
01950          ast_mutex_lock(&myrpt->lock);
01951          /* insert at end of queue */
01952          insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
01953          ast_mutex_unlock(&myrpt->lock);
01954          rpt_telemetry(myrpt,COMPLETE,NULL);
01955          return DC_COMPLETE;
01956       case 3: /* Link transceive */
01957          if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
01958             strcpy(digitbuf,myrpt->lastlinknode);
01959          val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
01960          if (!val){
01961             if(strlen(digitbuf) >= myrpt->longestnode)
01962                return DC_ERROR;
01963             break;
01964          }
01965          strncpy(tmp,val,sizeof(tmp) - 1);
01966          s = tmp;
01967          s1 = strsep(&s,",");
01968          s2 = strsep(&s,",");
01969          ast_mutex_lock(&myrpt->lock);
01970          l = myrpt->links.next;
01971          /* try to find this one in queue */
01972          while(l != &myrpt->links){
01973             if (l->name[0] == '0') 
01974             {
01975                l = l->next;
01976                continue;
01977             }
01978             /* if found matching string */
01979             if (!strcmp(l->name, digitbuf))
01980                break;
01981             l = l->next;
01982          }
01983          /* if found */
01984          if (l != &myrpt->links){ 
01985             /* if already in this mode, just ignore */
01986             if ((l->mode) || (!l->chan)) {
01987                ast_mutex_unlock(&myrpt->lock);
01988                rpt_telemetry(myrpt, REMALREADY, NULL);
01989                return DC_COMPLETE;
01990             }
01991             ast_mutex_unlock(&myrpt->lock);
01992             if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
01993             l->retries = MAX_RETRIES + 1;
01994             l->disced = 2;
01995             modechange = 1;
01996          } else
01997             ast_mutex_unlock(&myrpt->lock);
01998          strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
01999          /* establish call in tranceive mode */
02000          l = malloc(sizeof(struct rpt_link));
02001          if (!l){
02002             ast_log(LOG_WARNING, "Unable to malloc\n");
02003             return(DC_ERROR);
02004          }
02005          /* zero the silly thing */
02006          memset((char *)l,0,sizeof(struct rpt_link));
02007          l->mode = 1;
02008          l->outbound = 1;
02009          strncpy(l->name, digitbuf, MAXNODESTR - 1);
02010          l->isremote = (s && ast_true(s));
02011          if (modechange) l->connected = 1;
02012          snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
02013          tele = strchr(deststr, '/');
02014          if (!tele){
02015             fprintf(stderr,"link3:Dial number (%s) must be in format tech/number\n",deststr);
02016             free(l);
02017             return DC_ERROR;
02018          }
02019          *tele++ = 0;
02020          l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
02021          if (l->chan){
02022             ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
02023             ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
02024             l->chan->whentohangup = 0;
02025             l->chan->appl = "Apprpt";
02026             l->chan->data = "(Remote Rx)";
02027             if (option_verbose > 2)
02028                ast_verbose(VERBOSE_PREFIX_3 "rpt (remote) initiating call to %s/%s on %s\n",
02029                   deststr, tele, l->chan->name);
02030             if(l->chan->cid.cid_num)
02031                free(l->chan->cid.cid_num);
02032             l->chan->cid.cid_num = strdup(myrpt->name);
02033             ast_call(l->chan,tele,999);
02034          }
02035          else{
02036             rpt_telemetry(myrpt,CONNFAIL,l);
02037             free(l);
02038             if (option_verbose > 2)
02039                ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
02040                   deststr,tele,l->chan->name);
02041             return DC_ERROR;
02042          }
02043          /* allocate a pseudo-channel thru asterisk */
02044          l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
02045          if (!l->pchan){
02046             fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
02047             ast_hangup(l->chan);
02048             free(l);
02049             return DC_ERROR;
02050          }
02051          ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
02052          ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
02053          /* make a conference for the tx */
02054          ci.chan = 0;
02055          ci.confno = myrpt->conf;
02056          ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
02057          /* first put the channel on the conference in proper mode */
02058          if (ioctl(l->pchan->fds[0], ZT_SETCONF, &ci) == -1)
02059          {
02060             ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
02061             ast_hangup(l->chan);
02062             ast_hangup(l->pchan);
02063             free(l);
02064             return DC_ERROR;
02065          }
02066          ast_mutex_lock(&myrpt->lock);
02067          /* insert at end of queue */
02068          insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
02069          ast_mutex_unlock(&myrpt->lock);
02070          rpt_telemetry(myrpt,COMPLETE,NULL);
02071          return DC_COMPLETE;
02072       case 4: /* Enter Command Mode */
02073       
02074          /* if doesnt allow link cmd, or no links active, return */
02075          if (((command_source != SOURCE_RPT) && (command_source != SOURCE_PHONE) && (command_source != SOURCE_DPHONE)) || (myrpt->links.next == &myrpt->links))
02076             return DC_COMPLETE;
02077          
02078          /* if already in cmd mode, or selected self, fughetabahtit */
02079          if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
02080          
02081             rpt_telemetry(myrpt, REMALREADY, NULL);
02082             return DC_COMPLETE;
02083          }
02084          if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
02085             strcpy(digitbuf,myrpt->lastlinknode);
02086          /* node must at least exist in list */
02087          val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
02088          if (!val){
02089             if(strlen(digitbuf) >= myrpt->longestnode)
02090                return DC_ERROR;
02091             break;
02092          
02093          }
02094          ast_mutex_lock(&myrpt->lock);
02095          strcpy(myrpt->lastlinknode,digitbuf);
02096          strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
02097          ast_mutex_unlock(&myrpt->lock);
02098          rpt_telemetry(myrpt, REMGO, NULL);  
02099          return DC_COMPLETE;
02100          
02101       case 5: /* Status */
02102          rpt_telemetry(myrpt, STATUS, NULL);
02103          return DC_COMPLETE;
02104          
02105          
02106       case 6: /* All Links Off */
02107          l = myrpt->links.next;
02108          
02109          while(l != &myrpt->links){
02110             if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); /* Hang 'em up */
02111             l = l->next;
02112          }
02113          rpt_telemetry(myrpt, COMPLETE, NULL);
02114          break;
02115    
02116       default:
02117          return DC_ERROR;
02118          
02119    }
02120    
02121    return DC_INDETERMINATE;
02122 }  

static int function_remote ( struct rpt myrpt,
char *  param,
char *  digitbuf,
int  command_source,
struct rpt_link mylink 
) [static]

Definition at line 3618 of file app_rpt.c.

References AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_safe_sleep(), ast_variable_retrieve(), cfg, check_freq(), DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt::freq, HF_SCAN_DOWN_FAST, HF_SCAN_DOWN_QUICK, HF_SCAN_DOWN_SLOW, HF_SCAN_UP_FAST, HF_SCAN_UP_QUICK, HF_SCAN_UP_SLOW, rpt::hfscanmode, MAXREMSTR, MEMORY, multimode_bump_freq(), multimode_capable(), myatoi(), rpt::name, rpt::offset, offset, rpt::powerlevel, REM_HIPWR, REM_LOWPWR, REM_MEDPWR, REM_MINUS, REM_MODE_AM, REM_MODE_FM, REM_MODE_LSB, REM_MODE_USB, REM_PLUS, REM_SCANTIME, REM_SIMPLEX, rpt::remchannel, rpt::remmode, rpt::remoterx, rpt::remotetx, rmt_saycharstr(), rmt_sayfile(), rmt_telem_finish(), rmt_telem_start(), rpt::rxpl, rpt::rxplon, s, saycharstr(), sayfile(), saynum(), rpt::scantimer, setrem(), SOURCE_LNK, SOURCE_RPT, split_freq(), strsep(), rpt::tunerequest, rpt::txchannel, rpt::txpl, and rpt::txplon.

03619 {
03620    char *s,*s1,*s2,*val;
03621    int i,j,ht,k,l,ls2,m,d,res,offset,offsave, modesave, defmode;
03622    char multimode = 0;
03623    char oc;
03624    char tmp[20], freq[20] = "", savestr[20] = "";
03625    char mhz[MAXREMSTR], decimals[MAXREMSTR];
03626    struct ast_channel *mychannel;
03627 
03628    if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
03629       return DC_ERROR;
03630       
03631    multimode = multimode_capable(myrpt);
03632 
03633    mychannel = myrpt->remchannel;
03634    
03635    
03636    switch(myatoi(param)){
03637 
03638       case 1:  /* retrieve memory */
03639          if(strlen(digitbuf) < 2) /* needs 2 digits */
03640             break;
03641          
03642          for(i = 0 ; i < 2 ; i++){
03643             if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03644                return DC_ERROR;
03645          }
03646        
03647          val = ast_variable_retrieve(cfg, MEMORY, digitbuf);
03648          if (!val){
03649             if (ast_safe_sleep(mychannel,1000) == -1)
03650                return DC_ERROR;
03651             sayfile(mychannel,"rpt/memory_notfound");
03652             return DC_COMPLETE;
03653          }        
03654          strncpy(tmp,val,sizeof(tmp) - 1);
03655          s = strchr(tmp,',');
03656          if (!s)
03657             return DC_ERROR;
03658          *s++ = 0;
03659          s1 = strchr(s,',');
03660          if (!s1)
03661             return DC_ERROR;
03662          *s1++ = 0;
03663          strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
03664          strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
03665          strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
03666          myrpt->remmode = REM_MODE_FM;
03667          myrpt->offset = REM_SIMPLEX;
03668          myrpt->powerlevel = REM_MEDPWR;
03669          myrpt->txplon = myrpt->rxplon = 0;
03670          while(*s1)
03671          {
03672             switch(*s1++){
03673                case 'A':
03674                case 'a':
03675                   strcpy(myrpt->rxpl, "100.0");
03676                   strcpy(myrpt->txpl, "100.0");
03677                   myrpt->remmode = REM_MODE_AM; 
03678                   break;
03679                
03680                case 'B':
03681                case 'b':
03682                   strcpy(myrpt->rxpl, "100.0");
03683                   strcpy(myrpt->txpl, "100.0");
03684                   myrpt->remmode = REM_MODE_LSB;
03685                   break;
03686          
03687                case 'F':
03688                   myrpt->remmode = REM_MODE_FM;
03689                   break;
03690 
03691                case 'L':
03692                case 'l':
03693                   myrpt->powerlevel = REM_LOWPWR;
03694                   break;               
03695                case 'H':
03696                case 'h':
03697                   myrpt->powerlevel = REM_HIPWR;
03698                   break;
03699                
03700                case 'M':
03701                case 'm':
03702                   myrpt->powerlevel = REM_MEDPWR;
03703                   break;
03704                   
03705                case '-':
03706                   myrpt->offset = REM_MINUS;
03707                   break;
03708                   
03709                case '+':
03710                   myrpt->offset = REM_PLUS;
03711                   break;
03712                   
03713                case 'S':
03714                case 's':
03715                   myrpt->offset = REM_SIMPLEX;
03716                   break;
03717                   
03718                case 'T':
03719                case 't':
03720                   myrpt->txplon = 1;
03721                   break;
03722                   
03723                case 'R':
03724                case 'r':
03725                   myrpt->rxplon = 1;
03726                   break;
03727 
03728                case 'U':
03729                case 'u':
03730                   strcpy(myrpt->rxpl, "100.0");
03731                   strcpy(myrpt->txpl, "100.0");
03732                   myrpt->remmode = REM_MODE_USB;
03733                   break;
03734             }
03735          }
03736       
03737       
03738          if (setrem(myrpt) == -1)
03739             return DC_ERROR;
03740       
03741       
03742          return DC_COMPLETE;  
03743          
03744       case 2:  /* set freq and offset */
03745       
03746          
03747             for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for M+*K+*O or M+*H+* depending on mode */
03748             if(digitbuf[i] == '*'){
03749                j++;
03750                continue;
03751             }
03752             if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03753                goto invalid_freq;
03754             else{
03755                if(j == 0)
03756                   l++; /* # of digits before first * */
03757                if(j == 1)
03758                   k++; /* # of digits after first * */
03759             }
03760          }
03761       
03762          i = strlen(digitbuf) - 1;
03763          if(multimode){
03764             if((j > 2) || (l > 3) || (k > 6))
03765                goto invalid_freq; /* &^@#! */
03766          }
03767          else{
03768             if((j > 2) || (l > 4) || (k > 3))
03769                goto invalid_freq; /* &^@#! */
03770          }
03771 
03772          /* Wait for M+*K+* */
03773 
03774          if(j < 2)
03775             break; /* Not yet */
03776 
03777          /* We have a frequency */
03778 
03779          strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
03780          
03781          s = tmp;
03782          s1 = strsep(&s, "*"); /* Pick off MHz */
03783          s2 = strsep(&s,"*"); /* Pick off KHz and Hz */
03784          ls2 = strlen(s2); 
03785          
03786          switch(ls2){ /* Allow partial entry of khz and hz digits for laziness support */
03787             case 1:
03788                ht = 0;
03789                k = 100 * atoi(s2);
03790                break;
03791             
03792             case 2:
03793                ht = 0;
03794                k = 10 * atoi(s2);
03795                break;
03796                
03797             case 3:
03798                if(!multimode){
03799                   if((s2[2] != '0')&&(s2[2] != '5'))
03800                      goto invalid_freq;
03801                }
03802                ht = 0;
03803                k = atoi(s2);
03804                   break;
03805             case 4:
03806                k = atoi(s2)/10;
03807                ht = 10 * (atoi(s2+(ls2-1)));
03808                break;
03809 
03810             case 5:
03811                k = atoi(s2)/100;
03812                ht = (atoi(s2+(ls2-2)));
03813                break;
03814                
03815             default:
03816                goto invalid_freq;
03817          }
03818 
03819          /* Check frequency for validity and establish a default mode */
03820          
03821          snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
03822 
03823          if(debug)
03824             printf("New frequency: %s\n", freq);      
03825    
03826          split_freq(mhz, decimals, freq);
03827          m = atoi(mhz);
03828          d = atoi(decimals);
03829 
03830                         if(check_freq(myrpt, m, d, &defmode)) /* Check to see if frequency entered is legit */
03831                                 goto invalid_freq;
03832 
03833 
03834          if((defmode == REM_MODE_FM) && (digitbuf[i] == '*')) /* If FM, user must enter and additional offset digit */
03835             break; /* Not yet */
03836 
03837 
03838          offset = REM_SIMPLEX; /* Assume simplex */
03839 
03840          if(defmode == REM_MODE_FM){
03841             oc = *s; /* Pick off offset */
03842          
03843             if (oc){
03844                switch(oc){
03845                   case '1':
03846                      offset = REM_MINUS;
03847                      break;
03848                   
03849                   case '2':
03850                      offset = REM_SIMPLEX;
03851                   break;
03852                   
03853                   case '3':
03854                      offset = REM_PLUS;
03855                      break;
03856                   
03857                   default:
03858                      goto invalid_freq;
03859                } 
03860             } 
03861          }  
03862          offsave = myrpt->offset;
03863          modesave = myrpt->remmode;
03864          strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
03865          strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
03866          myrpt->offset = offset;
03867          myrpt->remmode = defmode;
03868 
03869          if (setrem(myrpt) == -1){
03870             myrpt->offset = offsave;
03871             myrpt->remmode = modesave;
03872             strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
03873             goto invalid_freq;
03874          }
03875 
03876          return DC_COMPLETE;
03877 
03878 
03879          invalid_freq:
03880    
03881          rmt_sayfile(myrpt, mychannel, 1000, "rpt/invalid-freq");
03882 
03883          return DC_ERROR; 
03884       
03885       case 3: /* set rx PL tone */
03886          
03887             for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N */
03888             if(digitbuf[i] == '*'){
03889                j++;
03890                continue;
03891             }
03892             if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03893                return DC_ERROR;
03894             else{
03895                if(j)
03896                   l++;
03897                else
03898                   k++;
03899             }
03900          }
03901          if((j > 1) || (k > 3) || (l > 1))
03902             return DC_ERROR; /* &$@^! */
03903          i = strlen(digitbuf) - 1;
03904          if((j != 1) || (k < 2)|| (l != 1))
03905             break; /* Not yet */
03906          if(debug)
03907             printf("PL digits entered %s\n", digitbuf);
03908             
03909          strncpy(tmp, digitbuf, sizeof(tmp) - 1);
03910          /* see if we have at least 1 */
03911          s = strchr(tmp,'*');
03912          if(s)
03913             *s = '.';
03914          strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
03915          strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
03916          
03917          if (setrem(myrpt) == -1){
03918             strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
03919             return DC_ERROR;
03920          }
03921       
03922       
03923          return DC_COMPLETE;
03924       
03925       case 4: /* set tx PL tone */
03926          
03927             for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N */
03928             if(digitbuf[i] == '*'){
03929                j++;
03930                continue;
03931             }
03932             if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03933                return DC_ERROR;
03934             else{
03935                if(j)
03936                   l++;
03937                else
03938                   k++;
03939             }
03940          }
03941          if((j > 1) || (k > 3) || (l > 1))
03942             return DC_ERROR; /* &$@^! */
03943          i = strlen(digitbuf) - 1;
03944          if((j != 1) || (k < 2)|| (l != 1))
03945             break; /* Not yet */
03946          if(debug)
03947             printf("PL digits entered %s\n", digitbuf);
03948             
03949          strncpy(tmp, digitbuf, sizeof(tmp) - 1);
03950          /* see if we have at least 1 */
03951          s = strchr(tmp,'*');
03952          if(s)
03953             *s = '.';
03954          strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
03955          strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
03956          
03957          if (setrem(myrpt) == -1){
03958             strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
03959             return DC_ERROR;
03960          }
03961       
03962       
03963          return DC_COMPLETE;
03964       
03965 
03966       case 6: /* MODE (FM,USB,LSB,AM) */
03967          if(strlen(digitbuf) < 1)
03968             break;
03969 
03970          if(!multimode)
03971             return DC_ERROR; /* Multimode radios only */
03972 
03973          switch(*digitbuf){
03974             case '1':
03975                split_freq(mhz, decimals, myrpt->freq); 
03976                m=atoi(mhz);
03977                if(m < 29) /* No FM allowed below 29MHz! */
03978                   return DC_ERROR;
03979                myrpt->remmode = REM_MODE_FM;
03980                res = rmt_saycharstr(myrpt, mychannel, 1000,"FM");
03981                break;
03982 
03983             case '2':
03984                myrpt->remmode = REM_MODE_USB;
03985                res = rmt_saycharstr(myrpt, mychannel, 1000,"USB");
03986                break;   
03987 
03988             case '3':
03989                myrpt->remmode = REM_MODE_LSB;
03990                res = rmt_saycharstr(myrpt, mychannel, 1000,"LSB");
03991                break;
03992             
03993             case '4':
03994                myrpt->remmode = REM_MODE_AM;
03995                res = rmt_saycharstr(myrpt, mychannel, 1000,"AM");
03996                break;
03997       
03998             default:
03999                return DC_ERROR;
04000          }
04001          if(res)
04002             return DC_ERROR;
04003 
04004          if(setrem(myrpt))
04005             return DC_ERROR;
04006          return DC_COMPLETE;
04007 
04008       case 100: /* other stuff */
04009       case 101: 
04010       case 102: 
04011       case 103: 
04012       case 104: 
04013       case 105: 
04014       case 106:
04015          res = rmt_telem_start(myrpt, mychannel, 1000);
04016          switch(myatoi(param)){ /* Quick commands requiring a setrem call */
04017             case 100: /* RX PL Off */
04018                myrpt->rxplon = 0;
04019                if(!res)
04020                   res = sayfile(mychannel, "rpt/rxpl");
04021                if(!res)
04022                   sayfile(mychannel, "rpt/off");
04023                break;
04024                
04025             case 101: /* RX PL On */
04026                myrpt->rxplon = 1;
04027                if(!res)
04028                   res = sayfile(mychannel, "rpt/rxpl");
04029                if(!res)
04030                   sayfile(mychannel, "rpt/on");
04031                break;
04032 
04033                
04034             case 102: /* TX PL Off */
04035                myrpt->txplon = 0;
04036                if(!res)
04037                   res = sayfile(mychannel, "rpt/txpl");
04038                if(!res)
04039                   sayfile(mychannel, "rpt/off");
04040                break;
04041                
04042             case 103: /* TX PL On */
04043                myrpt->txplon = 1;
04044                if(!res)
04045                   res = sayfile(mychannel, "rpt/txpl");
04046                if(!res)
04047                   sayfile(mychannel, "rpt/on");
04048                break;
04049                
04050             case 104: /* Low Power */
04051                myrpt->powerlevel = REM_LOWPWR;
04052                if(!res)
04053                   res = sayfile(mychannel, "rpt/lopwr");
04054                break;
04055                
04056             case 105: /* Medium Power */
04057                myrpt->powerlevel = REM_MEDPWR;
04058                if(!res)
04059                   res = sayfile(mychannel, "rpt/medpwr");
04060                break;
04061                
04062             case 106: /* Hi Power */
04063                myrpt->powerlevel = REM_HIPWR;
04064                if(!res)
04065                   res = sayfile(mychannel, "rpt/hipwr");
04066                break;
04067          
04068             default:
04069                if(!res)
04070                   rmt_telem_finish(myrpt, mychannel);
04071                return DC_ERROR;
04072          }
04073          if(!res)
04074             res = rmt_telem_finish(myrpt, mychannel);
04075          if(res)
04076             return DC_ERROR;
04077 
04078          if (setrem(myrpt) == -1) 
04079             return DC_ERROR;
04080          return DC_COMPLETE;
04081 
04082       case 107: /* Bump down 20Hz */
04083          multimode_bump_freq(myrpt, -20);
04084          return DC_COMPLETE;
04085 
04086       case 108: /* Bump down 100Hz */
04087          multimode_bump_freq(myrpt, -100);
04088          return DC_COMPLETE;
04089 
04090       case 109: /* Bump down 500Hz */
04091          multimode_bump_freq(myrpt, -500);
04092          return DC_COMPLETE;
04093 
04094       case 110: /* Bump up 20Hz */
04095          multimode_bump_freq(myrpt, 20);
04096          return DC_COMPLETE;
04097             
04098       case 111: /* Bump up 100Hz */
04099          multimode_bump_freq(myrpt, 100);
04100          return DC_COMPLETE;
04101 
04102       case 112: /* Bump up 500Hz */
04103          multimode_bump_freq(myrpt, 500);
04104          return DC_COMPLETE;
04105 
04106 
04107       case 113:
04108       case 114:
04109       case 115:
04110       case 116:
04111       case 117:
04112       case 118:
04113          myrpt->remotetx = 0;
04114          ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04115          if (!myrpt->remoterx)
04116             ast_indicate(mychannel,AST_CONTROL_RADIO_KEY);
04117          if (ast_safe_sleep(mychannel,1000) == -1)
04118                return DC_ERROR;
04119       
04120          switch(myatoi(param)){
04121 
04122             case 113: /* Scan down slow */
04123                res = sayfile(mychannel,"rpt/down");
04124                if(!res)
04125                   res = sayfile(mychannel, "rpt/slow");
04126                if(!res){
04127                   myrpt->scantimer = REM_SCANTIME;
04128                   myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
04129                }
04130                break;
04131 
04132             case 114: /* Scan down quick */
04133                res = sayfile(mychannel,"rpt/down");
04134                if(!res)
04135                   res = sayfile(mychannel, "rpt/quick");
04136                if(!res){
04137                   myrpt->scantimer = REM_SCANTIME;
04138                   myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
04139                }
04140                break;
04141 
04142             case 115: /* Scan down fast */
04143                res = sayfile(mychannel,"rpt/down");
04144                if(!res)
04145                   res = sayfile(mychannel, "rpt/fast");
04146                if(!res){
04147                   myrpt->scantimer = REM_SCANTIME;
04148                   myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
04149                }
04150                break;
04151 
04152             case 116: /* Scan up slow */
04153                res = sayfile(mychannel,"rpt/up");
04154                if(!res)
04155                   res = sayfile(mychannel, "rpt/slow");
04156                if(!res){
04157                   myrpt->scantimer = REM_SCANTIME;
04158                   myrpt->hfscanmode = HF_SCAN_UP_SLOW;
04159                }
04160                break;
04161 
04162             case 117: /* Scan up quick */
04163                res = sayfile(mychannel,"rpt/up");
04164                if(!res)
04165                   res = sayfile(mychannel, "rpt/quick");
04166                if(!res){
04167                   myrpt->scantimer = REM_SCANTIME;
04168                   myrpt->hfscanmode = HF_SCAN_UP_QUICK;
04169                }
04170                break;
04171 
04172             case 118: /* Scan up fast */
04173                res = sayfile(mychannel,"rpt/up");
04174                if(!res)
04175                   res = sayfile(mychannel, "rpt/fast");
04176                if(!res){
04177                   myrpt->scantimer = REM_SCANTIME;
04178                   myrpt->hfscanmode = HF_SCAN_UP_FAST;
04179                }
04180                break;
04181          }
04182          rmt_telem_finish(myrpt,mychannel);
04183          return DC_COMPLETE;
04184 
04185 
04186       case 119: /* Tune Request */
04187          myrpt->tunerequest = 1;
04188          return DC_COMPLETE;
04189 
04190       case 5: /* Long Status */
04191       case 140: /* Short Status */
04192          res = rmt_telem_start(myrpt, mychannel, 1000);
04193 
04194          res = sayfile(mychannel,"rpt/node");
04195          if(!res)
04196             res = saycharstr(mychannel, myrpt->name);
04197          if(!res)
04198             res = sayfile(mychannel,"rpt/frequency");
04199          if(!res)
04200             res = split_freq(mhz, decimals, myrpt->freq);
04201          if(!res){
04202             m = atoi(mhz);
04203             if(m < 100)
04204                res = saynum(mychannel, m);
04205             else
04206                res = saycharstr(mychannel, mhz);
04207          }
04208          if(!res)
04209             res = sayfile(mychannel, "letters/dot");
04210          if(!res)
04211             res = saycharstr(mychannel, decimals);
04212       
04213          if(res){ 
04214             rmt_telem_finish(myrpt,mychannel);
04215             return DC_ERROR;
04216          }
04217          if(myrpt->remmode == REM_MODE_FM){ /* Mode FM? */
04218             switch(myrpt->offset){
04219    
04220                case REM_MINUS:
04221                   res = sayfile(mychannel,"rpt/minus");
04222                   break;
04223             
04224                case REM_SIMPLEX:
04225                   res = sayfile(mychannel,"rpt/simplex");
04226                   break;
04227                
04228                case REM_PLUS:
04229                   res = sayfile(mychannel,"rpt/plus");
04230                   break;
04231                
04232                default:
04233                   return DC_ERROR;
04234 
04235             }
04236          }
04237          else{ /* Must be USB, LSB, or AM */
04238             switch(myrpt->remmode){
04239 
04240                case REM_MODE_USB:
04241                   res = saycharstr(mychannel, "USB");
04242                   break;
04243 
04244                case REM_MODE_LSB:
04245                   res = saycharstr(mychannel, "LSB");
04246                   break;
04247 
04248                case REM_MODE_AM:
04249                   res = saycharstr(mychannel, "AM");
04250                   break;
04251 
04252 
04253                default:
04254                   return DC_ERROR;
04255             }
04256          }
04257 
04258          if (res == -1){
04259             rmt_telem_finish(myrpt,mychannel);
04260             return DC_ERROR;
04261          }
04262 
04263          if(myatoi(param) == 140){ /* Short status? */
04264             if(!res)
04265                res = rmt_telem_finish(myrpt, mychannel);
04266             if(res)
04267                return DC_ERROR;
04268             return DC_COMPLETE;
04269          }
04270 
04271          switch(myrpt->powerlevel){
04272 
04273             case REM_LOWPWR:
04274                res = sayfile(mychannel,"rpt/lopwr") ;
04275                break;
04276                
04277             case REM_MEDPWR:
04278                res = sayfile(mychannel,"rpt/medpwr");
04279                break;
04280             case REM_HIPWR:
04281                res = sayfile(mychannel,"rpt/hipwr"); 
04282                break;
04283          }
04284          if (res || (sayfile(mychannel,"rpt/rxpl") == -1) ||
04285             (sayfile(mychannel,"rpt/frequency") == -1) ||
04286             (saycharstr(mychannel,myrpt->rxpl) == -1) ||
04287             (sayfile(mychannel,"rpt/txpl") == -1) ||
04288             (sayfile(mychannel,"rpt/frequency") == -1) ||
04289             (saycharstr(mychannel,myrpt->txpl) == -1) ||
04290             (sayfile(mychannel,"rpt/txpl") == -1) ||
04291             (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1) ||
04292             (sayfile(mychannel,"rpt/rxpl") == -1) ||
04293             (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1))
04294             {
04295                rmt_telem_finish(myrpt,mychannel);
04296                return DC_ERROR;
04297             }
04298          if(!res)
04299             res = rmt_telem_finish(myrpt,mychannel);
04300          if(res)
04301             return DC_ERROR;
04302 
04303          return DC_COMPLETE;
04304          default:
04305          return DC_ERROR;
04306    }
04307 
04308    return DC_INDETERMINATE;
04309 }

static int function_status ( struct rpt myrpt,
char *  param,
char *  digitbuf,
int  command_source,
struct rpt_link mylink 
) [static]

Definition at line 2189 of file app_rpt.c.

References DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt::enable, ID1, myatoi(), rpt_telemetry(), STATS_TIME, and STATS_VERSION.

02190 {
02191 
02192    if(!param)
02193       return DC_ERROR;
02194       
02195          
02196    if (!myrpt->enable)
02197       return DC_ERROR;
02198 
02199    if(debug)
02200       printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
02201    
02202    switch(myatoi(param)){
02203       case 1: /* System ID */
02204          rpt_telemetry(myrpt, ID1, NULL);
02205          return DC_COMPLETE;
02206       case 2: /* System Time */
02207          rpt_telemetry(myrpt, STATS_TIME, NULL);
02208          return DC_COMPLETE;
02209       case 3: /* app_rpt.c version */
02210          rpt_telemetry(myrpt, STATS_VERSION, NULL);
02211       default:
02212          return DC_ERROR;
02213    }
02214    return DC_INDETERMINATE;
02215 }

static int get_wait_interval ( struct rpt myrpt,
int  type 
) [static]

Definition at line 898 of file app_rpt.c.

References ast_log(), ast_strdupa, ast_variable_retrieve(), cfg, DLY_CALLTERM, DLY_ID, DLY_TELEM, DLY_UNKEY, LOG_WARNING, rpt::name, and retrieve_astcfgint().

Referenced by rpt_tele_thread(), and wait_interval().

00899 {
00900         int interval;
00901         char *wait_times;
00902         char *wait_times_save;
00903                                                                                                                   
00904         wait_times_save = NULL;
00905         wait_times = ast_variable_retrieve(cfg, myrpt->name, "wait_times");
00906                                                                                                                   
00907         if(wait_times){
00908                 wait_times_save = ast_strdupa(wait_times);
00909                 if(!wait_times_save){
00910                         ast_log(LOG_WARNING, "Out of memory in wait_interval()\n");
00911                         wait_times = NULL;
00912                 }
00913         }
00914                                                                                                                   
00915         switch(type){
00916                 case DLY_TELEM:
00917                         if(wait_times)
00918                                 interval = retrieve_astcfgint(wait_times_save, "telemwait", 500, 5000, 1000);
00919                         else
00920                                 interval = 1000;
00921                         break;
00922                                                                                                                   
00923                 case DLY_ID:
00924                         if(wait_times)
00925                                 interval = retrieve_astcfgint(wait_times_save, "idwait",250,5000,500);
00926                         else
00927                                 interval = 500;
00928                         break;
00929                                                                                                                   
00930                 case DLY_UNKEY:
00931                         if(wait_times)
00932                                 interval = retrieve_astcfgint(wait_times_save, "unkeywait",500,5000,1000);
00933                         else
00934                                 interval = 1000;
00935                         break;
00936                                                                                                                   
00937                 case DLY_CALLTERM:
00938                         if(wait_times)
00939                                 interval = retrieve_astcfgint(wait_times_save, "calltermwait",500,5000,1500);
00940                         else
00941                                 interval = 1500;
00942                         break;
00943                                                                                                                   
00944                 default:
00945                         return 0;
00946         }
00947    return interval;
00948 }                                                                                                                  

static void handle_link_data ( struct rpt myrpt,
struct rpt_link mylink,
char *  str 
) [static]

Definition at line 2335 of file app_rpt.c.

References ast_canmatch_extension(), ast_exists_extension(), AST_FRAME_TEXT, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_write(), rpt::callmode, rpt_link::chan, rpt::cidx, collect_function_digits(), ast_frame::data, ast_frame::datalen, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, rpt_link::disced, rpt::endchar, rpt::exten, ast_frame::frametype, rpt::funcchar, rpt::links, rpt::lock, LOG_WARNING, ast_frame::mallocd, MAX_RETRIES, MAXDTMF, rpt::mydtmf, rpt_link::name, rpt::name, rpt_link::next, ast_frame::offset, rpt::ourcontext, rpt::pchannel, PROC, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, rpt_link::retries, rpt_telemetry(), ast_frame::samples, seq, SOURCE_LNK, rpt::stopgen, strdup, and ast_frame::subclass.

Referenced by rpt().

02337 {
02338 char  tmp[300],cmd[300] = "",dest[300],src[300],c;
02339 int   seq, res;
02340 struct rpt_link *l;
02341 struct   ast_frame wf;
02342 
02343    wf.frametype = AST_FRAME_TEXT;
02344    wf.subclass = 0;
02345    wf.offset = 0;
02346    wf.mallocd = 1;
02347    wf.datalen = strlen(str) + 1;
02348    wf.samples = 0;
02349    /* put string in our buffer */
02350    strncpy(tmp,str,sizeof(tmp) - 1);
02351 
02352         if (!strcmp(tmp,discstr))
02353         {
02354                 mylink->disced = 1;
02355       mylink->retries = MAX_RETRIES + 1;
02356                 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
02357                 return;
02358         }
02359    if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
02360    {
02361       ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
02362       return;
02363    }
02364    if (strcmp(cmd,"D"))
02365    {
02366       ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
02367       return;
02368    }
02369 
02370    if (dest[0] == '0')
02371    {
02372       strcpy(dest,myrpt->name);
02373    }     
02374 
02375    /* if not for me, redistribute to all links */
02376    if (strcmp(dest,myrpt->name))
02377    {
02378       l = myrpt->links.next;
02379       /* see if this is one in list */
02380       while(l != &myrpt->links)
02381       {
02382          if (l->name[0] == '0') 
02383          {
02384             l = l->next;
02385             continue;
02386          }
02387          /* dont send back from where it came */
02388          if ((l == mylink) || (!strcmp(l->name,mylink->name)))
02389          {
02390             l = l->next;
02391             continue;
02392          }
02393          /* if it is, send it and we're done */
02394          if (!strcmp(l->name,dest))
02395          {
02396             /* send, but not to src */
02397             if (strcmp(l->name,src)) {
02398                wf.data = strdup(str);
02399                if (l->chan) ast_write(l->chan,&wf);
02400             }
02401             return;
02402          }
02403          l = l->next;
02404       }
02405       l = myrpt->links.next;
02406       /* otherwise, send it to all of em */
02407       while(l != &myrpt->links)
02408       {
02409          if (l->name[0] == '0') 
02410          {
02411             l = l->next;
02412             continue;
02413          }
02414          /* dont send back from where it came */
02415          if ((l == mylink) || (!strcmp(l->name,mylink->name)))
02416          {
02417             l = l->next;
02418             continue;
02419          }
02420          /* send, but not to src */
02421          if (strcmp(l->name,src)) {
02422             wf.data = strdup(str);
02423             if (l->chan) ast_write(l->chan,&wf);
02424          }
02425          l = l->next;
02426       }
02427       return;
02428    }
02429    ast_mutex_lock(&myrpt->lock);
02430    if (c == myrpt->endchar) myrpt->stopgen = 1;
02431    if (myrpt->callmode == 1)
02432    {
02433       myrpt->exten[myrpt->cidx++] = c;
02434       myrpt->exten[myrpt->cidx] = 0;
02435       /* if this exists */
02436       if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
02437       {
02438          myrpt->callmode = 2;
02439          rpt_telemetry(myrpt,PROC,NULL); 
02440       }
02441       /* if can continue, do so */
02442       if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) 
02443       {
02444          /* call has failed, inform user */
02445          myrpt->callmode = 4;
02446       }
02447    }
02448    if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
02449    {
02450       myrpt->mydtmf = c;
02451    }
02452    if (c == myrpt->funcchar)
02453    {
02454       myrpt->rem_dtmfidx = 0;
02455       myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02456       time(&myrpt->rem_dtmf_time);
02457       ast_mutex_unlock(&myrpt->lock);
02458       return;
02459    } 
02460    else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
02461    {
02462       time(&myrpt->rem_dtmf_time);
02463       if (myrpt->rem_dtmfidx < MAXDTMF)
02464       {
02465          myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
02466          myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02467          
02468          ast_mutex_unlock(&myrpt->lock);
02469          strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
02470          res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
02471          ast_mutex_lock(&myrpt->lock);
02472          
02473          switch(res){
02474 
02475             case DC_INDETERMINATE:
02476                break;
02477             
02478             case DC_REQ_FLUSH:
02479                myrpt->rem_dtmfidx = 0;
02480                myrpt->rem_dtmfbuf[0] = 0;
02481                break;
02482             
02483             
02484             case DC_COMPLETE:
02485                myrpt->rem_dtmfbuf[0] = 0;
02486                myrpt->rem_dtmfidx = -1;
02487                myrpt->rem_dtmf_time = 0;
02488                break;
02489             
02490             case DC_ERROR:
02491             default:
02492                myrpt->rem_dtmfbuf[0] = 0;
02493                myrpt->rem_dtmfidx = -1;
02494                myrpt->rem_dtmf_time = 0;
02495                break;
02496          }
02497       }
02498 
02499    }
02500    ast_mutex_unlock(&myrpt->lock);
02501    return;
02502 }

static void handle_link_phone_dtmf ( struct rpt myrpt,
struct rpt_link mylink,
char  c 
) [static]

Definition at line 2504 of file app_rpt.c.

References ast_canmatch_extension(), ast_exists_extension(), ast_mutex_lock(), ast_mutex_unlock(), rpt::callmode, rpt::cidx, rpt::cmdnode, collect_function_digits(), COMPLETE, DC_COMPLETE, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, rpt::dtmfbuf, rpt::dtmfidx, rpt::endchar, rpt::exten, rpt::funcchar, rpt_link::lastrx, rpt::lock, MAXDTMF, rpt::mydtmf, rpt::ourcontext, rpt::pchannel, rpt_link::phonemode, PROC, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, rpt_telemetry(), send_link_dtmf(), SOURCE_DPHONE, SOURCE_PHONE, and rpt::stopgen.

Referenced by rpt().

02506 {
02507 
02508 char  cmd[300];
02509 int   res;
02510 
02511    ast_mutex_lock(&myrpt->lock);
02512    if (c == myrpt->endchar)
02513    {
02514       if (mylink->lastrx)
02515       {
02516          mylink->lastrx = 0;
02517          ast_mutex_unlock(&myrpt->lock);
02518          return;
02519       }
02520       myrpt->stopgen = 1;
02521       if (myrpt->cmdnode[0])
02522       {
02523          myrpt->cmdnode[0] = 0;
02524          myrpt->dtmfidx = -1;
02525          myrpt->dtmfbuf[0] = 0;
02526          ast_mutex_unlock(&myrpt->lock);
02527          rpt_telemetry(myrpt,COMPLETE,NULL);
02528          ast_mutex_unlock(&myrpt->lock);
02529          return;
02530       }
02531    }
02532    if (myrpt->cmdnode[0])
02533    {
02534       ast_mutex_unlock(&myrpt->lock);
02535       send_link_dtmf(myrpt,c);
02536       return;
02537    }
02538    if (myrpt->callmode == 1)
02539    {
02540       myrpt->exten[myrpt->cidx++] = c;
02541       myrpt->exten[myrpt->cidx] = 0;
02542       /* if this exists */
02543       if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
02544       {
02545          myrpt->callmode = 2;
02546          rpt_telemetry(myrpt,PROC,NULL); 
02547       }
02548       /* if can continue, do so */
02549       if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) 
02550       {
02551          /* call has failed, inform user */
02552          myrpt->callmode = 4;
02553       }
02554    }
02555    if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
02556    {
02557       myrpt->mydtmf = c;
02558    }
02559    if (c == myrpt->funcchar)
02560    {
02561       myrpt->rem_dtmfidx = 0;
02562       myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02563       time(&myrpt->rem_dtmf_time);
02564       ast_mutex_unlock(&myrpt->lock);
02565       return;
02566    } 
02567    else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
02568    {
02569       time(&myrpt->rem_dtmf_time);
02570       if (myrpt->rem_dtmfidx < MAXDTMF)
02571       {
02572          myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
02573          myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02574          
02575          ast_mutex_unlock(&myrpt->lock);
02576          strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
02577          res = collect_function_digits(myrpt, cmd, 
02578             ((mylink->phonemode == 2) ? SOURCE_DPHONE : SOURCE_PHONE), mylink);
02579          ast_mutex_lock(&myrpt->lock);
02580          
02581          switch(res){
02582 
02583             case DC_INDETERMINATE:
02584                break;
02585             
02586             case DC_DOKEY:
02587                mylink->lastrx = 1;
02588                break;
02589             
02590             case DC_REQ_FLUSH:
02591                myrpt->rem_dtmfidx = 0;
02592                myrpt->rem_dtmfbuf[0] = 0;
02593                break;
02594             
02595             
02596             case DC_COMPLETE:
02597                myrpt->rem_dtmfbuf[0] = 0;
02598                myrpt->rem_dtmfidx = -1;
02599                myrpt->rem_dtmf_time = 0;
02600                break;
02601             
02602             case DC_ERROR:
02603             default:
02604                myrpt->rem_dtmfbuf[0] = 0;
02605                myrpt->rem_dtmfidx = -1;
02606                myrpt->rem_dtmf_time = 0;
02607                break;
02608          }
02609       }
02610 
02611    }
02612    ast_mutex_unlock(&myrpt->lock);
02613    return;
02614 }

static int handle_remote_data ( struct rpt myrpt,
char *  str 
) [static]

Definition at line 4406 of file app_rpt.c.

References AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_log(), ast_safe_sleep(), handle_remote_dtmf_digit(), LOG_WARNING, rpt::name, rpt::remchannel, rpt::remoterx, rpt::remotetx, rmt_telem_finish(), seq, telem_lookup(), and rpt::txchannel.

04407 {
04408 char  tmp[300],cmd[300],dest[300],src[300],c;
04409 int   seq,res;
04410 
04411    /* put string in our buffer */
04412    strncpy(tmp,str,sizeof(tmp) - 1);
04413    if (!strcmp(tmp,discstr)) return 0;
04414    if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
04415    {
04416       ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
04417       return 0;
04418    }
04419    if (strcmp(cmd,"D"))
04420    {
04421       ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
04422       return 0;
04423    }
04424    /* if not for me, ignore */
04425    if (strcmp(dest,myrpt->name)) return 0;
04426    res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
04427    if (res != 1)
04428       return res;
04429    myrpt->remotetx = 0;
04430    ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04431    if (!myrpt->remoterx)
04432    {
04433       ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
04434    }
04435    if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1;
04436    res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete");
04437    rmt_telem_finish(myrpt,myrpt->remchannel);
04438    return res;
04439 }

static int handle_remote_dtmf_digit ( struct rpt myrpt,
char  c,
char *  keyed,
int  phonemode 
) [static]

Definition at line 4311 of file app_rpt.c.

References collect_function_digits(), DC_COMPLETE, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, rpt::dtmf_time_rem, DTMF_TIMEOUT, rpt::dtmfbuf, rpt::dtmfidx, rpt::funcchar, rpt::hfscanmode, MAXDTMF, SOURCE_DPHONE, SOURCE_PHONE, SOURCE_RMT, and stop_scan().

Referenced by handle_remote_data(), and handle_remote_phone_dtmf().

04312 {
04313 time_t   now;
04314 int   ret,res = 0,src;
04315 
04316    /* Stop scan mode if in scan mode */
04317    if(myrpt->hfscanmode){
04318       stop_scan(myrpt,0);
04319       return 0;
04320    }
04321 
04322    time(&now);
04323    /* if timed-out */
04324    if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
04325    {
04326       myrpt->dtmfidx = -1;
04327       myrpt->dtmfbuf[0] = 0;
04328       myrpt->dtmf_time_rem = 0;
04329    }
04330    /* if decode not active */
04331    if (myrpt->dtmfidx == -1)
04332    {
04333       /* if not lead-in digit, dont worry */
04334       if (c != myrpt->funcchar) return 0;
04335       myrpt->dtmfidx = 0;
04336       myrpt->dtmfbuf[0] = 0;
04337       myrpt->dtmf_time_rem = now;
04338       return 0;
04339    }
04340    /* if too many in buffer, start over */
04341    if (myrpt->dtmfidx >= MAXDTMF)
04342    {
04343       myrpt->dtmfidx = 0;
04344       myrpt->dtmfbuf[0] = 0;
04345       myrpt->dtmf_time_rem = now;
04346    }
04347    if (c == myrpt->funcchar)
04348    {
04349       /* if star at beginning, or 2 together, erase buffer */
04350       if ((myrpt->dtmfidx < 1) || 
04351          (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->funcchar))
04352       {
04353          myrpt->dtmfidx = 0;
04354          myrpt->dtmfbuf[0] = 0;
04355          myrpt->dtmf_time_rem = now;
04356          return 0;
04357       }
04358    }
04359    myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
04360    myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
04361    myrpt->dtmf_time_rem = now;
04362    
04363    
04364    src = SOURCE_RMT;
04365    if (phonemode > 1) src = SOURCE_DPHONE;
04366    else if (phonemode) src = SOURCE_PHONE;
04367    ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
04368    
04369    switch(ret){
04370    
04371       case DC_INDETERMINATE:
04372          res = 0;
04373          break;
04374             
04375       case DC_DOKEY:
04376          if (keyed) *keyed = 1;
04377          res = 0;
04378          break;
04379             
04380       case DC_REQ_FLUSH:
04381          myrpt->dtmfidx = 0;
04382          myrpt->dtmfbuf[0] = 0;
04383          res = 0;
04384          break;
04385             
04386             
04387       case DC_COMPLETE:
04388          myrpt->dtmfbuf[0] = 0;
04389          myrpt->dtmfidx = -1;
04390          myrpt->dtmf_time_rem = 0;
04391          res = 1;
04392          break;
04393             
04394       case DC_ERROR:
04395       default:
04396          myrpt->dtmfbuf[0] = 0;
04397          myrpt->dtmfidx = -1;
04398          myrpt->dtmf_time_rem = 0;
04399          res = 0;
04400          break;
04401    }
04402 
04403    return res;
04404 }

static int handle_remote_phone_dtmf ( struct rpt myrpt,
char  c,
char *  keyed,
int  phonemode 
) [static]

Definition at line 4441 of file app_rpt.c.

References AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_safe_sleep(), DC_INDETERMINATE, rpt::endchar, handle_remote_dtmf_digit(), rpt::name, rpt::remchannel, rpt::remoterx, rpt::remotetx, rmt_telem_finish(), telem_lookup(), and rpt::txchannel.

04442 {
04443 int   res;
04444 
04445 
04446    if (keyed && *keyed && (c == myrpt->endchar))
04447    {
04448       *keyed = 0;
04449       return DC_INDETERMINATE;
04450    }
04451 
04452    res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
04453    if (res != 1)
04454       return res;
04455    myrpt->remotetx = 0;
04456    ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04457    if (!myrpt->remoterx)
04458    {
04459       ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
04460    }
04461    if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1;
04462    res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete");
04463    rmt_telem_finish(myrpt,myrpt->remchannel);
04464    return res;
04465 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 6556 of file app_rpt.c.

References ASTERISK_GPL_KEY.

06557 {
06558    return ASTERISK_GPL_KEY;
06559 }

int load_module ( void   ) 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 6534 of file app_rpt.c.

References ast_cli_register(), ast_pthread_create, ast_register_application(), cli_debug, rpt_exec(), and rpt_master().

06535 {
06536    ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
06537 
06538    /* Register cli extensions */
06539    ast_cli_register(&cli_debug);
06540 
06541    return ast_register_application(app, rpt_exec, synopsis, descrip);
06542 }

static int multimode_bump_freq ( struct rpt myrpt,
int  interval 
) [static]

Definition at line 3461 of file app_rpt.c.

References multimode_bump_freq_ft897(), and rpt::remote.

Referenced by function_remote(), and service_scan().

03462 {
03463    if(!strcmp(myrpt->remote, remote_rig_ft897))
03464       return multimode_bump_freq_ft897(myrpt, interval);
03465    else
03466       return -1;
03467 }

static int multimode_bump_freq_ft897 ( struct rpt myrpt,
int  interval 
) [static]

Definition at line 3370 of file app_rpt.c.

References check_freq_ft897(), rpt::freq, MAXREMSTR, set_freq_ft897(), and split_freq().

Referenced by multimode_bump_freq().

03371 {
03372    int m,d;
03373    char mhz[MAXREMSTR], decimals[MAXREMSTR];
03374 
03375    if(debug)
03376       printf("Before bump: %s\n", myrpt->freq);
03377 
03378    if(split_freq(mhz, decimals, myrpt->freq))
03379       return -1;
03380    
03381    m = atoi(mhz);
03382    d = atoi(decimals);
03383 
03384    d += (interval / 10); /* 10Hz resolution */
03385    if(d < 0){
03386       m--;
03387       d += 100000;
03388    }
03389    else if(d >= 100000){
03390       m++;
03391       d -= 100000;
03392    }
03393 
03394    if(check_freq_ft897(m, d, NULL)){
03395       if(debug)
03396          printf("Bump freq invalid\n");
03397       return -1;
03398    }
03399 
03400    snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
03401 
03402    if(debug)
03403       printf("After bump: %s\n", myrpt->freq);
03404 
03405    return set_freq_ft897(myrpt, myrpt->freq);   
03406 }

static int multimode_capable ( struct rpt myrpt  )  [static]

Definition at line 3450 of file app_rpt.c.

References rpt::remote.

Referenced by function_remote().

03451 {
03452    if(!strcmp(myrpt->remote, remote_rig_ft897))
03453       return 1;
03454    return 0;
03455 }  

static int myatoi ( char *  str  )  [static]

Definition at line 462 of file app_rpt.c.

Referenced by function_cop(), function_ilink(), function_remote(), function_status(), retrieve_astcfgint(), and rpt_do_debug().

00463 {
00464 int   ret;
00465 
00466    if (str == NULL) return -1;
00467    /* leave this %i alone, non-base-10 input is useful here */
00468    if (sscanf(str,"%i",&ret) != 1) return -1;
00469    return ret;
00470 }

static int play_silence ( struct ast_channel chan,
int  duration 
) [static]

Definition at line 515 of file app_rpt.c.

References play_tone_pair().

Referenced by send_morse().

00516 {
00517    return play_tone_pair(chan, 0, 0, duration, 0);
00518 }

static int play_tone ( struct ast_channel chan,
int  freq,
int  duration,
int  amplitude 
) [static]

Definition at line 510 of file app_rpt.c.

References play_tone_pair().

Referenced by send_morse().

00511 {
00512    return play_tone_pair(chan, freq, 0, duration, amplitude);
00513 }

static int play_tone_pair ( struct ast_channel chan,
int  f1,
int  f2,
int  duration,
int  amplitude 
) [static]

Definition at line 496 of file app_rpt.c.

References ast_safe_sleep(), ast_tonepair_start(), and ast_channel::generatordata.

Referenced by play_silence(), play_tone(), and send_tone_telemetry().

00497 {
00498    int res;
00499 
00500         if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
00501                 return res;
00502                                                                                                                                             
00503         while(chan->generatordata) {
00504       if (ast_safe_sleep(chan,1)) return -1;
00505    }
00506 
00507         return 0;
00508 }

static int rbi_mhztoband ( char *  str  )  [static]

Definition at line 2647 of file app_rpt.c.

Referenced by setrbi().

02648 {
02649 int   i;
02650 
02651    i = atoi(str) / 10; /* get the 10's of mhz */
02652    switch(i)
02653    {
02654        case 2:
02655       return 10;
02656        case 5:
02657       return 11;
02658        case 14:
02659       return 2;
02660        case 22:
02661       return 3;
02662        case 44:
02663       return 4;
02664        case 124:
02665       return 0;
02666        case 125:
02667       return 1;
02668        case 126:
02669       return 8;
02670        case 127:
02671       return 5;
02672        case 128:
02673       return 6;
02674        case 129:
02675       return 7;
02676        default:
02677       break;
02678    }
02679    return -1;
02680 }

static void rbi_out ( struct rpt myrpt,
unsigned char *  data 
) [static]

Definition at line 2804 of file app_rpt.c.

References ast_log(), ast_channel::fds, LOG_WARNING, ast_channel::name, rbi_out_parallel(), and rpt::rxchannel.

Referenced by setrbi().

02805 {
02806 struct zt_radio_param r;
02807 
02808    memset(&r,0,sizeof(struct zt_radio_param));
02809    r.radpar = ZT_RADPAR_REMMODE;
02810    r.data = ZT_RADPAR_REM_RBI1;
02811    /* if setparam ioctl fails, its probably not a pciradio card */
02812    if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
02813    {
02814       rbi_out_parallel(myrpt,data);
02815       return;
02816    }
02817    r.radpar = ZT_RADPAR_REMCOMMAND;
02818    memcpy(&r.data,data,5);
02819    if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
02820    {
02821       ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->rxchannel->name);
02822       return;
02823    }
02824 }

static void rbi_out_parallel ( struct rpt myrpt,
unsigned char *  data 
) [static]

Definition at line 2778 of file app_rpt.c.

References rpt::iobase.

Referenced by rbi_out().

02779     {
02780     int i,j;
02781     unsigned char od,d;
02782     static volatile long long delayvar;
02783 
02784     for(i = 0 ; i < 5 ; i++){
02785         od = *data++; 
02786         for(j = 0 ; j < 8 ; j++){
02787             d = od & 1;
02788             outb(d,myrpt->iobase);
02789        /* >= 15 us */
02790        for(delayvar = 1; delayvar < 15000; delayvar++); 
02791             od >>= 1;
02792             outb(d | 2,myrpt->iobase);
02793        /* >= 30 us */
02794        for(delayvar = 1; delayvar < 30000; delayvar++); 
02795             outb(d,myrpt->iobase);
02796        /* >= 10 us */
02797        for(delayvar = 1; delayvar < 10000; delayvar++); 
02798             }
02799         }
02800    /* >= 50 us */
02801         for(delayvar = 1; delayvar < 50000; delayvar++); 
02802     }

static int rbi_pltocode ( char *  str  )  [static]

Definition at line 2683 of file app_rpt.c.

References s.

Referenced by setrbi().

02684 {
02685 int i;
02686 char *s;
02687 
02688    s = strchr(str,'.');
02689    i = 0;
02690    if (s) i = atoi(s + 1);
02691    i += atoi(str) * 10;
02692    switch(i)
02693    {
02694        case 670:
02695       return 0;
02696        case 719:
02697       return 1;
02698        case 744:
02699       return 2;
02700        case 770:
02701       return 3;
02702        case 797:
02703       return 4;
02704        case 825:
02705       return 5;
02706        case 854:
02707       return 6;
02708        case 885:
02709       return 7;
02710        case 915:
02711       return 8;
02712        case 948:
02713       return 9;
02714        case 974:
02715       return 10;
02716        case 1000:
02717       return 11;
02718        case 1035:
02719       return 12;
02720        case 1072:
02721       return 13;
02722        case 1109:
02723       return 14;
02724        case 1148:
02725       return 15;
02726        case 1188:
02727       return 16;
02728        case 1230:
02729       return 17;
02730        case 1273:
02731       return 18;
02732        case 1318:
02733       return 19;
02734        case 1365:
02735       return 20;
02736        case 1413:
02737       return 21;
02738        case 1462:
02739       return 22;
02740        case 1514:
02741       return 23;
02742        case 1567:
02743       return 24;
02744        case 1622:
02745       return 25;
02746        case 1679:
02747       return 26;
02748        case 1738:
02749       return 27;
02750        case 1799:
02751       return 28;
02752        case 1862:
02753       return 29;
02754        case 1928:
02755       return 30;
02756        case 2035:
02757       return 31;
02758        case 2107:
02759       return 32;
02760        case 2181:
02761       return 33;
02762        case 2257:
02763       return 34;
02764        case 2336:
02765       return 35;
02766        case 2418:
02767       return 36;
02768        case 2503:
02769       return 37;
02770    }
02771    return -1;
02772 }

static int retrieve_astcfgint ( char *  category,
char *  name,
int  min,
int  max,
int  defl 
) [static]

Definition at line 776 of file app_rpt.c.

References ast_variable_retrieve(), cfg, myatoi(), and var.

Referenced by get_wait_interval(), rpt_master(), and telem_any().

00777 {
00778         char *var;
00779         int ret;
00780                                                                                 
00781         var = ast_variable_retrieve(cfg, category, name);
00782         if(var){
00783                 ret = myatoi(var);
00784                 if(ret < min)
00785                         ret = min;
00786                 if(ret > max)
00787                         ret = max;
00788         }
00789         else
00790                 ret = defl;
00791         return ret;
00792 }

static int rmt_saycharstr ( struct rpt myrpt,
struct ast_channel chan,
int  delay,
char *  charstr 
) [static]

Definition at line 3598 of file app_rpt.c.

References rmt_telem_finish(), rmt_telem_start(), and saycharstr().

Referenced by function_remote().

03599 {
03600    int res;
03601 
03602    res = rmt_telem_start(myrpt, chan, delay);
03603 
03604    if(!res)
03605       res = saycharstr(chan, charstr);
03606    
03607    if(!res)
03608       res = rmt_telem_finish(myrpt, chan);
03609    return res;
03610 }

static int rmt_sayfile ( struct rpt myrpt,
struct ast_channel chan,
int  delay,
char *  filename 
) [static]

Definition at line 3584 of file app_rpt.c.

References rmt_telem_finish(), rmt_telem_start(), and sayfile().

Referenced by function_remote().

03585 {
03586    int res;
03587 
03588    res = rmt_telem_start(myrpt, chan, delay);
03589 
03590    if(!res)
03591       res = sayfile(chan, filename);
03592    
03593    if(!res)
03594       res = rmt_telem_finish(myrpt, chan);
03595    return res;
03596 }

static int rmt_telem_finish ( struct rpt myrpt,
struct ast_channel chan 
) [static]

Definition at line 3561 of file app_rpt.c.

References AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_channel::fds, rpt::remchannel, rpt::remoterx, and rpt::txchannel.

Referenced by function_remote(), handle_remote_data(), handle_remote_phone_dtmf(), rmt_saycharstr(), and rmt_sayfile().

03562 {
03563 
03564 struct zt_params par;
03565 
03566    if (ioctl(myrpt->txchannel->fds[0],ZT_GET_PARAMS,&par) == -1)
03567    {
03568       return -1;
03569 
03570    }
03571    if (!par.rxisoffhook)
03572    {
03573       ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_UNKEY);
03574       myrpt->remoterx = 0;
03575    }
03576    else
03577    {
03578       myrpt->remoterx = 1;
03579    }
03580    return 0;
03581 }

static int rmt_telem_start ( struct rpt myrpt,
struct ast_channel chan,
int  delay 
) [static]

Definition at line 3549 of file app_rpt.c.

References AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_safe_sleep(), rpt::remoterx, rpt::remotetx, and rpt::txchannel.

Referenced by function_remote(), rmt_saycharstr(), and rmt_sayfile().

03550 {
03551          myrpt->remotetx = 0;
03552          ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
03553          if (!myrpt->remoterx)
03554             ast_indicate(chan,AST_CONTROL_RADIO_KEY);
03555          if (ast_safe_sleep(chan, delay) == -1)
03556                return -1;
03557          return 0;
03558 }

static void* rpt ( void *  this  )  [static]

Definition at line 4527 of file app_rpt.c.

References ast_channel::_state, ast_channel::appl, ast_call(), ast_canmatch_extension(), ast_channel_setoption(), ast_check_hangup(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_exists_extension(), AST_FORMAT_SLINEAR, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frfree(), ast_hangup(), ast_indicate(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_RELAXDTMF, AST_OPTION_TONE_VERIFY, ast_pthread_create, AST_PTHREADT_STOP, ast_read(), ast_request(), ast_set_read_format(), ast_set_write_format(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_STATE_BUSY, AST_STATE_UP, ast_variable_retrieve(), ast_verbose(), ast_waitfor_n(), ast_write(), attempt_reconnect(), rpt::callmode, cfg, rpt_link::chan, rpt_tele::chan, rpt::cidx, rpt::cmdnode, collect_function_digits(), COMPLETE, rpt::conf, CONNECTED, rpt_link::connected, CONNFAIL, ast_frame::data, ast_channel::data, ast_frame::datalen, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, DISC_TIME, rpt_link::disced, rpt_link::disctime, rpt::disgorgetime, DTMF_TIMEOUT, rpt::dtmfbuf, rpt::dtmfidx, rpt_link::elaptime, rpt::enable, rpt::endchar, rpt::exten, rpt::exttx, ast_channel::fds, ast_frame::frametype, free, rpt::funcchar, handle_link_data(), handle_link_phone_dtmf(), rpt::hangtime, rpt_link::hasconnected, ID, IDTALKOVER, rpt::idtime, rpt::idtimer, rpt_link::isremote, rpt::keyed, rpt_link::killme, rpt_link::lastrx, rpt_link::lasttx, rpt::links, rpt::localtx, rpt::lock, LOG_NOTICE, LOG_WARNING, MAX_RETRIES, MAXCONNECTTIME, MAXDTMF, rpt_link::mode, rpt_tele::mode, MSWAIT, rpt::mustid, rpt::mydtmf, n, rpt_link::name, rpt::name, ast_channel::name, rpt_tele::next, rpt_link::next, option_verbose, rpt::ourcontext, rpt_link::outbound, rpt_link::pchan, rpt::pchannel, rpt_link::phonemode, rpt::politeid, rpt_link::prev, PROC, REDUNDANT_TX_TIME, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, REMDISC, rpt_link::retries, RETRY_TIMER_MS, rpt_link::retrytimer, rpt_link::retxtimer, rpt::retxtimer, rpt_call(), rpt::rpt_call_thread, rpt_telemetry(), rpt::rpt_thread, rpt::rxchanname, rpt::rxchannel, send_link_dtmf(), rpt::simple, SOURCE_RPT, rpt::stopgen, ast_frame::subclass, t, rpt::tailtimer, rpt::tele, TERM, TIMEOUT, rpt::tonotify, rpt::totime, rpt::totimer, rpt::tounkeyed, rpt::txchanname, rpt::txchannel, rpt::txconf, rpt::txpchannel, UNKEY, VERBOSE_PREFIX_3, and ast_channel::whentohangup.

04528 {
04529 struct   rpt *myrpt = (struct rpt *)this;
04530 char *tele,*idtalkover;
04531 int ms = MSWAIT,lasttx=0,val,remrx=0,identqueued,nonidentqueued,res;
04532 struct ast_channel *who;
04533 ZT_CONFINFO ci;  /* conference info */
04534 time_t   dtmf_time,t;
04535 struct rpt_link *l,*m;
04536 struct rpt_tele *telem;
04537 pthread_attr_t attr;
04538 char tmpstr[300];
04539 char cmd[MAXDTMF+1] = "";
04540 
04541 
04542    ast_mutex_lock(&myrpt->lock);
04543    strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
04544    tele = strchr(tmpstr,'/');
04545    if (!tele)
04546    {
04547       fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
04548       ast_mutex_unlock(&myrpt->lock);
04549       myrpt->rpt_thread = AST_PTHREADT_STOP;
04550       pthread_exit(NULL);
04551    }
04552    *tele++ = 0;
04553    myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
04554    if (myrpt->rxchannel)
04555    {
04556       if (myrpt->rxchannel->_state == AST_STATE_BUSY)
04557       {
04558          fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
04559          ast_mutex_unlock(&myrpt->lock);
04560          ast_hangup(myrpt->rxchannel);
04561          myrpt->rpt_thread = AST_PTHREADT_STOP;
04562          pthread_exit(NULL);
04563       }
04564       ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
04565       ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
04566       myrpt->rxchannel->whentohangup = 0;
04567       myrpt->rxchannel->appl = "Apprpt";
04568       myrpt->rxchannel->data = "(Repeater Rx)";
04569       if (option_verbose > 2)
04570          ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
04571             tmpstr,tele,myrpt->rxchannel->name);
04572       ast_call(myrpt->rxchannel,tele,999);
04573       if (myrpt->rxchannel->_state != AST_STATE_UP)
04574       {
04575          ast_mutex_unlock(&myrpt->lock);
04576          ast_hangup(myrpt->rxchannel);
04577          myrpt->rpt_thread = AST_PTHREADT_STOP;
04578          pthread_exit(NULL);
04579       }
04580    }
04581    else
04582    {
04583       fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
04584       ast_mutex_unlock(&myrpt->lock);
04585       myrpt->rpt_thread = AST_PTHREADT_STOP;
04586       pthread_exit(NULL);
04587    }
04588    if (myrpt->txchanname)
04589    {
04590       strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
04591       tele = strchr(tmpstr,'/');
04592       if (!tele)
04593       {
04594          fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
04595          ast_mutex_unlock(&myrpt->lock);
04596          ast_hangup(myrpt->rxchannel);
04597          myrpt->rpt_thread = AST_PTHREADT_STOP;
04598          pthread_exit(NULL);
04599       }
04600       *tele++ = 0;
04601       myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
04602       if (myrpt->txchannel)
04603       {
04604          if (myrpt->txchannel->_state == AST_STATE_BUSY)
04605          {
04606             fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
04607             ast_mutex_unlock(&myrpt->lock);
04608             ast_hangup(myrpt->txchannel);
04609             ast_hangup(myrpt->rxchannel);
04610             myrpt->rpt_thread = AST_PTHREADT_STOP;
04611             pthread_exit(NULL);
04612          }        
04613          ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
04614          ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
04615          myrpt->txchannel->whentohangup = 0;
04616          myrpt->txchannel->appl = "Apprpt";
04617          myrpt->txchannel->data = "(Repeater Tx)";
04618          if (option_verbose > 2)
04619             ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
04620                tmpstr,tele,myrpt->txchannel->name);
04621          ast_call(myrpt->txchannel,tele,999);
04622          if (myrpt->rxchannel->_state != AST_STATE_UP)
04623          {
04624             ast_mutex_unlock(&myrpt->lock);
04625             ast_hangup(myrpt->rxchannel);
04626             ast_hangup(myrpt->txchannel);
04627             myrpt->rpt_thread = AST_PTHREADT_STOP;
04628             pthread_exit(NULL);
04629          }
04630       }
04631       else
04632       {
04633          fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
04634          ast_mutex_unlock(&myrpt->lock);
04635          ast_hangup(myrpt->rxchannel);
04636          myrpt->rpt_thread = AST_PTHREADT_STOP;
04637          pthread_exit(NULL);
04638       }
04639    }
04640    else
04641    {
04642       myrpt->txchannel = myrpt->rxchannel;
04643    }
04644    ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
04645    ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04646    /* allocate a pseudo-channel thru asterisk */
04647    myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04648    if (!myrpt->pchannel)
04649    {
04650       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04651       ast_mutex_unlock(&myrpt->lock);
04652       if (myrpt->txchannel != myrpt->rxchannel) 
04653          ast_hangup(myrpt->txchannel);
04654       ast_hangup(myrpt->rxchannel);
04655       myrpt->rpt_thread = AST_PTHREADT_STOP;
04656       pthread_exit(NULL);
04657    }
04658    /* make a conference for the tx */
04659    ci.chan = 0;
04660    ci.confno = -1; /* make a new conf */
04661    ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
04662    /* first put the channel on the conference in proper mode */
04663    if (ioctl(myrpt->txchannel->fds[0],ZT_SETCONF,&ci) == -1)
04664    {
04665       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04666       ast_mutex_unlock(&myrpt->lock);
04667       ast_hangup(myrpt->pchannel);
04668       if (myrpt->txchannel != myrpt->rxchannel) 
04669          ast_hangup(myrpt->txchannel);
04670       ast_hangup(myrpt->rxchannel);
04671       myrpt->rpt_thread = AST_PTHREADT_STOP;
04672       pthread_exit(NULL);
04673    }
04674    /* save tx conference number */
04675    myrpt->txconf = ci.confno;
04676    /* make a conference for the pseudo */
04677    ci.chan = 0;
04678    ci.confno = -1; /* make a new conf */
04679    ci.confmode = ZT_CONF_CONFANNMON; 
04680    /* first put the channel on the conference in announce mode */
04681    if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
04682    {
04683       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04684       ast_mutex_unlock(&myrpt->lock);
04685       ast_hangup(myrpt->pchannel);
04686       if (myrpt->txchannel != myrpt->rxchannel) 
04687          ast_hangup(myrpt->txchannel);
04688       ast_hangup(myrpt->rxchannel);
04689       myrpt->rpt_thread = AST_PTHREADT_STOP;
04690       pthread_exit(NULL);
04691    }
04692    /* save pseudo channel conference number */
04693    myrpt->conf = ci.confno;
04694    /* allocate a pseudo-channel thru asterisk */
04695    myrpt->txpchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04696    if (!myrpt->txpchannel)
04697    {
04698       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04699       ast_mutex_unlock(&myrpt->lock);
04700       ast_hangup(myrpt->pchannel);
04701       if (myrpt->txchannel != myrpt->rxchannel) 
04702          ast_hangup(myrpt->txchannel);
04703       ast_hangup(myrpt->rxchannel);
04704       myrpt->rpt_thread = AST_PTHREADT_STOP;
04705       pthread_exit(NULL);
04706    }
04707    /* make a conference for the tx */
04708    ci.chan = 0;
04709    ci.confno = myrpt->txconf;
04710    ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER ;
04711    /* first put the channel on the conference in proper mode */
04712    if (ioctl(myrpt->txpchannel->fds[0],ZT_SETCONF,&ci) == -1)
04713    {
04714       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04715       ast_mutex_unlock(&myrpt->lock);
04716       ast_hangup(myrpt->txpchannel);
04717       ast_hangup(myrpt->pchannel);
04718       if (myrpt->txchannel != myrpt->rxchannel) 
04719          ast_hangup(myrpt->txchannel);
04720       ast_hangup(myrpt->rxchannel);
04721       myrpt->rpt_thread = AST_PTHREADT_STOP;
04722       pthread_exit(NULL);
04723    }
04724    /* Now, the idea here is to copy from the physical rx channel buffer
04725       into the pseudo tx buffer, and from the pseudo rx buffer into the 
04726       tx channel buffer */
04727    myrpt->links.next = &myrpt->links;
04728    myrpt->links.prev = &myrpt->links;
04729    myrpt->tailtimer = 0;
04730    myrpt->totimer = 0;
04731    myrpt->idtimer = myrpt->politeid;
04732    myrpt->mustid = 0;
04733    myrpt->callmode = 0;
04734    myrpt->tounkeyed = 0;
04735    myrpt->tonotify = 0;
04736    myrpt->retxtimer = 0;
04737    lasttx = 0;
04738    myrpt->keyed = 0;
04739    idtalkover = ast_variable_retrieve(cfg, myrpt->name, "idtalkover");
04740    myrpt->dtmfidx = -1;
04741    myrpt->dtmfbuf[0] = 0;
04742    myrpt->rem_dtmfidx = -1;
04743    myrpt->rem_dtmfbuf[0] = 0;
04744    dtmf_time = 0;
04745    myrpt->rem_dtmf_time = 0;
04746    myrpt->enable = 1;
04747    myrpt->disgorgetime = 0;
04748    ast_mutex_unlock(&myrpt->lock);
04749    val = 0;
04750    ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
04751    val = 1;
04752    ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
04753    while (ms >= 0)
04754    {
04755       struct ast_frame *f;
04756       struct ast_channel *cs[300];
04757       int totx=0,elap=0,n,toexit=0;
04758 
04759       /* DEBUG Dump */
04760       if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
04761          struct rpt_link *zl;
04762          struct rpt_tele *zt;
04763 
04764          myrpt->disgorgetime = 0;
04765          ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
04766          ast_log(LOG_NOTICE,"totx = %d\n",totx);
04767          ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
04768          ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
04769          ast_log(LOG_NOTICE,"elap = %d\n",elap);
04770          ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
04771 
04772          ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
04773          ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
04774          ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
04775          ast_log(LOG_NOTICE,"myrpt->enable = %d\n",myrpt->enable);
04776          ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
04777          ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
04778          ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
04779          ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
04780          ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
04781          ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
04782 
04783          zl = myrpt->links.next;
04784                   while(zl != &myrpt->links){
04785             ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",zl->name);
04786             ast_log(LOG_NOTICE,"        link->lasttx %d\n",zl->lasttx);
04787             ast_log(LOG_NOTICE,"        link->lastrx %d\n",zl->lastrx);
04788             ast_log(LOG_NOTICE,"        link->connected %d\n",zl->connected);
04789             ast_log(LOG_NOTICE,"        link->hasconnected %d\n",zl->hasconnected);
04790             ast_log(LOG_NOTICE,"        link->outbound %d\n",zl->outbound);
04791             ast_log(LOG_NOTICE,"        link->disced %d\n",zl->disced);
04792             ast_log(LOG_NOTICE,"        link->killme %d\n",zl->killme);
04793             ast_log(LOG_NOTICE,"        link->disctime %ld\n",zl->disctime);
04794             ast_log(LOG_NOTICE,"        link->retrytimer %ld\n",zl->retrytimer);
04795             ast_log(LOG_NOTICE,"        link->retries = %d\n",zl->retries);
04796 
04797                            zl = zl->next;
04798                   }
04799                                                                                                                                
04800          zt = myrpt->tele.next;
04801          if(zt != &myrpt->tele)
04802             ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
04803                   while(zt != &myrpt->tele){
04804             ast_log(LOG_NOTICE,"        Telemetry mode: %d\n",zt->mode);
04805                            zt = zt->next;
04806                   }
04807          ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
04808 
04809       }  
04810 
04811 
04812 
04813 
04814 
04815       ast_mutex_lock(&myrpt->lock);
04816       if (ast_check_hangup(myrpt->rxchannel)) break;
04817       if (ast_check_hangup(myrpt->txchannel)) break;
04818       if (ast_check_hangup(myrpt->pchannel)) break;
04819       if (ast_check_hangup(myrpt->txpchannel)) break;
04820       myrpt->localtx = myrpt->keyed && (myrpt->dtmfidx == -1) && (!myrpt->cmdnode[0]);
04821       
04822       /* If someone's connected, and they're transmitting from their end to us, set remrx true */
04823       
04824       l = myrpt->links.next;
04825       remrx = 0;
04826       while(l != &myrpt->links)
04827       {
04828          if (l->lastrx) remrx = 1;
04829          l = l->next;
04830       }
04831       
04832       /* Create a "must_id" flag for the cleanup ID */   
04833          
04834       myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
04835 
04836       /* Build a fresh totx from myrpt->keyed and autopatch activated */
04837       
04838       totx = myrpt->localtx || myrpt->callmode;
04839        
04840       /* Traverse the telemetry list to see if there's an ID queued and if there is not an ID queued */
04841       
04842       identqueued = 0;
04843       nonidentqueued = 0;
04844       
04845       telem = myrpt->tele.next;
04846       while(telem != &myrpt->tele)
04847       {
04848          if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
04849             identqueued = 1;
04850          }
04851          else
04852             nonidentqueued = 1;
04853          telem = telem->next;
04854       }
04855    
04856       /* Add in any non-id telemetry */
04857       
04858       totx = totx || nonidentqueued;
04859       
04860       /* Update external transmitter PTT state with everything but ID telemetry */
04861       
04862       myrpt->exttx = totx;
04863       
04864       /* Add in ID telemetry to local transmitter */
04865       
04866       totx = totx || remrx || identqueued;
04867       
04868       if (!totx) 
04869       {
04870          myrpt->totimer = myrpt->totime;
04871          myrpt->tounkeyed = 0;
04872          myrpt->tonotify = 0;
04873       }
04874       else myrpt->tailtimer = myrpt->hangtime;
04875       totx = totx && myrpt->totimer;
04876       /* if timed-out and not said already, say it */
04877       if ((!myrpt->totimer) && (!myrpt->tonotify))
04878       {
04879          myrpt->tonotify = 1;
04880          ast_mutex_unlock(&myrpt->lock);
04881          rpt_telemetry(myrpt,TIMEOUT,NULL);
04882          ast_mutex_lock(&myrpt->lock);
04883       }
04884       /* if wants to transmit and in phone call, but timed out, 
04885          reset time-out timer if keyed */
04886       if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
04887       {
04888          myrpt->tounkeyed = 1;
04889       }
04890       if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
04891       {
04892          myrpt->totimer = myrpt->totime;
04893          myrpt->tounkeyed = 0;
04894          myrpt->tonotify = 0;
04895          ast_mutex_unlock(&myrpt->lock);
04896          continue;
04897       }
04898       /* if timed-out and in circuit busy after call */
04899       if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
04900       {
04901          myrpt->callmode = 0;
04902       }
04903       /* get rid of tail if timed out */
04904       if (!myrpt->totimer) myrpt->tailtimer = 0;
04905       /* if not timed-out, add in tail */
04906       if (myrpt->totimer) totx = totx || myrpt->tailtimer;
04907       /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
04908       if (identqueued && (myrpt->keyed || remrx) && idtalkover) {
04909          int hasid = 0,hastalkover = 0;
04910 
04911          telem = myrpt->tele.next;
04912          while(telem != &myrpt->tele){
04913             if(telem->mode == ID){
04914                if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
04915                hasid = 1;
04916             }
04917             if (telem->mode == IDTALKOVER) hastalkover = 1;
04918             telem = telem->next;
04919          }
04920          ast_mutex_unlock(&myrpt->lock);
04921          if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL); /* Start Talkover ID */
04922          ast_mutex_lock(&myrpt->lock);
04923       }
04924       /* Try to be polite */
04925       /* If the repeater has been inactive for longer than the ID time, do an initial ID in the tail*/
04926       /* If within 30 seconds of the time to ID, try do it in the tail */
04927       /* else if at ID time limit, do it right over the top of them */
04928       /* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */
04929       if (((totx && (!myrpt->exttx) && (myrpt->idtimer <= myrpt->politeid) && myrpt->tailtimer)) ||
04930          (myrpt->mustid && (!myrpt->idtimer)))
04931       {
04932          myrpt->mustid = 0;
04933          myrpt->idtimer = myrpt->idtime; /* Reset our ID timer */
04934          ast_mutex_unlock(&myrpt->lock);
04935          rpt_telemetry(myrpt,ID,NULL);
04936          ast_mutex_lock(&myrpt->lock);
04937       }
04938       /* let telemetry transmit anyway (regardless of timeout) */
04939       totx = totx || (myrpt->tele.next != &myrpt->tele);
04940       if (totx && (!lasttx))
04941       {
04942          lasttx = 1;
04943          ast_mutex_unlock(&myrpt->lock);
04944          ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
04945          ast_mutex_lock(&myrpt->lock);
04946       }
04947       totx = totx && myrpt->enable;
04948       if ((!totx) && lasttx)
04949       {
04950          lasttx = 0;
04951          ast_mutex_unlock(&myrpt->lock);
04952          ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04953          ast_mutex_lock(&myrpt->lock);
04954       }
04955       time(&t);
04956       /* if DTMF timeout */
04957       if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((dtmf_time + DTMF_TIMEOUT) < t))
04958       {
04959          myrpt->dtmfidx = -1;
04960          myrpt->dtmfbuf[0] = 0;
04961       }        
04962       /* if remote DTMF timeout */
04963       if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
04964       {
04965          myrpt->rem_dtmfidx = -1;
04966          myrpt->rem_dtmfbuf[0] = 0;
04967       }  
04968       
04969       /* Reconnect kludge */
04970       l = myrpt->links.next;
04971       while(l != &myrpt->links)
04972       {
04973          if (l->killme)
04974          {
04975             /* remove from queue */
04976             remque((struct qelem *) l);
04977             if (!strcmp(myrpt->cmdnode,l->name))
04978                myrpt->cmdnode[0] = 0;
04979             ast_mutex_unlock(&myrpt->lock);
04980             /* hang-up on call to device */
04981             if (l->chan) ast_hangup(l->chan);
04982             ast_hangup(l->pchan);
04983             free(l);
04984             ast_mutex_lock(&myrpt->lock);
04985             /* re-start link traversal */
04986             l = myrpt->links.next;
04987             continue;
04988          }
04989          l = l->next;
04990       }
04991       n = 0;
04992       cs[n++] = myrpt->rxchannel;
04993       cs[n++] = myrpt->pchannel;
04994       cs[n++] = myrpt->txpchannel;
04995       if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
04996       l = myrpt->links.next;
04997       while(l != &myrpt->links)
04998       {
04999          if ((!l->killme) && (!l->disctime) && l->chan)
05000          {
05001             cs[n++] = l->chan;
05002             cs[n++] = l->pchan;
05003          }
05004          l = l->next;
05005       }
05006       ast_mutex_unlock(&myrpt->lock);
05007       ms = MSWAIT;
05008       who = ast_waitfor_n(cs,n,&ms);
05009       if (who == NULL) ms = 0;
05010       elap = MSWAIT - ms;
05011       ast_mutex_lock(&myrpt->lock);
05012       l = myrpt->links.next;
05013       while(l != &myrpt->links)
05014       {
05015          if (!l->lasttx)
05016          {
05017             if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
05018             {
05019                l->retxtimer = 0;
05020                if (l->chan) ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
05021             }
05022          } else l->retxtimer = 0;
05023 #ifdef   RECONNECT_KLUDGE
05024          if (l->disctime) /* Disconnect timer active on a channel ? */
05025          {
05026             l->disctime -= elap;
05027             if (l->disctime <= 0) /* Disconnect timer expired on inbound channel ? */
05028                l->disctime = 0; /* Yep */
05029          }
05030 
05031          if (l->retrytimer)
05032          {
05033             l->retrytimer -= elap;
05034             if (l->retrytimer < 0) l->retrytimer = 0;
05035          }
05036 #endif
05037          /* ignore non-timing channels */
05038          if (l->elaptime < 0)
05039          {
05040             l = l->next;
05041             continue;
05042          }
05043          l->elaptime += elap;
05044          /* if connection has taken too long */
05045          if ((l->elaptime > MAXCONNECTTIME) && 
05046             ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
05047          {
05048             l->elaptime = 0;
05049             ast_mutex_unlock(&myrpt->lock);
05050             if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
05051 #ifndef  RECONNECT_KLUDGE
05052             rpt_telemetry(myrpt,CONNFAIL,l);
05053 #endif
05054             ast_mutex_lock(&myrpt->lock);
05055             break;
05056          }
05057 #ifdef   RECONNECT_KLUDGE
05058          if ((!l->chan) && (!l->retrytimer) && l->outbound && 
05059             (l->retries++ < MAX_RETRIES) && (l->hasconnected))
05060          {
05061             if (l->chan) ast_hangup(l->chan);
05062             ast_mutex_unlock(&myrpt->lock);
05063             if ((l->name[0] != '0') && (!l->isremote))
05064             {
05065                l->retrytimer = MAX_RETRIES + 1;
05066             }
05067             else 
05068             {
05069                if (attempt_reconnect(myrpt,l) == -1)
05070                {
05071                   l->retrytimer = RETRY_TIMER_MS;
05072                }
05073             }
05074             ast_mutex_lock(&myrpt->lock);
05075             break;
05076          }
05077          if ((!l->chan) && (!l->retrytimer) && l->outbound &&
05078             (l->retries >= MAX_RETRIES))
05079          {
05080             /* remove from queue */
05081             remque((struct qelem *) l);
05082             if (!strcmp(myrpt->cmdnode,l->name))
05083                myrpt->cmdnode[0] = 0;
05084             ast_mutex_unlock(&myrpt->lock);
05085             if (l->name[0] != '0')
05086             {
05087                if (!l->hasconnected)
05088                   rpt_telemetry(myrpt,CONNFAIL,l);
05089                else rpt_telemetry(myrpt,REMDISC,l);
05090             }
05091             /* hang-up on call to device */
05092             ast_hangup(l->pchan);
05093             free(l);
05094                                 ast_mutex_lock(&myrpt->lock);
05095             break;
05096          }
05097                         if ((!l->chan) && (!l->disctime) && (!l->outbound))
05098                         {
05099                                 /* remove from queue */
05100                                 remque((struct qelem *) l);
05101                                 if (!strcmp(myrpt->cmdnode,l->name))
05102                                         myrpt->cmdnode[0] = 0;
05103                                 ast_mutex_unlock(&myrpt->lock);
05104             if (l->name[0] != '0') 
05105             {
05106                                    rpt_telemetry(myrpt,REMDISC,l);
05107             }
05108                                 /* hang-up on call to device */
05109                                 ast_hangup(l->pchan);
05110                                 free(l);
05111                                 ast_mutex_lock(&myrpt->lock);
05112                                 break;
05113                         }
05114 #endif
05115          l = l->next;
05116       }
05117       if (myrpt->tailtimer) myrpt->tailtimer -= elap;
05118       if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
05119       if (myrpt->totimer) myrpt->totimer -= elap;
05120       if (myrpt->totimer < 0) myrpt->totimer = 0;
05121       if (myrpt->idtimer) myrpt->idtimer -= elap;
05122       if (myrpt->idtimer < 0) myrpt->idtimer = 0;
05123       ast_mutex_unlock(&myrpt->lock);
05124       if (!ms) continue;
05125       if (who == myrpt->rxchannel) /* if it was a read from rx */
05126       {
05127          f = ast_read(myrpt->rxchannel);
05128          if (!f)
05129          {
05130             if (debug) printf("@@@@ rpt:Hung Up\n");
05131             break;
05132          }
05133          if (f->frametype == AST_FRAME_VOICE)
05134          {
05135             if (!myrpt->localtx)
05136                memset(f->data,0,f->datalen);
05137             ast_write(myrpt->pchannel,f);
05138          }
05139          else if (f->frametype == AST_FRAME_DTMF)
05140          {
05141             char c;
05142 
05143             c = (char) f->subclass; /* get DTMF char */
05144             ast_frfree(f);
05145             if (!myrpt->keyed) continue;
05146             if (c == myrpt->endchar)
05147             {
05148                /* if in simple mode, kill autopatch */
05149                if (myrpt->simple && myrpt->callmode)
05150                {
05151                   ast_mutex_lock(&myrpt->lock);
05152                   myrpt->callmode = 0;
05153                   ast_mutex_unlock(&myrpt->lock);
05154                   rpt_telemetry(myrpt,TERM,NULL);
05155                   continue;
05156                }
05157                ast_mutex_lock(&myrpt->lock);
05158                myrpt->stopgen = 1;
05159                if (myrpt->cmdnode[0])
05160                {
05161                   myrpt->cmdnode[0] = 0;
05162                   myrpt->dtmfidx = -1;
05163                   myrpt->dtmfbuf[0] = 0;
05164                   ast_mutex_unlock(&myrpt->lock);
05165                   rpt_telemetry(myrpt,COMPLETE,NULL);
05166                } else ast_mutex_unlock(&myrpt->lock);
05167                continue;
05168             }
05169             ast_mutex_lock(&myrpt->lock);
05170             if (myrpt->cmdnode[0])
05171             {
05172                ast_mutex_unlock(&myrpt->lock);
05173                send_link_dtmf(myrpt,c);
05174                continue;
05175             }
05176             if (!myrpt->simple)
05177             {
05178                if (c == myrpt->funcchar)
05179                {
05180                   myrpt->dtmfidx = 0;
05181                   myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
05182                   ast_mutex_unlock(&myrpt->lock);
05183                   time(&dtmf_time);
05184                   continue;
05185                } 
05186                else if ((c != myrpt->endchar) && (myrpt->dtmfidx >= 0))
05187                {
05188                   time(&dtmf_time);
05189                   
05190                   if (myrpt->dtmfidx < MAXDTMF)
05191                   {
05192                      myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
05193                      myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
05194                      
05195                      strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
05196                      
05197                      ast_mutex_unlock(&myrpt->lock);
05198                      res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL);
05199                      ast_mutex_lock(&myrpt->lock);
05200 
05201                      switch(res){
05202          
05203                         case DC_INDETERMINATE:
05204                            break;
05205             
05206                         case DC_REQ_FLUSH:
05207                            myrpt->dtmfidx = 0;
05208                            myrpt->dtmfbuf[0] = 0;
05209                            break;
05210             
05211             
05212                         case DC_COMPLETE:
05213                            myrpt->dtmfbuf[0] = 0;
05214                            myrpt->dtmfidx = -1;
05215                            dtmf_time = 0;
05216                            break;
05217             
05218                         case DC_ERROR:
05219                         default:
05220                            myrpt->dtmfbuf[0] = 0;
05221                            myrpt->dtmfidx = -1;
05222                            dtmf_time = 0;
05223                            break;
05224                      }
05225                      if(res != DC_INDETERMINATE) {
05226                         ast_mutex_unlock(&myrpt->lock);
05227                         continue;
05228                      }
05229                   } 
05230                }
05231             }
05232             else /* if simple */
05233             {
05234                if ((!myrpt->callmode) && (c == myrpt->funcchar))
05235                {
05236                   myrpt->callmode = 1;
05237                   myrpt->cidx = 0;
05238                   myrpt->exten[myrpt->cidx] = 0;
05239                   ast_mutex_unlock(&myrpt->lock);
05240                        pthread_attr_init(&attr);
05241                        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05242                   ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
05243                   continue;
05244                }
05245             }
05246             if (myrpt->callmode == 1)
05247             {
05248                myrpt->exten[myrpt->cidx++] = c;
05249                myrpt->exten[myrpt->cidx] = 0;
05250                /* if this exists */
05251                if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
05252                {
05253                   myrpt->callmode = 2;
05254                   ast_mutex_unlock(&myrpt->lock);
05255                   rpt_telemetry(myrpt,PROC,NULL); 
05256                   continue;
05257                }
05258                /* if can continue, do so */
05259                if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
05260                {
05261                   /* call has failed, inform user */
05262                   myrpt->callmode = 4;
05263                }
05264                ast_mutex_unlock(&myrpt->lock);
05265                continue;
05266             }
05267             if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
05268             {
05269                myrpt->mydtmf = c;
05270             }
05271             ast_mutex_unlock(&myrpt->lock);
05272             continue;
05273          }                 
05274          else if (f->frametype == AST_FRAME_CONTROL)
05275          {
05276             if (f->subclass == AST_CONTROL_HANGUP)
05277             {
05278                if (debug) printf("@@@@ rpt:Hung Up\n");
05279                ast_frfree(f);
05280                break;
05281             }
05282             /* if RX key */
05283             if (f->subclass == AST_CONTROL_RADIO_KEY)
05284             {
05285                if (debug) printf("@@@@ rx key\n");
05286                myrpt->keyed = 1;
05287             }
05288             /* if RX un-key */
05289             if (f->subclass == AST_CONTROL_RADIO_UNKEY)
05290             {
05291                if (debug) printf("@@@@ rx un-key\n");
05292                if(myrpt->keyed) {
05293                   rpt_telemetry(myrpt,UNKEY,NULL);
05294                }
05295                myrpt->keyed = 0;
05296             }
05297          }
05298          ast_frfree(f);
05299          continue;
05300       }
05301       if (who == myrpt->pchannel) /* if it was a read from pseudo */
05302       {
05303          f = ast_read(myrpt->pchannel);
05304          if (!f)
05305          {
05306             if (debug) printf("@@@@ rpt:Hung Up\n");
05307             break;
05308          }
05309          if (f->frametype == AST_FRAME_VOICE)
05310          {
05311             ast_write(myrpt->txpchannel,f);
05312          }
05313          if (f->frametype == AST_FRAME_CONTROL)
05314          {
05315             if (f->subclass == AST_CONTROL_HANGUP)
05316             {
05317                if (debug) printf("@@@@ rpt:Hung Up\n");
05318                ast_frfree(f);
05319                break;
05320             }
05321          }
05322          ast_frfree(f);
05323          continue;
05324       }
05325       if (who == myrpt->txchannel) /* if it was a read from tx */
05326       {
05327          f = ast_read(myrpt->txchannel);
05328          if (!f)
05329          {
05330             if (debug) printf("@@@@ rpt:Hung Up\n");
05331             break;
05332          }
05333          if (f->frametype == AST_FRAME_CONTROL)
05334          {
05335             if (f->subclass == AST_CONTROL_HANGUP)
05336             {
05337                if (debug) printf("@@@@ rpt:Hung Up\n");
05338                ast_frfree(f);
05339                break;
05340             }
05341          }
05342          ast_frfree(f);
05343          continue;
05344       }
05345       toexit = 0;
05346       ast_mutex_lock(&myrpt->lock);
05347       l = myrpt->links.next;
05348       while(l != &myrpt->links)
05349       {
05350          if (l->disctime)
05351          {
05352             l = l->next;
05353             continue;
05354          }
05355          if (who == l->chan) /* if it was a read from rx */
05356          {
05357             remrx = 0;
05358             /* see if any other links are receiving */
05359             m = myrpt->links.next;
05360             while(m != &myrpt->links)
05361             {
05362                /* if not us, count it */
05363                if ((m != l) && (m->lastrx)) remrx = 1;
05364                m = m->next;
05365             }
05366             ast_mutex_unlock(&myrpt->lock);
05367             totx = (((l->isremote) ? myrpt->localtx : 
05368                myrpt->exttx) || remrx) && l->mode;
05369             if (l->chan && (l->lasttx != totx))
05370             {
05371                if (totx)
05372                {
05373                   ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
05374                }
05375                else
05376                {
05377                   ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
05378                }
05379             }
05380             l->lasttx = totx;
05381             f = ast_read(l->chan);
05382             if (!f)
05383             {
05384 #ifdef   RECONNECT_KLUDGE
05385                if ((!l->disced) && (!l->outbound))
05386                {
05387                   if ((l->name[0] == '0') || l->isremote)
05388                      l->disctime = 1;
05389                   else
05390                      l->disctime = DISC_TIME;
05391                   ast_mutex_lock(&myrpt->lock);
05392                   ast_hangup(l->chan);
05393                   l->chan = 0;
05394                   break;
05395                }
05396 
05397                if (l->retrytimer) 
05398                {
05399                   ast_mutex_lock(&myrpt->lock);
05400                   break; 
05401                }
05402                if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected))
05403                {
05404                   ast_mutex_lock(&myrpt->lock);
05405                   ast_hangup(l->chan);
05406                   l->chan = 0;
05407                   ast_mutex_unlock(&myrpt->lock);
05408                   if (attempt_reconnect(myrpt,l) == -1)
05409                   {
05410                      l->retrytimer = RETRY_TIMER_MS;
05411                   }
05412                   ast_mutex_lock(&myrpt->lock);
05413                   break;
05414                }
05415 #endif
05416                ast_mutex_lock(&myrpt->lock);
05417                /* remove from queue */
05418                remque((struct qelem *) l);
05419                if (!strcmp(myrpt->cmdnode,l->name))
05420                   myrpt->cmdnode[0] = 0;
05421                ast_mutex_unlock(&myrpt->lock);
05422                if (!l->hasconnected)
05423                   rpt_telemetry(myrpt,CONNFAIL,l);
05424                else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
05425                /* hang-up on call to device */
05426                ast_hangup(l->chan);
05427                ast_hangup(l->pchan);
05428                free(l);
05429                ast_mutex_lock(&myrpt->lock);
05430                break;
05431             }
05432             if (f->frametype == AST_FRAME_VOICE)
05433             {
05434                if (l->phonemode && (!l->lastrx))
05435                {
05436                   memset(f->data,0,f->datalen);
05437                }
05438                ast_write(l->pchan,f);
05439             }
05440             if (f->frametype == AST_FRAME_TEXT)
05441             {
05442                handle_link_data(myrpt,l,f->data);
05443             }
05444             if (f->frametype == AST_FRAME_DTMF)
05445             {
05446                handle_link_phone_dtmf(myrpt,l,f->subclass);
05447             }
05448             if (f->frametype == AST_FRAME_CONTROL)
05449             {
05450                if (f->subclass == AST_CONTROL_ANSWER)
05451                {
05452                   char lconnected = l->connected;
05453                   l->connected = 1;
05454                   l->hasconnected = 1;
05455                   l->elaptime = -1;
05456                   l->retries = 0;
05457                   if (!lconnected) rpt_telemetry(myrpt,CONNECTED,l);
05458                }
05459                /* if RX key */
05460                if (f->subclass == AST_CONTROL_RADIO_KEY)
05461                {
05462                   if (debug) printf("@@@@ rx key\n");
05463                   l->lastrx = 1;
05464                }
05465                /* if RX un-key */
05466                if (f->subclass == AST_CONTROL_RADIO_UNKEY)
05467                {
05468                   if (debug) printf("@@@@ rx un-key\n");
05469                   l->lastrx = 0;
05470                }
05471                if (f->subclass == AST_CONTROL_HANGUP)
05472                {
05473                   ast_frfree(f);
05474 #ifdef   RECONNECT_KLUDGE
05475                   if ((!l->outbound) && (!l->disced))
05476                   {
05477                      if ((l->name[0] == '0') || l->isremote)
05478                         l->disctime = 1;
05479                      else
05480                         l->disctime = DISC_TIME;
05481                      ast_mutex_lock(&myrpt->lock);
05482                      ast_hangup(l->chan);
05483                      l->chan = 0;
05484                      break;
05485                   }
05486                   if (l->retrytimer) 
05487                   {
05488                      ast_mutex_lock(&myrpt->lock);
05489                      break;
05490                   }
05491                   if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected))
05492                   {
05493                      ast_mutex_lock(&myrpt->lock);
05494                      ast_hangup(l->chan);
05495                      l->chan = 0;
05496                      ast_mutex_unlock(&myrpt->lock);
05497                      if (attempt_reconnect(myrpt,l) == -1)
05498                      {
05499                         l->retrytimer = RETRY_TIMER_MS;
05500                      }
05501                      ast_mutex_lock(&myrpt->lock);
05502                      break;
05503                   }
05504 #endif
05505                   ast_mutex_lock(&myrpt->lock);
05506                   /* remove from queue */
05507                   remque((struct qelem *) l);
05508                   if (!strcmp(myrpt->cmdnode,l->name))
05509                      myrpt->cmdnode[0] = 0;
05510                   ast_mutex_unlock(&myrpt->lock);
05511                   if (!l->hasconnected)
05512                      rpt_telemetry(myrpt,CONNFAIL,l);
05513                   else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
05514                   /* hang-up on call to device */
05515                   ast_hangup(l->chan);
05516                   ast_hangup(l->pchan);
05517                   free(l);
05518                   ast_mutex_lock(&myrpt->lock);
05519                   break;
05520                }
05521             }
05522             ast_frfree(f);
05523             ast_mutex_lock(&myrpt->lock);
05524             break;
05525          }
05526          if (who == l->pchan) 
05527          {
05528             ast_mutex_unlock(&myrpt->lock);
05529             f = ast_read(l->pchan);
05530             if (!f)
05531             {
05532                if (debug) printf("@@@@ rpt:Hung Up\n");
05533                toexit = 1;
05534                ast_mutex_lock(&myrpt->lock);
05535                break;
05536             }
05537             if (f->frametype == AST_FRAME_VOICE)
05538             {
05539                if (l->chan) ast_write(l->chan,f);
05540             }
05541             if (f->frametype == AST_FRAME_CONTROL)
05542             {
05543                if (f->subclass == AST_CONTROL_HANGUP)
05544                {
05545                   if (debug) printf("@@@@ rpt:Hung Up\n");
05546                   ast_frfree(f);
05547                   toexit = 1;
05548                   ast_mutex_lock(&myrpt->lock);
05549                   break;
05550                }
05551             }
05552             ast_frfree(f);
05553             ast_mutex_lock(&myrpt->lock);
05554             break;
05555          }
05556          l = l->next;
05557       }
05558       ast_mutex_unlock(&myrpt->lock);
05559       if (toexit) break;
05560       if (who == myrpt->txpchannel) /* if it was a read from remote tx */
05561       {
05562          f = ast_read(myrpt->txpchannel);
05563          if (!f)
05564          {
05565             if (debug) printf("@@@@ rpt:Hung Up\n");
05566             break;
05567          }
05568          if (f->frametype == AST_FRAME_CONTROL)
05569          {
05570             if (f->subclass == AST_CONTROL_HANGUP)
05571             {
05572                if (debug) printf("@@@@ rpt:Hung Up\n");
05573                ast_frfree(f);
05574                break;
05575             }
05576          }
05577          ast_frfree(f);
05578          continue;
05579       }
05580    }
05581    usleep(100000);
05582    ast_hangup(myrpt->pchannel);
05583    ast_hangup(myrpt->txpchannel);
05584    if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
05585    ast_hangup(myrpt->rxchannel);
05586    ast_mutex_lock(&myrpt->lock);
05587    l = myrpt->links.next;
05588    while(l != &myrpt->links)
05589    {
05590       struct rpt_link *ll = l;
05591       /* remove from queue */
05592       remque((struct qelem *) l);
05593       /* hang-up on call to device */
05594       if (l->chan) ast_hangup(l->chan);
05595       ast_hangup(l->pchan);
05596       l = l->next;
05597       free(ll);
05598    }
05599    ast_mutex_unlock(&myrpt->lock);
05600    if (debug) printf("@@@@ rpt:Hung up channel\n");
05601    myrpt->rpt_thread = AST_PTHREADT_STOP;
05602    pthread_exit(NULL); 
05603    return NULL;
05604 }

static void* rpt_call ( void *  this  )  [static]

Definition at line 1528 of file app_rpt.c.

References ast_channel::accountcode, rpt::acctcode, ast_callerid_parse(), ast_channel_undefer_dtmf(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_request(), ast_safe_sleep(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_write(), rpt::callmode, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, rpt::cidx, rpt::conf, ast_channel::context, ast_frame::data, ast_frame::datalen, rpt::exten, ast_channel::exten, ast_channel::fds, ast_frame::frametype, free, rpt::lock, LOG_WARNING, ast_frame::mallocd, MSWAIT, rpt::mydtmf, name, ast_frame::offset, rpt::ourcallerid, rpt::ourcontext, ast_channel::pbx, ast_channel::priority, ast_frame::samples, strdup, ast_frame::subclass, and rpt::tonezone.

Referenced by function_autopatchup(), and rpt().

01529 {
01530 ZT_CONFINFO ci;  /* conference info */
01531 struct   rpt *myrpt = (struct rpt *)this;
01532 int   res;
01533 struct   ast_frame wf;
01534 int stopped,congstarted;
01535 struct ast_channel *mychannel,*genchannel;
01536 
01537    myrpt->mydtmf = 0;
01538    /* allocate a pseudo-channel thru asterisk */
01539    mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
01540    if (!mychannel)
01541    {
01542       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
01543       pthread_exit(NULL);
01544    }
01545    ci.chan = 0;
01546    ci.confno = myrpt->conf; /* use the pseudo conference */
01547    ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
01548       | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER; 
01549    /* first put the channel on the conference */
01550    if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
01551    {
01552       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01553       ast_hangup(mychannel);
01554       myrpt->callmode = 0;
01555       pthread_exit(NULL);
01556    }
01557    /* allocate a pseudo-channel thru asterisk */
01558    genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
01559    if (!genchannel)
01560    {
01561       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
01562       ast_hangup(mychannel);
01563       pthread_exit(NULL);
01564    }
01565    ci.chan = 0;
01566    ci.confno = myrpt->conf;
01567    ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
01568       | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER; 
01569    /* first put the channel on the conference */
01570    if (ioctl(genchannel->fds[0],ZT_SETCONF,&ci) == -1)
01571    {
01572       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01573       ast_hangup(mychannel);
01574       ast_hangup(genchannel);
01575       myrpt->callmode = 0;
01576       pthread_exit(NULL);
01577    }
01578    if (myrpt->tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->tonezone) == -1))
01579    {
01580       ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
01581       ast_hangup(mychannel);
01582       ast_hangup(genchannel);
01583       myrpt->callmode = 0;
01584       pthread_exit(NULL);
01585    }
01586    if (myrpt->tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->tonezone) == -1))
01587    {
01588       ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
01589       ast_hangup(mychannel);
01590       ast_hangup(genchannel);
01591       myrpt->callmode = 0;
01592       pthread_exit(NULL);
01593    }
01594    /* start dialtone */
01595    if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0)
01596    {
01597       ast_log(LOG_WARNING, "Cannot start dialtone\n");
01598       ast_hangup(mychannel);
01599       ast_hangup(genchannel);
01600       myrpt->callmode = 0;
01601       pthread_exit(NULL);
01602    }
01603    stopped = 0;
01604    congstarted = 0;
01605    while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
01606    {
01607 
01608       if ((myrpt->callmode == 1) && (myrpt->cidx > 0) && (!stopped))
01609       {
01610          stopped = 1;
01611          /* stop dial tone */
01612          tone_zone_play_tone(mychannel->fds[0],-1);
01613       }
01614       if ((myrpt->callmode == 4) && (!congstarted))
01615       {
01616          congstarted = 1;
01617          /* start congestion tone */
01618          tone_zone_play_tone(mychannel->fds[0],ZT_TONE_CONGESTION);
01619       }
01620       res = ast_safe_sleep(mychannel, MSWAIT);
01621       if (res < 0)
01622       {
01623          ast_hangup(mychannel);
01624          ast_hangup(genchannel);
01625          ast_mutex_lock(&myrpt->lock);
01626          myrpt->callmode = 0;
01627          ast_mutex_unlock(&myrpt->lock);
01628          pthread_exit(NULL);
01629       }
01630    }
01631    /* stop any tone generation */
01632    tone_zone_play_tone(mychannel->fds[0],-1);
01633    /* end if done */
01634    if (!myrpt->callmode)
01635    {
01636       ast_hangup(mychannel);
01637       ast_hangup(genchannel);
01638       ast_mutex_lock(&myrpt->lock);
01639       myrpt->callmode = 0;
01640       ast_mutex_unlock(&myrpt->lock);
01641       pthread_exit(NULL);        
01642    }
01643 
01644    if (myrpt->ourcallerid && *myrpt->ourcallerid){
01645       char *name, *loc, *instr;
01646       instr = strdup(myrpt->ourcallerid);
01647       if(instr){
01648          ast_callerid_parse(instr, &name, &loc);
01649          if(loc){
01650             if(mychannel->cid.cid_num)
01651                free(mychannel->cid.cid_num);
01652             mychannel->cid.cid_num = strdup(loc);
01653          }
01654          if(name){
01655             if(mychannel->cid.cid_name)
01656                free(mychannel->cid.cid_name);
01657             mychannel->cid.cid_name = strdup(name);
01658          }
01659          free(instr);
01660       }
01661    }
01662 
01663    strncpy(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
01664    strncpy(mychannel->context, myrpt->ourcontext, sizeof(mychannel->context) - 1);
01665    if (myrpt->acctcode)
01666       strncpy(mychannel->accountcode, myrpt->acctcode, sizeof(mychannel->accountcode) - 1);
01667    mychannel->priority = 1;
01668    ast_channel_undefer_dtmf(mychannel);
01669    if (ast_pbx_start(mychannel) < 0)
01670    {
01671       ast_log(LOG_WARNING, "Unable to start PBX!!\n");
01672       ast_hangup(mychannel);
01673       ast_hangup(genchannel);
01674       ast_mutex_lock(&myrpt->lock);
01675       myrpt->callmode = 0;
01676       ast_mutex_unlock(&myrpt->lock);
01677       pthread_exit(NULL);
01678    }
01679    usleep(10000);
01680    ast_mutex_lock(&myrpt->lock);
01681    myrpt->callmode = 3;
01682    while(myrpt->callmode)
01683    {
01684       if ((!mychannel->pbx) && (myrpt->callmode != 4))
01685       {
01686          myrpt->callmode = 4;
01687          ast_mutex_unlock(&myrpt->lock);
01688          /* start congestion tone */
01689          tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
01690          ast_mutex_lock(&myrpt->lock);
01691       }
01692       if (myrpt->mydtmf)
01693       {
01694          wf.frametype = AST_FRAME_DTMF;
01695          wf.subclass = myrpt->mydtmf;
01696          wf.offset = 0;
01697          wf.mallocd = 0;
01698          wf.data = NULL;
01699          wf.datalen = 0;
01700          wf.samples = 0;
01701          ast_mutex_unlock(&myrpt->lock);
01702          ast_write(genchannel,&wf); 
01703          ast_mutex_lock(&myrpt->lock);
01704          myrpt->mydtmf = 0;
01705       }
01706       ast_mutex_unlock(&myrpt->lock);
01707       usleep(MSWAIT * 1000);
01708       ast_mutex_lock(&myrpt->lock);
01709    }
01710    ast_mutex_unlock(&myrpt->lock);
01711    tone_zone_play_tone(genchannel->fds[0],-1);
01712    if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
01713    ast_hangup(genchannel);
01714    ast_mutex_lock(&myrpt->lock);
01715    myrpt->callmode = 0;
01716    ast_mutex_unlock(&myrpt->lock);
01717    pthread_exit(NULL);
01718 }

static int rpt_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 476 of file app_rpt.c.

References ast_cli(), myatoi(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00477 {
00478    int newlevel;
00479 
00480         if (argc != 4)
00481                 return RESULT_SHOWUSAGE;
00482         newlevel = myatoi(argv[3]);
00483         if((newlevel < 0) || (newlevel > 7))
00484                 return RESULT_SHOWUSAGE;
00485         if(newlevel)
00486                 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
00487         else
00488                 ast_cli(fd, "app_rpt Debugging disabled\n");
00489 
00490         debug = newlevel;                                                                                                                          
00491         return RESULT_SUCCESS;
00492 }

static int rpt_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 5830 of file app_rpt.c.

References ast_channel::_state, ahp, ast_channel::appl, ast_answer(), ast_call(), ast_callerid_parse(), ast_check_hangup(), AST_CONTROL_BUSY, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_exists_extension(), AST_FORMAT_SLINEAR, ast_gethostbyname(), ast_hangup(), ast_indicate(), ast_inet_ntoa(), ast_log(), ast_masq_park_call(), ast_mutex_lock(), ast_mutex_unlock(), AST_PBX_KEEPALIVE, ast_request(), ast_safe_sleep(), ast_set_callerid(), ast_set_read_format(), ast_set_write_format(), ast_shrink_phone_number(), AST_STATE_UP, ast_strlen_zero(), ast_variable_retrieve(), ast_verbose(), ast_waitfor_n(), rpt::callmode, cfg, rpt_link::chan, ast_channel::cid, ast_callerid::cid_num, rpt::conf, ast_channel::context, context, ast_channel::data, rpt_link::disced, rpt::dtmf_time_rem, rpt::dtmfbuf, rpt::dtmfidx, ast_channel::exten, exten, ast_channel::fds, free, rpt::hfscanmode, rpt::hfscanstatus, hp, rpt::iobase, rpt_link::killme, rpt::links, LOCAL_USER_ADD, rpt::lock, LOG_WARNING, malloc, MAX_RETRIES, MAXNODESTR, MSWAIT, n, rpt_link::name, rpt::name, ast_channel::name, name, rpt_link::next, rpt::nobusyout, rpt::nodes, option_verbose, pbx_substitute_variables_helper(), ast_channel::priority, REDUNDANT_TX_TIME, rpt::remote, rpt::remoteon, rpt::remoterx, rpt::remotetx, rpt_link::retries, rpt::retxtimer, REV_PATCH, rpt_telemetry(), rpt_vars, rpt::rxchanname, rpt::rxchannel, s, setrem(), strsep(), rpt::txchanname, rpt::txchannel, VERBOSE_PREFIX_3, and ast_channel::whentohangup.

Referenced by load_module().

05831 {
05832    int res=-1,i,rem_totx,n,phone_mode = 0;
05833    struct localuser *u;
05834    char tmp[256], keyed = 0;
05835    char *options,*stringp,*tele;
05836    struct   rpt *myrpt;
05837    struct ast_frame *f;
05838    struct ast_channel *who;
05839    struct ast_channel *cs[20];
05840    struct   rpt_link *l;
05841    ZT_CONFINFO ci;  /* conference info */
05842    ZT_PARAMS par;
05843    int ms,elap;
05844 
05845    if (ast_strlen_zero(data)) {
05846       ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
05847       return -1;
05848    }
05849    strncpy(tmp, (char *)data, sizeof(tmp)-1);
05850    stringp=tmp;
05851    strsep(&stringp, "|");
05852    options = stringp;
05853    myrpt = NULL;
05854    /* see if we can find our specified one */
05855    for(i = 0; i < nrpts; i++)
05856    {
05857       /* if name matches, assign it and exit loop */
05858       if (!strcmp(tmp,rpt_vars[i].name))
05859       {
05860          myrpt = &rpt_vars[i];
05861          break;
05862       }
05863    }
05864    if (myrpt == NULL)
05865    {
05866       ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
05867       return -1;
05868    }
05869 
05870    /* if not phone access, must be an IAX connection */
05871    if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R')))
05872    {
05873       phone_mode = 1;
05874       if (*options == 'D') phone_mode = 2;
05875       ast_set_callerid(chan,"0","app_rpt user","0");
05876    }
05877    else
05878    {
05879       if (strncmp(chan->name,"IAX2",4))
05880       {
05881          ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
05882          return -1;
05883       }
05884    }
05885    if (options && (*options == 'R'))
05886    {
05887 
05888       /* Parts of this section taken from app_parkandannounce */
05889       char *return_context;
05890       int l, m, lot, timeout = 0;
05891       char tmp[256],*template;
05892       char *working, *context, *exten, *priority;
05893       char *s,*orig_s;
05894 
05895 
05896       ast_mutex_lock(&myrpt->lock);
05897       m = myrpt->callmode;
05898       ast_mutex_unlock(&myrpt->lock);
05899 
05900       if ((!myrpt->nobusyout) && m)
05901       {
05902          if (chan->_state != AST_STATE_UP)
05903          {
05904             ast_indicate(chan,AST_CONTROL_BUSY);
05905          }
05906          while(ast_safe_sleep(chan,10000) != -1);
05907          return -1;
05908       }
05909 
05910       if (chan->_state != AST_STATE_UP)
05911       {
05912          ast_answer(chan);
05913       }
05914 
05915       l=strlen(options)+2;
05916       orig_s=malloc(l);
05917       if(!orig_s) {
05918          ast_log(LOG_WARNING, "Out of memory\n");
05919          return -1;
05920       }
05921       s=orig_s;
05922       strncpy(s,options,l);
05923 
05924       template=strsep(&s,"|");
05925       if(!template) {
05926          ast_log(LOG_WARNING, "An announce template must be defined\n");
05927          free(orig_s);
05928          return -1;
05929       } 
05930   
05931       if(s) {
05932          timeout = atoi(strsep(&s, "|"));
05933          timeout *= 1000;
05934       }
05935    
05936       return_context = s;
05937   
05938       if(return_context != NULL) {
05939          /* set the return context. Code borrowed from the Goto builtin */
05940     
05941          working = return_context;
05942          context = strsep(&working, "|");
05943          exten = strsep(&working, "|");
05944          if(!exten) {
05945             /* Only a priority in this one */
05946             priority = context;
05947             exten = NULL;
05948             context = NULL;
05949          } else {
05950             priority = strsep(&working, "|");
05951             if(!priority) {
05952                /* Only an extension and priority in this one */
05953                priority = exten;
05954                exten = context;
05955                context = NULL;
05956          }
05957       }
05958       if(atoi(priority) < 0) {
05959          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
05960          free(orig_s);
05961          return -1;
05962       }
05963       /* At this point we have a priority and maybe an extension and a context */
05964       chan->priority = atoi(priority);
05965       if(exten && strcasecmp(exten, "BYEXTENSION"))
05966          strncpy(chan->exten, exten, sizeof(chan->exten)-1);
05967       if(context)
05968          strncpy(chan->context, context, sizeof(chan->context)-1);
05969       } else {  /* increment the priority by default*/
05970          chan->priority++;
05971       }
05972 
05973       if(option_verbose > 2) {
05974          ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
05975          if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
05976             ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
05977          }
05978       }
05979   
05980       /* we are using masq_park here to protect * from touching the channel once we park it.  If the channel comes out of timeout
05981       before we are done announcing and the channel is messed with, Kablooeee.  So we use Masq to prevent this.  */
05982 
05983       ast_masq_park_call(chan, NULL, timeout, &lot);
05984 
05985       if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
05986 
05987       snprintf(tmp,sizeof(tmp) - 1,"%d,%s",lot,template + 1);
05988 
05989       rpt_telemetry(myrpt,REV_PATCH,tmp);
05990 
05991       free(orig_s);
05992 
05993       return 0;
05994 
05995    }
05996 
05997    if (!options)
05998    {
05999                 struct ast_hostent ahp;
06000                 struct hostent *hp;
06001       struct in_addr ia;
06002       char hisip[100],nodeip[100],*val, *s, *s1, *s2, *b,*b1;
06003 
06004       /* look at callerid to see what node this comes from */
06005       if (!chan->cid.cid_num) /* if doesn't have caller id */
06006       {
06007          ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
06008          return -1;
06009       }
06010 
06011       /* get his IP from IAX2 module */
06012       memset(hisip,0,sizeof(hisip));
06013       pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
06014       if (!hisip[0])
06015       {
06016          ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
06017          return -1;
06018       }
06019       
06020       ast_callerid_parse(chan->cid.cid_num,&b,&b1);
06021       ast_shrink_phone_number(b1);
06022       if (!strcmp(myrpt->name,b1))
06023       {
06024          ast_log(LOG_WARNING, "Trying to link to self!!\n");
06025          return -1;
06026       }
06027 
06028       if (*b1 < '1')
06029       {
06030          ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
06031          return -1;
06032       }
06033 
06034 
06035       /* look for his reported node string */
06036       val = ast_variable_retrieve(cfg, myrpt->nodes, b1);
06037       if (!val)
06038       {
06039          ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
06040          return -1;
06041       }
06042       strncpy(tmp,val,sizeof(tmp) - 1);
06043       s = tmp;
06044       s1 = strsep(&s,",");
06045       s2 = strsep(&s,",");
06046       if (!s2)
06047       {
06048          ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
06049          return -1;
06050       }
06051                 if (strcmp(s2,"NONE")) {
06052          hp = ast_gethostbyname(s2, &ahp);
06053          if (!hp)
06054          {
06055             ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
06056             return -1;
06057          }
06058          memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
06059          ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
06060          if (strcmp(hisip,nodeip))
06061          {
06062             char *s3 = strchr(s1,'@');
06063             if (s3) s1 = s3 + 1;
06064             s3 = strchr(s1,'/');
06065             if (s3) *s3 = 0;
06066             hp = ast_gethostbyname(s1, &ahp);
06067             if (!hp)
06068             {
06069                ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
06070                return -1;
06071             }
06072             memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
06073             ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
06074             if (strcmp(hisip,nodeip))
06075             {
06076                ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
06077                return -1;
06078             }
06079          }
06080       }
06081    }
06082 
06083    /* if is not a remote */
06084    if (!myrpt->remote)
06085    {
06086 
06087       char *b,*b1;
06088 
06089       /* look at callerid to see what node this comes from */
06090       if (!chan->cid.cid_num) /* if doesn't have caller id */
06091       {
06092          ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
06093          return -1;
06094       }
06095 
06096       ast_callerid_parse(chan->cid.cid_num,&b,&b1);
06097       ast_shrink_phone_number(b1);
06098       if (!strcmp(myrpt->name,b1))
06099       {
06100          ast_log(LOG_WARNING, "Trying to link to self!!\n");
06101          return -1;
06102       }
06103       ast_mutex_lock(&myrpt->lock);
06104       l = myrpt->links.next;
06105       /* try to find this one in queue */
06106       while(l != &myrpt->links)
06107       {
06108          if (l->name[0] == '0') 
06109          {
06110             l = l->next;
06111             continue;
06112          }
06113          /* if found matching string */
06114          if (!strcmp(l->name,b1)) break;
06115          l = l->next;
06116       }
06117       /* if found */
06118       if (l != &myrpt->links) 
06119       {
06120          l->killme = 1;
06121          l->retries = MAX_RETRIES + 1;
06122          l->disced = 2;
06123                         ast_mutex_unlock(&myrpt->lock);
06124          usleep(500000);   
06125       } else 
06126          ast_mutex_unlock(&myrpt->lock);
06127       /* establish call in tranceive mode */
06128       l = malloc(sizeof(struct rpt_link));
06129       if (!l)
06130       {
06131          ast_log(LOG_WARNING, "Unable to malloc\n");
06132          pthread_exit(NULL);
06133       }
06134       /* zero the silly thing */
06135       memset((char *)l,0,sizeof(struct rpt_link));
06136       l->mode = 1;
06137       strncpy(l->name,b1,MAXNODESTR - 1);
06138       l->isremote = 0;
06139       l->chan = chan;
06140       l->connected = 1;
06141       l->hasconnected = 1;
06142       l->phonemode = phone_mode;
06143       ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
06144       ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
06145       /* allocate a pseudo-channel thru asterisk */
06146       l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
06147       if (!l->pchan)
06148       {
06149          fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
06150          pthread_exit(NULL);
06151       }
06152       ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
06153       ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
06154       /* make a conference for the tx */
06155       ci.chan = 0;
06156       ci.confno = myrpt->conf;
06157       ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
06158       /* first put the channel on the conference in proper mode */
06159       if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
06160       {
06161          ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
06162          pthread_exit(NULL);
06163       }
06164       ast_mutex_lock(&myrpt->lock);
06165       if (phone_mode > 1) l->lastrx = 1;
06166       /* insert at end of queue */
06167       insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
06168       ast_mutex_unlock(&myrpt->lock);
06169       if (chan->_state != AST_STATE_UP) {
06170          ast_answer(chan);
06171       }
06172       return AST_PBX_KEEPALIVE;
06173    }
06174    ast_mutex_lock(&myrpt->lock);
06175    /* if remote, error if anyone else already linked */
06176    if (myrpt->remoteon)
06177    {
06178       ast_mutex_unlock(&myrpt->lock);
06179       usleep(500000);
06180       if (myrpt->remoteon)
06181       {
06182          ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
06183          return -1;
06184       }     
06185       ast_mutex_lock(&myrpt->lock);
06186    }
06187    myrpt->remoteon = 1;
06188    if (ioperm(myrpt->iobase,1,1) == -1)
06189    {
06190       ast_mutex_unlock(&myrpt->lock);
06191       ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->iobase);
06192       return -1;
06193    }
06194    LOCAL_USER_ADD(u);
06195    tele = strchr(myrpt->rxchanname,'/');
06196    if (!tele)
06197    {
06198       fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
06199       ast_mutex_unlock(&myrpt->lock);
06200       pthread_exit(NULL);
06201    }
06202    *tele++ = 0;
06203    myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
06204    if (myrpt->rxchannel)
06205    {
06206       ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
06207       ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
06208       myrpt->rxchannel->whentohangup = 0;
06209       myrpt->rxchannel->appl = "Apprpt";
06210       myrpt->rxchannel->data = "(Link Rx)";
06211       if (option_verbose > 2)
06212          ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
06213             myrpt->rxchanname,tele,myrpt->rxchannel->name);
06214       ast_mutex_unlock(&myrpt->lock);
06215       ast_call(myrpt->rxchannel,tele,999);
06216       ast_mutex_lock(&myrpt->lock);
06217    }
06218    else
06219    {
06220       fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
06221       ast_mutex_unlock(&myrpt->lock);
06222       pthread_exit(NULL);
06223    }
06224    *--tele = '/';
06225    if (myrpt->txchanname)
06226    {
06227       tele = strchr(myrpt->txchanname,'/');
06228       if (!tele)
06229       {
06230          fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
06231          ast_mutex_unlock(&myrpt->lock);
06232          ast_hangup(myrpt->rxchannel);
06233          pthread_exit(NULL);
06234       }
06235       *tele++ = 0;
06236       myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
06237       if (myrpt->txchannel)
06238       {
06239          ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
06240          ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
06241          myrpt->txchannel->whentohangup = 0;
06242          myrpt->txchannel->appl = "Apprpt";
06243          myrpt->txchannel->data = "(Link Tx)";
06244          if (option_verbose > 2)
06245             ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
06246                myrpt->txchanname,tele,myrpt->txchannel->name);
06247          ast_mutex_unlock(&myrpt->lock);
06248          ast_call(myrpt->txchannel,tele,999);
06249          ast_mutex_lock(&myrpt->lock);
06250       }
06251       else
06252       {
06253          fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
06254          ast_mutex_unlock(&myrpt->lock);
06255          ast_hangup(myrpt->rxchannel);
06256          pthread_exit(NULL);
06257       }
06258       *--tele = '/';
06259    }
06260    else
06261    {
06262       myrpt->txchannel = myrpt->rxchannel;
06263    }
06264    myrpt->remoterx = 0;
06265    myrpt->remotetx = 0;
06266    myrpt->retxtimer = 0;
06267    myrpt->remoteon = 1;
06268    myrpt->dtmfidx = -1;
06269    myrpt->dtmfbuf[0] = 0;
06270    myrpt->dtmf_time_rem = 0;
06271    myrpt->hfscanmode = 0;
06272    myrpt->hfscanstatus = 0;
06273    ast_mutex_unlock(&myrpt->lock);
06274    setrem(myrpt); 
06275    ast_set_write_format(chan, AST_FORMAT_SLINEAR);
06276    ast_set_read_format(chan, AST_FORMAT_SLINEAR);
06277    /* if we are on 2w loop and are a remote, turn EC on */
06278    if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
06279    {
06280       i = 128;
06281       ioctl(myrpt->rxchannel->fds[0],ZT_ECHOCANCEL,&i);
06282    }
06283    if (chan->_state != AST_STATE_UP) {
06284       ast_answer(chan);
06285    }
06286 
06287    if (ioctl(myrpt->txchannel->fds[0],ZT_GET_PARAMS,&par) != -1)
06288    {
06289       if (par.rxisoffhook)
06290       {
06291          ast_indicate(chan,AST_CONTROL_RADIO_KEY);
06292          myrpt->remoterx = 1;
06293       }
06294    }
06295    n = 0;
06296    cs[n++] = chan;
06297    cs[n++] = myrpt->rxchannel;
06298    if (myrpt->rxchannel != myrpt->txchannel)
06299       cs[n++] = myrpt->txchannel;
06300    for(;;) 
06301    {
06302       if (ast_check_hangup(chan)) break;
06303       if (ast_check_hangup(myrpt->rxchannel)) break;
06304       ms = MSWAIT;
06305       who = ast_waitfor_n(cs,n,&ms);
06306       if (who == NULL) ms = 0;
06307       elap = MSWAIT - ms;
06308       if (!ms) continue;
06309       rem_totx = keyed;
06310       
06311       
06312       if ((!myrpt->remoterx) && (!myrpt->remotetx))
06313       {
06314          if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
06315          {
06316             myrpt->retxtimer = 0;
06317             ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
06318          }
06319       } else myrpt->retxtimer = 0;
06320       if (rem_totx && (!myrpt->remotetx)) /* Remote base radio TX key */
06321       {
06322          myrpt->remotetx = 1;
06323          ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
06324       }
06325       if ((!rem_totx) && myrpt->remotetx) /* Remote base radio TX unkey */
06326       {
06327          myrpt->remotetx = 0;
06328          ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
06329       }
06330 
06331       if(myrpt->tunerequest && (!strcmp(myrpt->remote, remote_rig_ft897))){ /* ft-897 specific for now... */
06332          myrpt->tunerequest = 0;
06333          set_mode_ft897(myrpt, REM_MODE_AM);
06334          simple_command_ft897(myrpt, 8);
06335          myrpt->remotetx = 0;
06336          ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
06337          if (!myrpt->remoterx)
06338             ast_indicate(chan, AST_CONTROL_RADIO_KEY);
06339          if(play_tone(chan, 800, 6000, 8192) == -1)
06340             break;
06341 
06342          rmt_telem_finish(myrpt,chan);
06343          set_mode_ft897(myrpt, 0x88);
06344          setrem(myrpt);
06345       }
06346    
06347       if (myrpt->hfscanmode){
06348          myrpt->scantimer -= elap;
06349          if(myrpt->scantimer <= 0){
06350             myrpt->scantimer = REM_SCANTIME;
06351             service_scan(myrpt);
06352          }
06353       }
06354 
06355 
06356       if (who == chan) /* if it was a read from incomming */
06357       {
06358          f = ast_read(chan);
06359          if (!f)
06360          {
06361             if (debug) printf("@@@@ link:Hung Up\n");
06362             break;
06363          }
06364          if (f->frametype == AST_FRAME_VOICE)
06365          {
06366             /* if not transmitting, zero-out audio */
06367             if (!myrpt->remotetx)
06368                memset(f->data,0,f->datalen);
06369             ast_write(myrpt->txchannel,f);
06370          }
06371          if (f->frametype == AST_FRAME_DTMF)
06372          {
06373             myrpt->remchannel = chan; /* Save copy of channel */
06374             if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1)
06375             {
06376                if (debug) printf("@@@@ rpt:Hung Up\n");
06377                ast_frfree(f);
06378                break;
06379             }
06380          }
06381          if (f->frametype == AST_FRAME_TEXT)
06382          {
06383             myrpt->remchannel = chan; /* Save copy of channel */
06384             if (handle_remote_data(myrpt,f->data) == -1)
06385             {
06386                if (debug) printf("@@@@ rpt:Hung Up\n");
06387                ast_frfree(f);
06388                break;
06389             }
06390          }
06391          if (f->frametype == AST_FRAME_CONTROL)
06392          {
06393             if (f->subclass == AST_CONTROL_HANGUP)
06394             {
06395                if (debug) printf("@@@@ rpt:Hung Up\n");
06396                ast_frfree(f);
06397                break;
06398             }
06399             /* if RX key */
06400             if (f->subclass == AST_CONTROL_RADIO_KEY)
06401             {
06402                if (debug) printf("@@@@ rx key\n");
06403                keyed = 1;
06404             }
06405             /* if RX un-key */
06406             if (f->subclass == AST_CONTROL_RADIO_UNKEY)
06407             {
06408                if (debug) printf("@@@@ rx un-key\n");
06409                keyed = 0;
06410             }
06411          }
06412          if (myrpt->hfscanstatus){
06413             myrpt->remchannel = chan; /* Save copy of channel */
06414             myrpt->remotetx = 0;
06415             ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
06416             if (!myrpt->remoterx)
06417             {
06418                ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
06419             }
06420             if(myrpt->hfscanstatus < 0) {
06421                if (myrpt->hfscanstatus == -1) {
06422                   if (ast_safe_sleep(myrpt->remchannel,1000) == -1) break;
06423                }
06424                sayfile(myrpt->remchannel, "rpt/stop");
06425             }
06426             else
06427             {
06428                saynum(myrpt->remchannel, myrpt->hfscanstatus );
06429             }  
06430             rmt_telem_finish(myrpt,myrpt->remchannel);
06431             myrpt->hfscanstatus = 0;
06432          }
06433          ast_frfree(f);
06434          continue;
06435       }
06436       if (who == myrpt->rxchannel) /* if it was a read from radio */
06437       {
06438          f = ast_read(myrpt->rxchannel);
06439          if (!f)
06440          {
06441             if (debug) printf("@@@@ link:Hung Up\n");
06442             break;
06443          }
06444          if (f->frametype == AST_FRAME_VOICE)
06445          {
06446             if ((myrpt->remote) && (myrpt->remotetx))
06447                memset(f->data,0,f->datalen);
06448              ast_write(chan,f);
06449          }
06450          else if (f->frametype == AST_FRAME_CONTROL)
06451          {
06452             if (f->subclass == AST_CONTROL_HANGUP)
06453             {
06454                if (debug) printf("@@@@ rpt:Hung Up\n");
06455                ast_frfree(f);
06456                break;
06457             }
06458             /* if RX key */
06459             if (f->subclass == AST_CONTROL_RADIO_KEY)
06460             {
06461                if (debug) printf("@@@@ remote rx key\n");
06462                if (!myrpt->remotetx)
06463                {
06464                   ast_indicate(chan,AST_CONTROL_RADIO_KEY);
06465                   myrpt->remoterx = 1;
06466                }
06467             }
06468             /* if RX un-key */
06469             if (f->subclass == AST_CONTROL_RADIO_UNKEY)
06470             {
06471                if (debug) printf("@@@@ remote rx un-key\n");
06472                if (!myrpt->remotetx) 
06473                {
06474                   ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
06475                   myrpt->remoterx = 0;
06476                }
06477             }
06478          }
06479          ast_frfree(f);
06480          continue;
06481       }
06482       if ((myrpt->rxchannel != myrpt->txchannel) && 
06483          (who == myrpt->txchannel)) /* do this cuz you have to */
06484       {
06485          f = ast_read(myrpt->txchannel);
06486          if (!f)
06487          {
06488             if (debug) printf("@@@@ link:Hung Up\n");
06489             break;
06490          }
06491          if (f->frametype == AST_FRAME_CONTROL)
06492          {
06493             if (f->subclass == AST_CONTROL_HANGUP)
06494             {
06495                if (debug) printf("@@@@ rpt:Hung Up\n");
06496                ast_frfree(f);
06497                break;
06498             }
06499          }
06500          ast_frfree(f);
06501          continue;
06502       }
06503 
06504    }
06505    ast_mutex_lock(&myrpt->lock);
06506    if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
06507    ast_hangup(myrpt->rxchannel);
06508    myrpt->hfscanmode = 0;
06509    myrpt->hfscanstatus = 0;
06510    myrpt->remoteon = 0;
06511    ast_mutex_unlock(&myrpt->lock);
06512    closerem(myrpt);
06513    LOCAL_USER_REMOVE(u);
06514    return res;
06515 }

static void* rpt_master ( void *  ignore  )  [static]

Definition at line 5607 of file app_rpt.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_init(), ast_pthread_create, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_true(), ast_variable_browse(), ast_variable_retrieve(), cfg, DEFAULT_IOBASE, ENDCHAR, FUNCCHAR, FUNCTIONS, HANGTIME, IDTIME, lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, n, name, ast_variable::name, ast_variable::next, NODES, POLITEID, REM_MEDPWR, REM_MODE_FM, REM_SIMPLEX, retrieve_astcfgint(), rpt_vars, and TOTIME.

Referenced by load_module().

05608 {
05609 char *this,*val;
05610 struct ast_variable *vp;
05611 int   i,j,n,longestnode;
05612 pthread_attr_t attr;
05613 
05614    /* start with blank config */
05615    memset(&rpt_vars,0,sizeof(rpt_vars));
05616 
05617    cfg = ast_config_load("rpt.conf");
05618    if (!cfg) {
05619       ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf.  Radio Repeater disabled.\n");
05620       pthread_exit(NULL);
05621    }
05622 
05623    /* go thru all the specified repeaters */
05624    this = NULL;
05625    n = 0;
05626    while((this = ast_category_browse(cfg,this)) != NULL)
05627    {
05628    
05629       for(i = 0 ; i < strlen(this) ; i++){
05630          if((this[i] < '0') || (this[i] > '9'))
05631             break;
05632       }
05633       if(i != strlen(this))
05634          continue; /* Not a node defn */
05635          
05636       ast_log(LOG_DEBUG,"Loading config for repeater %s\n",this);
05637       ast_mutex_init(&rpt_vars[n].lock);
05638       rpt_vars[n].tele.next = &rpt_vars[n].tele;
05639       rpt_vars[n].tele.prev = &rpt_vars[n].tele;
05640       rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
05641       rpt_vars[n].name = this;
05642       rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel");
05643       rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel");
05644       rpt_vars[n].ourcontext = ast_variable_retrieve(cfg,this,"context");
05645       if (!rpt_vars[n].ourcontext) rpt_vars[n].ourcontext = this;
05646       rpt_vars[n].ourcallerid = ast_variable_retrieve(cfg,this,"callerid");
05647       rpt_vars[n].acctcode = ast_variable_retrieve(cfg,this,"accountcode");
05648       rpt_vars[n].ident = ast_variable_retrieve(cfg,this,"idrecording");
05649       val = ast_variable_retrieve(cfg,this,"hangtime");
05650       if (val) rpt_vars[n].hangtime = atoi(val);
05651          else rpt_vars[n].hangtime = HANGTIME;
05652       val = ast_variable_retrieve(cfg,this,"totime");
05653       if (val) rpt_vars[n].totime = atoi(val);
05654          else rpt_vars[n].totime = TOTIME;
05655       
05656       rpt_vars[n].idtime = retrieve_astcfgint( this, "idtime", 60000, 2400000, IDTIME);   /* Enforce a min max */
05657       rpt_vars[n].politeid = retrieve_astcfgint( this, "politeid", 30000, 300000, POLITEID); /* Enforce a min max */
05658       rpt_vars[n].remote = ast_variable_retrieve(cfg,this,"remote");
05659       rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone");
05660       val = ast_variable_retrieve(cfg,this,"iobase");
05661       /* do not use atoi() here, we need to be able to have
05662          the input specified in hex or decimal so we use
05663          sscanf with a %i */
05664       if ((!val) || (sscanf(val,"%i",&rpt_vars[n].iobase) != 1))
05665          rpt_vars[n].iobase = DEFAULT_IOBASE;
05666       rpt_vars[n].simple = 0;
05667       rpt_vars[n].functions = ast_variable_retrieve(cfg,this,"functions");
05668       if (!rpt_vars[n].functions) 
05669       {
05670          rpt_vars[n].functions = FUNCTIONS;
05671          rpt_vars[n].simple = 1;
05672       }
05673       rpt_vars[n].link_functions = ast_variable_retrieve(cfg,this,"link_functions");
05674       if (!rpt_vars[n].link_functions) 
05675          rpt_vars[n].link_functions = rpt_vars[n].functions;
05676       rpt_vars[n].phone_functions = ast_variable_retrieve(cfg,this,"phone_functions");
05677       rpt_vars[n].dphone_functions = ast_variable_retrieve(cfg,this,"dphone_functions");
05678       val = ast_variable_retrieve(cfg,this,"funcchar");
05679       if (!val) rpt_vars[n].funcchar = FUNCCHAR; else 
05680          rpt_vars[n].funcchar = *val;     
05681       val = ast_variable_retrieve(cfg,this,"endchar");
05682       if (!val) rpt_vars[n].endchar = ENDCHAR; else 
05683          rpt_vars[n].endchar = *val;      
05684       val = ast_variable_retrieve(cfg,this,"nobusyout");
05685       if (val) rpt_vars[n].nobusyout = ast_true(val);
05686       rpt_vars[n].nodes = ast_variable_retrieve(cfg,this,"nodes");
05687       if (!rpt_vars[n].nodes) 
05688          rpt_vars[n].nodes = NODES;
05689       n++;
05690    }
05691    nrpts = n;
05692    ast_log(LOG_DEBUG, "Total of %d repeaters configured.\n",n);
05693    /* start em all */
05694    for(i = 0; i < n; i++)
05695    {
05696 
05697       /*
05698       * Go through the node list to determine the longest node
05699       */
05700       longestnode = 0;
05701 
05702       vp = ast_variable_browse(cfg, rpt_vars[i].nodes);
05703       
05704       while(vp){
05705          j = strlen(vp->name);
05706          if (j > longestnode)
05707             longestnode = j;
05708          vp = vp->next;
05709       }
05710 
05711 
05712       rpt_vars[i].longestnode = longestnode;
05713       
05714       /*
05715       * For this repeater, Determine the length of the longest function 
05716       */
05717       rpt_vars[i].longestfunc = 0;
05718       vp = ast_variable_browse(cfg, rpt_vars[i].functions);
05719       while(vp){
05720          j = strlen(vp->name);
05721          if (j > rpt_vars[i].longestfunc)
05722             rpt_vars[i].longestfunc = j;
05723          vp = vp->next;
05724       }
05725       /*
05726       * For this repeater, Determine the length of the longest function 
05727       */
05728       rpt_vars[i].link_longestfunc = 0;
05729       vp = ast_variable_browse(cfg, rpt_vars[i].link_functions);
05730       while(vp){
05731          j = strlen(vp->name);
05732          if (j > rpt_vars[i].link_longestfunc)
05733             rpt_vars[i].link_longestfunc = j;
05734          vp = vp->next;
05735       }
05736       rpt_vars[i].phone_longestfunc = 0;
05737       if (rpt_vars[i].phone_functions)
05738       {
05739          vp = ast_variable_browse(cfg, rpt_vars[i].phone_functions);
05740          while(vp){
05741             j = strlen(vp->name);
05742             if (j > rpt_vars[i].phone_longestfunc)
05743                rpt_vars[i].phone_longestfunc = j;
05744             vp = vp->next;
05745          }
05746       }
05747       rpt_vars[i].dphone_longestfunc = 0;
05748       if (rpt_vars[i].dphone_functions)
05749       {
05750          vp = ast_variable_browse(cfg, rpt_vars[i].dphone_functions);
05751          while(vp){
05752             j = strlen(vp->name);
05753             if (j > rpt_vars[i].dphone_longestfunc)
05754                rpt_vars[i].dphone_longestfunc = j;
05755             vp = vp->next;
05756          }
05757       }
05758       if (!rpt_vars[i].rxchanname)
05759       {
05760          ast_log(LOG_WARNING,"Did not specify rxchanname for node %s\n",rpt_vars[i].name);
05761          ast_config_destroy(cfg);
05762          pthread_exit(NULL);
05763       }
05764       /* if is a remote, dont start one for it */
05765       if (rpt_vars[i].remote)
05766       {
05767          strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
05768          strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
05769 
05770          strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
05771          rpt_vars[i].remmode = REM_MODE_FM;
05772          rpt_vars[i].offset = REM_SIMPLEX;
05773          rpt_vars[i].powerlevel = REM_MEDPWR;
05774          continue;
05775       }
05776       if (!rpt_vars[i].ident)
05777       {
05778          ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
05779          ast_config_destroy(cfg);
05780          pthread_exit(NULL);
05781       }
05782            pthread_attr_init(&attr);
05783            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05784       ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
05785    }
05786    usleep(500000);
05787    for(;;)
05788    {
05789       /* Now monitor each thread, and restart it if necessary */
05790       for(i = 0; i < n; i++)
05791       { 
05792          int rv;
05793          if (rpt_vars[i].remote) continue;
05794          if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP) 
05795             rv = -1;
05796          else
05797             rv = pthread_kill(rpt_vars[i].rpt_thread,0);
05798          if (rv)
05799          {
05800             if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
05801             {
05802                if(rpt_vars[i].threadrestarts >= 5)
05803                {
05804                   ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
05805                   exit(1); /* Stuck in a restart loop, kill Asterisk and start over */
05806                }
05807                else
05808                {
05809                   ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
05810                   rpt_vars[i].threadrestarts++;
05811                }
05812             }
05813             else
05814                rpt_vars[i].threadrestarts = 0;
05815 
05816             rpt_vars[i].lastthreadrestarttime = time(NULL);
05817                  pthread_attr_init(&attr);
05818                  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05819             ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
05820             ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
05821          }
05822 
05823       }
05824       usleep(2000000);
05825    }
05826    ast_config_destroy(cfg);
05827    pthread_exit(NULL);
05828 }

static void* rpt_tele_thread ( void *  this  )  [static]

Definition at line 965 of file app_rpt.c.

References ARB_ALPHA, AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_safe_sleep(), ast_say_character_str(), ast_say_digits(), ast_say_number(), ast_say_time(), ast_stopstream(), ast_strdupa, ast_streamfile(), ast_tonepair_start(), ast_variable_retrieve(), ast_waitstream(), cfg, rpt_tele::chan, COMPLETE, CONNECTED, rpt_link::connected, CONNFAIL, DLY_CALLTERM, DLY_ID, DLY_TELEM, DLY_UNKEY, ast_channel::fds, free, get_wait_interval(), ID, ID1, IDTALKOVER, rpt_link::isremote, ast_channel::language, LOG_WARNING, malloc, rpt_link::mode, rpt_tele::mode, rpt_tele::mylink, rpt_link::name, ast_channel::name, rpt_link::next, rpt_tele::next, rpt_tele::param, rpt_link::prev, PROC, REMALREADY, REMDISC, REMGO, REMNOTFOUND, REV_PATCH, rpt_tele::rpt, saycharstr(), sayfile(), STATS_TIME, STATS_VERSION, STATUS, strsep(), t, telem_any(), telem_lookup(), TERM, TEST_TONE, TIMEOUT, UNKEY, and wait_interval().

Referenced by rpt_telemetry().

00966 {
00967 ZT_CONFINFO ci;  /* conference info */
00968 int   res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
00969 struct   rpt_tele *mytele = (struct rpt_tele *)this;
00970 struct  rpt_tele *tlist;
00971 struct   rpt *myrpt;
00972 struct   rpt_link *l,*m,linkbase;
00973 struct   ast_channel *mychannel;
00974 int vmajor, vminor;
00975 char *p,*ct,*ct_copy,*ident, *nodename;
00976 time_t t;
00977 struct tm localtm;
00978 
00979 
00980    /* get a pointer to myrpt */
00981    myrpt = mytele->rpt;
00982 
00983    /* Snag copies of a few key myrpt variables */
00984    ast_mutex_lock(&myrpt->lock);
00985    nodename = ast_strdupa(myrpt->name);
00986    ident = ast_strdupa(myrpt->ident);
00987    ast_mutex_unlock(&myrpt->lock);
00988    
00989    
00990    /* allocate a pseudo-channel thru asterisk */
00991    mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
00992    if (!mychannel)
00993    {
00994       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
00995       ast_mutex_lock(&myrpt->lock);
00996       remque((struct qelem *)mytele);
00997       ast_mutex_unlock(&myrpt->lock);
00998       free(mytele);     
00999       pthread_exit(NULL);
01000    }
01001    ast_mutex_lock(&myrpt->lock);
01002    mytele->chan = mychannel; /* Save a copy of the channel so we can access it externally if need be */
01003    ast_mutex_unlock(&myrpt->lock);
01004    
01005    /* make a conference for the tx */
01006    ci.chan = 0;
01007    /* If there's an ID queued, only connect the ID audio to the local tx conference so 
01008       linked systems can't hear it */
01009    ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY)) ?
01010        myrpt->txconf : myrpt->conf);
01011    ci.confmode = ZT_CONF_CONFANN;
01012    /* first put the channel on the conference in announce mode */
01013    if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
01014    {
01015       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01016       ast_mutex_lock(&myrpt->lock);
01017       remque((struct qelem *)mytele);
01018       ast_mutex_unlock(&myrpt->lock);
01019       free(mytele);     
01020       ast_hangup(mychannel);
01021       pthread_exit(NULL);
01022    }
01023    ast_stopstream(mychannel);
01024    switch(mytele->mode)
01025    {
01026        case ID:
01027        case ID1:
01028       /* wait a bit */
01029       wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
01030       res = telem_any(mychannel, ident); 
01031       imdone=1;
01032    
01033       break;
01034       
01035       
01036        case IDTALKOVER:
01037          p = ast_variable_retrieve(cfg, nodename, "idtalkover");
01038          if(p)
01039          res = telem_any(mychannel, p); 
01040       imdone=1;   
01041          break;
01042             
01043        case PROC:
01044       /* wait a little bit longer */
01045       wait_interval(myrpt, DLY_TELEM, mychannel);
01046       res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
01047       break;
01048        case TERM:
01049       /* wait a little bit longer */
01050       wait_interval(myrpt, DLY_CALLTERM, mychannel);
01051       res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
01052       break;
01053        case COMPLETE:
01054       /* wait a little bit */
01055       wait_interval(myrpt, DLY_TELEM, mychannel);
01056       res = telem_lookup(mychannel, myrpt->name, "functcomplete");
01057       break;
01058        case UNKEY:
01059 
01060       /*
01061       * Reset the Unkey to CT timer
01062       */
01063 
01064       x = get_wait_interval(myrpt, DLY_UNKEY);
01065       ast_mutex_lock(&myrpt->lock);
01066       myrpt->unkeytocttimer = x; /* Must be protected as it is changed below */
01067       ast_mutex_unlock(&myrpt->lock);
01068 
01069       /*
01070       * If there's one already queued, don't do another
01071       */
01072 
01073       tlist = myrpt->tele.next;
01074       unkeys_queued = 0;
01075                 if (tlist != &myrpt->tele)
01076                 {
01077                         ast_mutex_lock(&myrpt->lock);
01078                         while(tlist != &myrpt->tele){
01079                                 if (tlist->mode == UNKEY) unkeys_queued++;
01080                                 tlist = tlist->next;
01081                         }
01082                         ast_mutex_unlock(&myrpt->lock);
01083       }
01084       if( unkeys_queued > 1){
01085          imdone = 1;
01086          break;
01087       }
01088 
01089       /* Wait for the telemetry timer to expire */
01090       /* Periodically check the timer since it can be re-initialized above */
01091 
01092       while(myrpt->unkeytocttimer)
01093       {
01094          int ctint;
01095          if(myrpt->unkeytocttimer > 100)
01096             ctint = 100;
01097          else
01098             ctint = myrpt->unkeytocttimer;
01099          ast_safe_sleep(mychannel, ctint);
01100          ast_mutex_lock(&myrpt->lock);
01101          if(myrpt->unkeytocttimer < ctint)
01102             myrpt->unkeytocttimer = 0;
01103          else
01104             myrpt->unkeytocttimer -= ctint;
01105          ast_mutex_unlock(&myrpt->lock);
01106       }
01107    
01108 
01109       /*
01110       * Now, the carrier on the rptr rx should be gone. 
01111       * If it re-appeared, then forget about sending the CT
01112       */
01113       if(myrpt->keyed){
01114          imdone = 1;
01115          break;
01116       }
01117          
01118       haslink = 0;
01119       hastx = 0;
01120       hasremote = 0;    
01121       l = myrpt->links.next;
01122       if (l != &myrpt->links)
01123       {
01124          ast_mutex_lock(&myrpt->lock);
01125          while(l != &myrpt->links)
01126          {
01127             if (l->name[0] == '0')
01128             {
01129                l = l->next;
01130                continue;
01131             }
01132             haslink = 1;
01133             if (l->mode) {
01134                hastx++;
01135                if (l->isremote) hasremote++;
01136             }
01137             l = l->next;
01138          }
01139          ast_mutex_unlock(&myrpt->lock);
01140       }
01141       if (haslink)
01142       {
01143 
01144          res = telem_lookup(mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
01145          if(res)
01146             ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
01147          
01148       
01149          /* if in remote cmd mode, indicate it */
01150          if (myrpt->cmdnode[0])
01151          {
01152             ast_safe_sleep(mychannel,200);
01153             res = telem_lookup(mychannel, myrpt->name, "cmdmode");
01154             if(res)
01155                ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
01156             ast_stopstream(mychannel);
01157          }
01158       }
01159       else if((ct = ast_variable_retrieve(cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */
01160          ct_copy = ast_strdupa(ct);
01161          res = telem_lookup(mychannel, myrpt->name, ct_copy);
01162          if(res)
01163             ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);     
01164       }  
01165          
01166       if (hasremote && (!myrpt->cmdnode[0]))
01167       {
01168          /* set for all to hear */
01169          ci.chan = 0;
01170          ci.confno = myrpt->conf;
01171          ci.confmode = ZT_CONF_CONFANN;
01172          /* first put the channel on the conference in announce mode */
01173          if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
01174          {
01175             ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01176             ast_mutex_lock(&myrpt->lock);
01177             remque((struct qelem *)mytele);
01178             ast_mutex_unlock(&myrpt->lock);
01179             free(mytele);     
01180             ast_hangup(mychannel);
01181             pthread_exit(NULL);
01182          }
01183          if((ct = ast_variable_retrieve(cfg, nodename, "remotect"))){ /* Unlinked Courtesy Tone */
01184             ast_safe_sleep(mychannel,200);
01185             ct_copy = ast_strdupa(ct);
01186             res = telem_lookup(mychannel, myrpt->name, ct_copy);
01187             if(res)
01188                ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);     
01189          }  
01190       }
01191       imdone = 1;
01192       break;
01193        case REMDISC:
01194       /* wait a little bit */
01195       wait_interval(myrpt, DLY_TELEM, mychannel);
01196       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01197       if (!res) 
01198          res = ast_waitstream(mychannel, "");
01199       else
01200           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01201       ast_stopstream(mychannel);
01202       ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
01203       res = ast_streamfile(mychannel, ((mytele->mylink.connected) ? 
01204          "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
01205       break;
01206        case REMALREADY:
01207       /* wait a little bit */
01208       wait_interval(myrpt, DLY_TELEM, mychannel);
01209       res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
01210       break;
01211        case REMNOTFOUND:
01212       /* wait a little bit */
01213       wait_interval(myrpt, DLY_TELEM, mychannel);
01214       res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
01215       break;
01216        case REMGO:
01217       /* wait a little bit */
01218       wait_interval(myrpt, DLY_TELEM, mychannel);
01219       res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
01220       break;
01221        case CONNECTED:
01222       /* wait a little bit */
01223       wait_interval(myrpt, DLY_TELEM,  mychannel);
01224       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01225       if (!res) 
01226          res = ast_waitstream(mychannel, "");
01227       else
01228           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01229       ast_stopstream(mychannel);
01230       ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
01231       res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
01232       break;
01233        case CONNFAIL:
01234       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01235       if (!res) 
01236          res = ast_waitstream(mychannel, "");
01237       else
01238           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01239       ast_stopstream(mychannel);
01240       ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
01241       res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
01242       break;
01243        case STATUS:
01244       /* wait a little bit */
01245       wait_interval(myrpt, DLY_TELEM, mychannel);
01246       hastx = 0;
01247       linkbase.next = &linkbase;
01248       linkbase.prev = &linkbase;
01249       ast_mutex_lock(&myrpt->lock);
01250       /* make our own list of links */
01251       l = myrpt->links.next;
01252       while(l != &myrpt->links)
01253       {
01254          if (l->name[0] == '0')
01255          {
01256             l = l->next;
01257             continue;
01258          }
01259          m = malloc(sizeof(struct rpt_link));
01260          if (!m)
01261          {
01262             ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
01263             ast_mutex_lock(&myrpt->lock);
01264             remque((struct qelem *)mytele);
01265             ast_mutex_unlock(&myrpt->lock);
01266             free(mytele);     
01267             ast_hangup(mychannel);
01268             pthread_exit(NULL);
01269          }
01270          memcpy(m,l,sizeof(struct rpt_link));
01271          m->next = m->prev = NULL;
01272          insque((struct qelem *)m,(struct qelem *)linkbase.next);
01273          l = l->next;
01274       }
01275       ast_mutex_unlock(&myrpt->lock);
01276       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01277       if (!res) 
01278          res = ast_waitstream(mychannel, "");
01279       else
01280           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01281       ast_stopstream(mychannel);
01282       ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
01283       if (!res) 
01284          res = ast_waitstream(mychannel, "");
01285       else
01286           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01287       ast_stopstream(mychannel);
01288       if (myrpt->callmode)
01289       {
01290          hastx = 1;
01291          res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
01292          if (!res) 
01293             res = ast_waitstream(mychannel, "");
01294          else
01295              ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01296          ast_stopstream(mychannel);
01297       }
01298       l = linkbase.next;
01299       while(l != &linkbase)
01300       {
01301          hastx = 1;
01302          res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01303          if (!res) 
01304             res = ast_waitstream(mychannel, "");
01305          else
01306             ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01307          ast_stopstream(mychannel);
01308          ast_say_character_str(mychannel,l->name,NULL,mychannel->language);
01309          if (!res) 
01310             res = ast_waitstream(mychannel, "");
01311          else
01312              ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01313          ast_stopstream(mychannel);
01314          res = ast_streamfile(mychannel, ((l->mode) ? 
01315             "rpt/tranceive" : "rpt/monitor"), mychannel->language);
01316          if (!res) 
01317             res = ast_waitstream(mychannel, "");
01318          else
01319             ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01320          ast_stopstream(mychannel);
01321          l = l->next;
01322       }        
01323       if (!hastx)
01324       {
01325          res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
01326          if (!res) 
01327             res = ast_waitstream(mychannel, "");
01328          else
01329              ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01330          ast_stopstream(mychannel);
01331       }
01332       /* destroy our local link queue */
01333       l = linkbase.next;
01334       while(l != &linkbase)
01335       {
01336          m = l;
01337          l = l->next;
01338          remque((struct qelem *)m);
01339          free(m);
01340       }        
01341       imdone = 1;
01342       break;
01343        case TIMEOUT:
01344       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01345       if (!res) 
01346          res = ast_waitstream(mychannel, "");
01347       else
01348           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01349       ast_stopstream(mychannel);
01350       ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
01351       res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
01352       break;
01353       
01354        case STATS_TIME:
01355          wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
01356       t = time(NULL);
01357       localtime_r(&t, &localtm);
01358       /* Say the phase of the day is before the time */
01359       if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
01360          p = "rpt/goodmorning";
01361       else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
01362          p = "rpt/goodafternoon";
01363       else
01364          p = "rpt/goodevening";
01365       if (sayfile(mychannel,p) == -1)
01366       {
01367          imdone = 1;
01368          break;
01369       }
01370       /* Say the time is ... */     
01371       if (sayfile(mychannel,"rpt/thetimeis") == -1)
01372       {
01373          imdone = 1;
01374          break;
01375       }
01376       /* Say the time */            
01377          res = ast_say_time(mychannel, t, "", mychannel->language);
01378       if (!res) 
01379          res = ast_waitstream(mychannel, "");
01380       ast_stopstream(mychannel);    
01381       imdone = 1;
01382          break;
01383        case STATS_VERSION:
01384       p = strstr(tdesc, "version"); 
01385       if(!p)
01386          break;   
01387       if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
01388          break;
01389          wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
01390       /* Say "version" */
01391       if (sayfile(mychannel,"rpt/version") == -1)
01392       {
01393          imdone = 1;
01394          break;
01395       }
01396       if(!res) /* Say "X" */
01397          ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
01398       if (!res) 
01399          res = ast_waitstream(mychannel, "");
01400       ast_stopstream(mychannel); 
01401       if (saycharstr(mychannel,".") == -1)
01402       {
01403          imdone = 1;
01404          break;
01405       }
01406       if(!res) /* Say "Y" */
01407          ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
01408       if (!res){
01409          res = ast_waitstream(mychannel, "");
01410          ast_stopstream(mychannel);
01411       }  
01412       else
01413           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01414       imdone = 1;
01415          break;
01416        case ARB_ALPHA:
01417          wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
01418          if(mytele->param)
01419             saycharstr(mychannel, mytele->param);
01420          imdone = 1;
01421       break;
01422        case REV_PATCH:
01423          wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
01424          if(mytele->param) {
01425 
01426          /* Parts of this section taken from app_parkandannounce */
01427          char *tpl_working, *tpl_current;
01428          char *tmp[100], *myparm;
01429          int looptemp=0,i=0, dres = 0;
01430    
01431 
01432          tpl_working = strdupa(mytele->param);
01433          myparm = strsep(&tpl_working,",");
01434          tpl_current=strsep(&tpl_working, ":");
01435 
01436          while(tpl_current && looptemp < sizeof(tmp)) {
01437             tmp[looptemp]=tpl_current;
01438             looptemp++;
01439             tpl_current=strsep(&tpl_working,":");
01440          }
01441 
01442          for(i=0; i<looptemp; i++) {
01443             if(!strcmp(tmp[i], "PARKED")) {
01444                ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
01445             } else if(!strcmp(tmp[i], "NODE")) {
01446                ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
01447             } else {
01448                dres = ast_streamfile(mychannel, tmp[i], mychannel->language);
01449                if(!dres) {
01450                   dres = ast_waitstream(mychannel, "");
01451                } else {
01452                   ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name);
01453                   dres = 0;
01454                }
01455             }
01456          }
01457       }
01458          imdone = 1;
01459       break;
01460        case TEST_TONE:
01461       imdone = 1;
01462       myrpt->stopgen = 0;
01463            if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0))) 
01464          break;
01465            while(mychannel->generatordata && (!myrpt->stopgen)) {
01466          if (ast_safe_sleep(mychannel,1)) break;
01467             imdone = 1;
01468          }
01469       break;
01470        default:
01471          break;
01472    }
01473    myrpt->stopgen = 0;
01474    if (!imdone)
01475    {
01476       if (!res) 
01477          res = ast_waitstream(mychannel, "");
01478       else {
01479          ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01480          res = 0;
01481       }
01482    }
01483    ast_stopstream(mychannel);
01484    ast_mutex_lock(&myrpt->lock);
01485    remque((struct qelem *)mytele);
01486    ast_mutex_unlock(&myrpt->lock);
01487    free(mytele);     
01488    ast_hangup(mychannel);
01489    pthread_exit(NULL);
01490 }

static void rpt_telemetry ( struct rpt myrpt,
int  mode,
void *  data 
) [static]

Definition at line 1492 of file app_rpt.c.

References ARB_ALPHA, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, CONNECTED, CONNFAIL, rpt::lock, LOG_WARNING, malloc, rpt_tele::next, REMDISC, REV_PATCH, rpt_tele_thread(), rpt::tele, and TELEPARAMSIZE.

Referenced by function_autopatchdn(), function_cop(), function_ilink(), function_status(), handle_link_data(), handle_link_phone_dtmf(), rpt(), and rpt_exec().

01493 {
01494 struct rpt_tele *tele;
01495 struct rpt_link *mylink = (struct rpt_link *) data;
01496 pthread_attr_t attr;
01497 
01498    tele = malloc(sizeof(struct rpt_tele));
01499    if (!tele)
01500    {
01501       ast_log(LOG_WARNING, "Unable to allocate memory\n");
01502       pthread_exit(NULL);
01503       return;
01504    }
01505    /* zero it out */
01506    memset((char *)tele,0,sizeof(struct rpt_tele));
01507    tele->rpt = myrpt;
01508    tele->mode = mode;
01509    ast_mutex_lock(&myrpt->lock);
01510    if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED)){
01511       memset(&tele->mylink,0,sizeof(struct rpt_link));
01512       if (mylink){
01513          memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
01514       }
01515    }
01516    else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) {
01517       strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
01518       tele->param[TELEPARAMSIZE - 1] = 0;
01519    }
01520    insque((struct qelem *)tele,(struct qelem *)myrpt->tele.next); 
01521    ast_mutex_unlock(&myrpt->lock);
01522         pthread_attr_init(&attr);
01523         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01524    ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
01525    return;
01526 }

static int saycharstr ( struct ast_channel mychannel,
char *  str 
) [static]

Definition at line 748 of file app_rpt.c.

References ast_log(), ast_say_character_str(), ast_stopstream(), ast_waitstream(), ast_channel::language, LOG_WARNING, and ast_channel::name.

Referenced by function_remote(), rmt_saycharstr(), and rpt_tele_thread().

00749 {
00750 int   res;
00751 
00752    res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
00753    if (!res) 
00754       res = ast_waitstream(mychannel, "");
00755    else
00756        ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
00757    ast_stopstream(mychannel);
00758    return res;
00759 }

static int sayfile ( struct ast_channel mychannel,
char *  fname 
) [static]

Definition at line 735 of file app_rpt.c.

References ast_log(), ast_stopstream(), ast_streamfile(), ast_waitstream(), ast_channel::language, LOG_WARNING, and ast_channel::name.

Referenced by function_remote(), rmt_sayfile(), rpt_tele_thread(), and telem_any().

00736 {
00737 int   res;
00738 
00739    res = ast_streamfile(mychannel, fname, mychannel->language);
00740    if (!res) 
00741       res = ast_waitstream(mychannel, "");
00742    else
00743        ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
00744    ast_stopstream(mychannel);
00745    return res;
00746 }

static int saynum ( struct ast_channel mychannel,
int  num 
) [static]

Definition at line 761 of file app_rpt.c.

References ast_log(), ast_say_number(), ast_stopstream(), ast_waitstream(), ast_channel::language, LOG_WARNING, and ast_channel::name.

Referenced by function_remote().

00762 {
00763    int res;
00764    res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
00765    if(!res)
00766       res = ast_waitstream(mychannel, "");
00767    else
00768       ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
00769    ast_stopstream(mychannel);
00770    return res;
00771 }

static void send_link_dtmf ( struct rpt myrpt,
char  c 
) [static]

Definition at line 1720 of file app_rpt.c.

References AST_FRAME_TEXT, ast_write(), rpt_link::chan, rpt::cmdnode, ast_frame::data, ast_frame::datalen, rpt::dtmfidx, ast_frame::frametype, rpt::links, ast_frame::mallocd, rpt_link::name, rpt::name, rpt_link::next, ast_frame::offset, ast_frame::samples, strdup, and ast_frame::subclass.

Referenced by handle_link_phone_dtmf(), and rpt().

01721 {
01722 char  str[300];
01723 struct   ast_frame wf;
01724 struct   rpt_link *l;
01725 
01726    snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
01727    wf.frametype = AST_FRAME_TEXT;
01728    wf.subclass = 0;
01729    wf.offset = 0;
01730    wf.mallocd = 1;
01731    wf.datalen = strlen(str) + 1;
01732    wf.samples = 0;
01733    l = myrpt->links.next;
01734    /* first, see if our dude is there */
01735    while(l != &myrpt->links)
01736    {
01737       if (l->name[0] == '0') 
01738       {
01739          l = l->next;
01740          continue;
01741       }
01742       /* if we found it, write it and were done */
01743       if (!strcmp(l->name,myrpt->cmdnode))
01744       {
01745          wf.data = strdup(str);
01746          if (l->chan) ast_write(l->chan,&wf);
01747          return;
01748       }
01749       l = l->next;
01750    }
01751    l = myrpt->links.next;
01752    /* if not, give it to everyone */
01753    while(l != &myrpt->links)
01754    {
01755       wf.data = strdup(str);
01756       if (l->chan) ast_write(l->chan,&wf);
01757       l = l->next;
01758    }
01759    return;
01760 }

static int send_morse ( struct ast_channel chan,
char *  string,
int  speed,
int  freq,
int  amplitude 
) [static]

Definition at line 521 of file app_rpt.c.

References ast_safe_sleep(), ast_stopstream(), ast_waitstream(), morse_bits::ddcomb, ast_channel::fds, morse_bits::len, play_silence(), and play_tone().

Referenced by telem_any().

00522 {
00523 
00524 static struct morse_bits mbits[] = {
00525       {0, 0}, /* SPACE */
00526       {0, 0}, 
00527       {6, 18},/* " */
00528       {0, 0},
00529       {7, 72},/* $ */
00530       {0, 0},
00531       {0, 0},
00532       {6, 30},/* ' */
00533       {5, 13},/* ( */
00534       {6, 29},/* ) */
00535       {0, 0},
00536       {5, 10},/* + */
00537       {6, 51},/* , */
00538       {6, 33},/* - */
00539       {6, 42},/* . */
00540       {5, 9}, /* / */
00541       {5, 31},/* 0 */
00542       {5, 30},/* 1 */
00543       {5, 28},/* 2 */
00544       {5, 24},/* 3 */
00545       {5, 16},/* 4 */
00546       {5, 0}, /* 5 */
00547       {5, 1}, /* 6 */
00548       {5, 3}, /* 7 */
00549       {5, 7}, /* 8 */
00550       {5, 15},/* 9 */
00551       {6, 7}, /* : */
00552       {6, 21},/* ; */
00553       {0, 0},
00554       {5, 33},/* = */
00555       {0, 0},
00556       {6, 12},/* ? */
00557       {0, 0},
00558          {2, 2}, /* A */
00559       {4, 1}, /* B */
00560       {4, 5}, /* C */
00561       {3, 1}, /* D */
00562       {1, 0}, /* E */
00563       {4, 4}, /* F */
00564       {3, 3}, /* G */
00565       {4, 0}, /* H */
00566       {2, 0}, /* I */
00567       {4, 14},/* J */
00568       {3, 5}, /* K */
00569       {4, 2}, /* L */
00570       {2, 3}, /* M */
00571       {2, 1}, /* N */
00572       {3, 7}, /* O */
00573       {4, 6}, /* P */
00574       {4, 11},/* Q */
00575       {3, 2}, /* R */
00576       {3, 0}, /* S */
00577       {1, 1}, /* T */
00578       {3, 4}, /* U */
00579       {4, 8}, /* V */
00580       {3, 6}, /* W */
00581       {4, 9}, /* X */
00582       {4, 13},/* Y */
00583       {4, 3}  /* Z */
00584    };
00585 
00586 
00587    int dottime;
00588    int dashtime;
00589    int intralettertime;
00590    int interlettertime;
00591    int interwordtime;
00592    int len, ddcomb;
00593    int res;
00594    int c;
00595    int i;
00596    int flags;
00597          
00598    res = 0;
00599    
00600    /* Approximate the dot time from the speed arg. */
00601    
00602    dottime = 900/speed;
00603    
00604    /* Establish timing releationships */
00605    
00606    dashtime = 3 * dottime;
00607    intralettertime = dottime;
00608    interlettertime = dottime * 4 ;
00609    interwordtime = dottime * 7;
00610    
00611    for(;(*string) && (!res); string++){
00612    
00613       c = *string;
00614       
00615       /* Convert lower case to upper case */
00616       
00617       if((c >= 'a') && (c <= 'z'))
00618          c -= 0x20;
00619       
00620       /* Can't deal with any char code greater than Z, skip it */
00621       
00622       if(c  > 'Z')
00623          continue;
00624       
00625       /* If space char, wait the inter word time */
00626                
00627       if(c == ' '){
00628          if(!res)
00629             res = play_silence(chan, interwordtime);
00630          continue;
00631       }
00632       
00633       /* Subtract out control char offset to match our table */
00634       
00635       c -= 0x20;
00636       
00637       /* Get the character data */
00638       
00639       len = mbits[c].len;
00640       ddcomb = mbits[c].ddcomb;
00641       
00642       /* Send the character */
00643       
00644       for(; len ; len--){
00645          if(!res)
00646             res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
00647          if(!res)
00648             res = play_silence(chan, intralettertime);
00649          ddcomb >>= 1;
00650       }
00651       
00652       /* Wait the interletter time */
00653       
00654       if(!res)
00655          res = play_silence(chan, interlettertime - intralettertime);
00656    }
00657    
00658    /* Wait for all the frames to be sent */
00659    
00660    if (!res) 
00661       res = ast_waitstream(chan, "");
00662    ast_stopstream(chan);
00663    
00664    /*
00665    * Wait for the zaptel driver to physically write the tone blocks to the hardware
00666    */
00667 
00668    for(i = 0; i < 20 ; i++){
00669       flags =  ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT; 
00670       res = ioctl(chan->fds[0], ZT_IOMUX, &flags);
00671       if(flags & ZT_IOMUX_WRITEEMPTY)
00672          break;
00673       if( ast_safe_sleep(chan, 50)){
00674          res = -1;
00675          break;
00676       }
00677    }
00678 
00679    
00680    return res;
00681 }

static int send_tone_telemetry ( struct ast_channel chan,
char *  tonestring 
) [static]

Definition at line 683 of file app_rpt.c.

References ast_safe_sleep(), ast_stopstream(), ast_strdupa, ast_waitstream(), ast_channel::fds, play_tone_pair(), and strsep().

Referenced by telem_any().

00684 {
00685    char *stringp;
00686    char *tonesubset;
00687    int f1,f2;
00688    int duration;
00689    int amplitude;
00690    int res;
00691    int i;
00692    int flags;
00693    
00694    res = 0;
00695    
00696    stringp = ast_strdupa(tonestring);
00697 
00698    for(;tonestring;){
00699       tonesubset = strsep(&stringp,")");
00700       if(!tonesubset)
00701          break;
00702       if(sscanf(tonesubset,"(%d,%d,%d,%d", &f1, &f2, &duration, &amplitude) != 4)
00703          break;
00704       res = play_tone_pair(chan, f1, f2, duration, amplitude);
00705       if(res)
00706          break;
00707    }
00708    if(!res)
00709       res = play_tone_pair(chan, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */
00710    
00711    if (!res) 
00712       res = ast_waitstream(chan, "");
00713    ast_stopstream(chan);
00714 
00715    /*
00716    * Wait for the zaptel driver to physically write the tone blocks to the hardware
00717    */
00718 
00719    for(i = 0; i < 20 ; i++){
00720       flags =  ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT; 
00721       res = ioctl(chan->fds[0], ZT_IOMUX, &flags);
00722       if(flags & ZT_IOMUX_WRITEEMPTY)
00723          break;
00724       if( ast_safe_sleep(chan, 50)){
00725          res = -1;
00726          break;
00727       }
00728    }
00729       
00730    return res;
00731       
00732 }

static int serial_remote_io ( struct rpt myrpt,
char *  txbuf,
int  txbytes,
char *  rxbuf,
int  rxmaxbytes,
int  asciiflag 
) [static]

Definition at line 2826 of file app_rpt.c.

References ast_channel::fds, and rpt::rxchannel.

Referenced by set_ctcss_freq_ft897(), set_ctcss_mode_ft897(), set_freq_ft897(), set_mode_ft897(), set_offset_ft897(), and simple_command_ft897().

02828 {
02829    int i;
02830    struct zt_radio_param prm;
02831 
02832    if(debug){
02833       printf("String output was: ");
02834       for(i = 0; i < txbytes; i++)
02835          printf("%02X ", (unsigned char ) txbuf[i]);
02836       printf("\n");
02837    }
02838 
02839         prm.radpar = ZT_RADPAR_REMMODE;
02840         if (asciiflag)  prm.data = ZT_RADPAR_REM_SERIAL_ASCII;
02841         else prm.data = ZT_RADPAR_REM_SERIAL;
02842    if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
02843         prm.radpar = ZT_RADPAR_REMCOMMAND;
02844         prm.data = rxmaxbytes;
02845         memcpy(prm.buf,txbuf,txbytes);
02846         prm.index = txbytes;
02847    if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
02848         if (rxbuf)
02849         {
02850                 *rxbuf = 0;
02851                 memcpy(rxbuf,prm.buf,prm.index);
02852         }
02853         return(prm.index);
02854 }

static int service_scan ( struct rpt myrpt  )  [static]

Definition at line 3485 of file app_rpt.c.

References rpt::freq, HF_SCAN_DOWN_FAST, HF_SCAN_DOWN_QUICK, HF_SCAN_DOWN_SLOW, HF_SCAN_UP_FAST, HF_SCAN_UP_QUICK, HF_SCAN_UP_SLOW, rpt::hfscanmode, rpt::hfscanstatus, MAXREMSTR, multimode_bump_freq(), split_freq(), and stop_scan().

03486 {
03487    int res, interval;
03488    char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
03489 
03490    switch(myrpt->hfscanmode){
03491 
03492       case HF_SCAN_DOWN_SLOW:
03493          interval = -10; /* 100Hz /sec */
03494          break;
03495 
03496       case HF_SCAN_DOWN_QUICK:
03497          interval = -50; /* 500Hz /sec */
03498          break;
03499 
03500       case HF_SCAN_DOWN_FAST:
03501          interval = -200; /* 2KHz /sec */
03502          break;
03503 
03504       case HF_SCAN_UP_SLOW:
03505          interval = 10; /* 100Hz /sec */
03506          break;
03507 
03508       case HF_SCAN_UP_QUICK:
03509          interval = 50; /* 500 Hz/sec */
03510          break;
03511 
03512       case HF_SCAN_UP_FAST:
03513          interval = 200; /* 2KHz /sec */
03514          break;
03515 
03516       default:
03517          myrpt->hfscanmode = 0; /* Huh? */
03518          return -1;
03519    }
03520 
03521    res = split_freq(mhz, decimals, myrpt->freq);
03522       
03523    if(!res){
03524       k100 =decimals[0];
03525       k10 = decimals[1];
03526       res = multimode_bump_freq(myrpt, interval);
03527    }
03528 
03529    if(!res)
03530       res = split_freq(mhz, decimals, myrpt->freq);
03531 
03532 
03533    if(res){
03534       stop_scan(myrpt,1);
03535       return -1;
03536    }
03537 
03538    /* Announce 10KHz boundaries */
03539    if(k10 != decimals[1]){
03540       int myhund = (interval < 0) ? k100 : decimals[0];
03541       int myten = (interval < 0) ? k10 : decimals[1];
03542       myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
03543    }
03544    return res;
03545 
03546 }

static int set_ctcss_freq_ft897 ( struct rpt myrpt,
char *  txtone,
char *  rxtone 
) [static]

Definition at line 3267 of file app_rpt.c.

References MAXREMSTR, serial_remote_io(), and split_ctcss_freq().

Referenced by set_ft897().

03268 {
03269    unsigned char cmdstr[5];
03270    char hertz[MAXREMSTR],decimal[MAXREMSTR];
03271    int h,d; 
03272 
03273    memset(cmdstr, 0, 5);
03274 
03275    if(split_ctcss_freq(hertz, decimal, txtone))
03276       return -1; 
03277 
03278    h = atoi(hertz);
03279    d = atoi(decimal);
03280    
03281    cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
03282    cmdstr[1] = ((h % 10) << 4) + (d % 10);
03283    
03284    if(rxtone){
03285    
03286       if(split_ctcss_freq(hertz, decimal, rxtone))
03287          return -1; 
03288 
03289       h = atoi(hertz);
03290       d = atoi(decimal);
03291    
03292       cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
03293       cmdstr[3] = ((h % 10) << 4) + (d % 10);
03294    }
03295    cmdstr[4] = 0x0B; 
03296 
03297    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03298 }  

static int set_ctcss_mode_ft897 ( struct rpt myrpt,
char  txplon,
char  rxplon 
) [static]

Definition at line 3244 of file app_rpt.c.

References serial_remote_io().

Referenced by set_ft897().

03245 {
03246    unsigned char cmdstr[5];
03247    
03248    memset(cmdstr, 0, 5);
03249    
03250    if(rxplon && txplon)
03251       cmdstr[0] = 0x2A; /* Encode and Decode */
03252    else if (!rxplon && txplon)
03253       cmdstr[0] = 0x4A; /* Encode only */
03254    else if (rxplon && !txplon)
03255       cmdstr[0] = 0x3A; /* Encode only */
03256    else
03257       cmdstr[0] = 0x8A; /* OFF */
03258 
03259    cmdstr[4] = 0x0A; 
03260 
03261    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03262 }

static int set_freq_ft897 ( struct rpt myrpt,
char *  newfreq 
) [static]

Definition at line 3136 of file app_rpt.c.

References MAXREMSTR, serial_remote_io(), and split_freq().

Referenced by multimode_bump_freq_ft897(), and set_ft897().

03137 {
03138    char mhz[MAXREMSTR];
03139    char decimals[MAXREMSTR];
03140    unsigned char cmdstr[5];
03141    int fd,m,d;
03142 
03143    fd = 0;
03144    if(debug) 
03145       printf("New frequency: %s\n",newfreq);
03146 
03147    if(split_freq(mhz, decimals, newfreq))
03148       return -1; 
03149 
03150    m = atoi(mhz);
03151    d = atoi(decimals);
03152 
03153    /* The FT-897 likes packed BCD frequencies */
03154 
03155    cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);        /* 100MHz 10Mhz */
03156    cmdstr[1] = ((m % 10) << 4) + (d / 10000);         /* 1MHz 100KHz */
03157    cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);  /* 10KHz 1KHz */
03158    cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);         /* 100Hz 10Hz */
03159    cmdstr[4] = 0x01;                /* command */
03160 
03161    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03162 
03163 }

static int set_ft897 ( struct rpt myrpt  )  [static]

Definition at line 3302 of file app_rpt.c.

References REM_MODE_FM, REM_MODE_LSB, REM_MODE_USB, rpt::remmode, set_ctcss_freq_ft897(), set_ctcss_mode_ft897(), set_freq_ft897(), set_mode_ft897(), set_offset_ft897(), and simple_command_ft897().

Referenced by setrem().

03303 {
03304    int res;
03305    
03306    if(debug)
03307       printf("@@@@ lock on\n");
03308 
03309    res = simple_command_ft897(myrpt, 0x00);           /* LOCK on */  
03310 
03311    if(debug)
03312       printf("@@@@ ptt off\n");
03313 
03314    if(!res)
03315       res = simple_command_ft897(myrpt, 0x88);     /* PTT off */
03316 
03317    if(debug)
03318       printf("Modulation mode\n");
03319 
03320    if(!res)
03321       res = set_mode_ft897(myrpt, myrpt->remmode);    /* Modulation mode */
03322 
03323    if(debug)
03324       printf("Split off\n");
03325 
03326    if(!res)
03327       simple_command_ft897(myrpt, 0x82);        /* Split off */
03328 
03329    if(debug)
03330       printf("Frequency\n");
03331 
03332    if(!res)
03333       res = set_freq_ft897(myrpt, myrpt->freq);    /* Frequency */
03334    if((myrpt->remmode == REM_MODE_FM)){
03335       if(debug)
03336          printf("Offset\n");
03337       if(!res)
03338          res = set_offset_ft897(myrpt, myrpt->offset);   /* Offset if FM */
03339       if((!res)&&(myrpt->rxplon || myrpt->txplon)){
03340          if(debug)
03341             printf("CTCSS tone freqs.\n");
03342          res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl); /* CTCSS freqs if CTCSS is enabled */
03343       }
03344       if(!res){
03345          if(debug)
03346             printf("CTCSS mode\n");
03347          res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */
03348       }
03349    }
03350    if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
03351       if(debug)
03352          printf("Clarifier off\n");
03353       simple_command_ft897(myrpt, 0x85);        /* Clarifier off if LSB or USB */
03354    }
03355    return res;
03356 }

static int set_mode_ft897 ( struct rpt myrpt,
char  newmode 
) [static]

Definition at line 3211 of file app_rpt.c.

References REM_MODE_AM, REM_MODE_FM, REM_MODE_LSB, REM_MODE_USB, and serial_remote_io().

Referenced by set_ft897().

03212 {
03213    unsigned char cmdstr[5];
03214    
03215    memset(cmdstr, 0, 5);
03216    
03217    switch(newmode){
03218       case  REM_MODE_FM:
03219          cmdstr[0] = 0x08;
03220          break;
03221 
03222       case  REM_MODE_USB:
03223          cmdstr[0] = 0x01;
03224          break;
03225 
03226       case  REM_MODE_LSB:
03227          cmdstr[0] = 0x00;
03228          break;
03229 
03230       case  REM_MODE_AM:
03231          cmdstr[0] = 0x04;
03232          break;
03233       
03234       default:
03235          return -1;
03236    }
03237    cmdstr[4] = 0x07; 
03238 
03239    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03240 }

static int set_offset_ft897 ( struct rpt myrpt,
char  offset 
) [static]

Definition at line 3181 of file app_rpt.c.

References REM_MINUS, REM_PLUS, REM_SIMPLEX, and serial_remote_io().

Referenced by set_ft897().

03182 {
03183    unsigned char cmdstr[5];
03184    
03185    memset(cmdstr, 0, 5);
03186 
03187    switch(offset){
03188       case  REM_SIMPLEX:
03189          cmdstr[0] = 0x89;
03190          break;
03191 
03192       case  REM_MINUS:
03193          cmdstr[0] = 0x09;
03194          break;
03195       
03196       case  REM_PLUS:
03197          cmdstr[0] = 0x49;
03198          break;   
03199 
03200       default:
03201          return -1;
03202    }
03203 
03204    cmdstr[4] = 0x09; 
03205 
03206    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03207 }

static int setrbi ( struct rpt myrpt  )  [static]

Definition at line 2856 of file app_rpt.c.

References rpt::freq, MAXREMSTR, rpt::offset, rpt::powerlevel, rbi_mhztoband(), rbi_out(), rbi_pltocode(), REM_HIPWR, REM_LOWPWR, REM_MEDPWR, REM_MINUS, REM_PLUS, REM_SIMPLEX, rpt::remote, rpt::rxplon, s, rpt::txpl, and rpt::txplon.

Referenced by setrem().

02857 {
02858 char tmp[MAXREMSTR] = "",rbicmd[5],*s;
02859 int   band,txoffset = 0,txpower = 0,txpl;
02860 
02861    /* must be a remote system */
02862    if (!myrpt->remote) return(0);
02863    /* must have rbi hardware */
02864    if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0);
02865    strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
02866    s = strchr(tmp,'.');
02867    /* if no decimal, is invalid */
02868    
02869    if (s == NULL){
02870       if(debug)
02871          printf("@@@@ Frequency needs a decimal\n");
02872       return -1;
02873    }
02874    
02875    *s++ = 0;
02876    if (strlen(tmp) < 2){
02877       if(debug)
02878          printf("@@@@ Bad MHz digits: %s\n", tmp);
02879       return -1;
02880    }
02881     
02882    if (strlen(s) < 3){
02883       if(debug)
02884          printf("@@@@ Bad KHz digits: %s\n", s);
02885       return -1;
02886    }
02887 
02888    if ((s[2] != '0') && (s[2] != '5')){
02889       if(debug)
02890          printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
02891       return -1;
02892    }
02893     
02894    band = rbi_mhztoband(tmp);
02895    if (band == -1){
02896       if(debug)
02897          printf("@@@@ Bad Band: %s\n", tmp);
02898       return -1;
02899    }
02900    
02901    txpl = rbi_pltocode(myrpt->txpl);
02902    
02903    if (txpl == -1){
02904       if(debug)
02905          printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
02906       return -1;
02907    }
02908 
02909    
02910    switch(myrpt->offset)
02911    {
02912        case REM_MINUS:
02913       txoffset = 0;
02914       break;
02915        case REM_PLUS:
02916       txoffset = 0x10;
02917       break;
02918        case REM_SIMPLEX:
02919       txoffset = 0x20;
02920       break;
02921    }
02922    switch(myrpt->powerlevel)
02923    {
02924        case REM_LOWPWR:
02925       txpower = 0;
02926       break;
02927        case REM_MEDPWR:
02928       txpower = 0x20;
02929       break;
02930        case REM_HIPWR:
02931       txpower = 0x10;
02932       break;
02933    }
02934    rbicmd[0] = 0;
02935    rbicmd[1] = band | txpower | 0xc0;
02936    rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
02937    if (s[2] == '5') rbicmd[2] |= 0x40;
02938    rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
02939    rbicmd[4] = txpl;
02940    if (myrpt->txplon) rbicmd[4] |= 0x40;
02941    if (myrpt->rxplon) rbicmd[4] |= 0x80;
02942    rbi_out(myrpt,rbicmd);
02943    return 0;
02944 }

static int setrem ( struct rpt myrpt  )  [static]

Definition at line 3414 of file app_rpt.c.

References rpt::remote, set_ft897(), and setrbi().

Referenced by function_remote(), and rpt_exec().

03415 {
03416    if(!strcmp(myrpt->remote, remote_rig_ft897))
03417       return set_ft897(myrpt);
03418    else if(!strcmp(myrpt->remote, remote_rig_rbi))
03419       return setrbi(myrpt);
03420    else
03421       return -1;
03422 }

static int simple_command_ft897 ( struct rpt myrpt,
char  command 
) [static]

Definition at line 3167 of file app_rpt.c.

References serial_remote_io().

Referenced by closerem_ft897(), and set_ft897().

03168 {
03169    unsigned char cmdstr[5];
03170    
03171    memset(cmdstr, 0, 5);
03172 
03173    cmdstr[4] = command; 
03174 
03175    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03176 
03177 }

static int split_ctcss_freq ( char *  hertz,
char *  decimal,
char *  freq 
) [static]

Definition at line 3014 of file app_rpt.c.

References MAXREMSTR.

Referenced by set_ctcss_freq_ft897().

03015 {
03016    char freq_copy[MAXREMSTR];
03017    char *decp;
03018 
03019    decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
03020    if(decp){
03021       *decp++ = 0;
03022       strncpy(hertz, freq_copy, MAXREMSTR);
03023       strncpy(decimal, decp, strlen(decp));
03024       decimal[strlen(decp)] = '\0';
03025       return 0;
03026    }
03027    else
03028       return -1;
03029 }

static int split_freq ( char *  mhz,
char *  decimals,
char *  freq 
) [static]

Definition at line 2991 of file app_rpt.c.

References MAXREMSTR.

Referenced by function_remote(), multimode_bump_freq_ft897(), service_scan(), and set_freq_ft897().

02992 {
02993    char freq_copy[MAXREMSTR];
02994    char *decp;
02995 
02996    decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
02997    if(decp){
02998       *decp++ = 0;
02999       strncpy(mhz, freq_copy, MAXREMSTR);
03000       strcpy(decimals, "00000");
03001       strncpy(decimals, decp, strlen(decp));
03002       decimals[5] = 0;
03003       return 0;
03004    }
03005    else
03006       return -1;
03007 
03008 }

static void stop_scan ( struct rpt myrpt,
int  flag 
) [static]

Definition at line 3474 of file app_rpt.c.

References rpt::hfscanmode, and rpt::hfscanstatus.

Referenced by handle_remote_dtmf_digit(), and service_scan().

03475 {
03476    myrpt->hfscanmode = 0;
03477    myrpt->hfscanstatus = ((flag) ? -2 : -1);
03478 }

static int telem_any ( struct ast_channel chan,
char *  entry 
) [static]

Definition at line 794 of file app_rpt.c.

References MORSE, retrieve_astcfgint(), sayfile(), send_morse(), and send_tone_telemetry().

Referenced by rpt_tele_thread(), and telem_lookup().

00795 {
00796    int res;
00797    char c;
00798    
00799    static int morsespeed;
00800    static int morsefreq;
00801    static int morseampl;
00802    static int morseidfreq = 0;
00803    static int morseidampl;
00804    static char mcat[] = MORSE;
00805    
00806    res = 0;
00807    
00808    if(!morseidfreq){ /* Get the morse parameters if not already loaded */
00809       morsespeed = retrieve_astcfgint( mcat, "speed", 5, 20, 20);
00810          morsefreq = retrieve_astcfgint( mcat, "frequency", 300, 3000, 800);
00811          morseampl = retrieve_astcfgint( mcat, "amplitude", 200, 8192, 4096);
00812       morseidampl = retrieve_astcfgint( mcat, "idamplitude", 200, 8192, 2048);
00813       morseidfreq = retrieve_astcfgint( mcat, "idfrequency", 300, 3000, 330); 
00814    }
00815    
00816    /* Is it a file, or a tone sequence? */
00817          
00818    if(entry[0] == '|'){
00819       c = entry[1];
00820       if((c >= 'a')&&(c <= 'z'))
00821          c -= 0x20;
00822    
00823       switch(c){
00824          case 'I': /* Morse ID */
00825             res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
00826             break;
00827          
00828          case 'M': /* Morse Message */
00829             res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
00830             break;
00831          
00832          case 'T': /* Tone sequence */
00833             res = send_tone_telemetry(chan, entry + 2);
00834             break;
00835          default:
00836             res = -1;
00837       }
00838    }
00839    else
00840       res = sayfile(chan, entry); /* File */
00841    return res;
00842 }

static int telem_lookup ( struct ast_channel chan,
char *  node,
char *  name 
) [static]

Definition at line 850 of file app_rpt.c.

References ast_log(), ast_strdupa, ast_variable_retrieve(), cfg, LOG_WARNING, tele_defs, telem_any(), and TELEMETRY.

Referenced by handle_remote_data(), handle_remote_phone_dtmf(), and rpt_tele_thread().

00851 {
00852    
00853    int res;
00854    int i;
00855    char *entry;
00856    char *telemetry;
00857    char *telemetry_save;
00858 
00859    res = 0;
00860    telemetry_save = NULL;
00861    entry = NULL;
00862    
00863    
00864    /* Retrieve the section name for telemetry from the node section */
00865    
00866    telemetry = ast_variable_retrieve(cfg, node, TELEMETRY);
00867    if(telemetry){
00868       telemetry_save = ast_strdupa(telemetry);
00869       if(!telemetry_save){
00870          ast_log(LOG_WARNING,"ast_strdupa() failed in telem_lookup()\n");
00871          return res;
00872       }
00873       entry = ast_variable_retrieve(cfg, telemetry_save, name);
00874    }
00875    
00876    /* Try to look up the telemetry name */
00877    
00878    if(!entry){
00879       /* Telemetry name wasn't found in the config file, use the default */
00880       for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
00881          if(!strcasecmp(tele_defs[i].name, name))
00882             entry = tele_defs[i].value;
00883       }
00884    }
00885    if(entry)   
00886       telem_any(chan, entry);
00887    else{
00888       ast_log(LOG_WARNING, "Telemetry name not found: %s\n", name);
00889       res = -1;
00890    }
00891    return res;
00892 }

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 6517 of file app_rpt.c.

References ast_cli_unregister(), ast_mutex_destroy(), ast_unregister_application(), cli_debug, lock, name, rpt_vars, and STANDARD_HANGUP_LOCALUSERS.

06518 {
06519    int i;
06520 
06521    STANDARD_HANGUP_LOCALUSERS;
06522    for(i = 0; i < nrpts; i++) {
06523       if (!strcmp(rpt_vars[i].name,rpt_vars[i].nodes)) continue;
06524                 ast_mutex_destroy(&rpt_vars[i].lock);
06525    }
06526    i = ast_unregister_application(app);
06527 
06528    /* Unregister cli extensions */
06529    ast_cli_unregister(&cli_debug);
06530 
06531    return i;
06532 }

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 6549 of file app_rpt.c.

References STANDARD_USECOUNT.

06550 {
06551    int res;
06552    STANDARD_USECOUNT(res);
06553    return res;
06554 }

static void wait_interval ( struct rpt myrpt,
int  type,
struct ast_channel chan 
) [static]

Definition at line 956 of file app_rpt.c.

References ast_safe_sleep(), and get_wait_interval().

Referenced by rpt_tele_thread().

00957 {
00958    int interval;
00959    if((interval = get_wait_interval(myrpt, type)))
00960       ast_safe_sleep(chan,interval);
00961    return;
00962 }


Variable Documentation

char* app = "Rpt" [static]

Definition at line 202 of file app_rpt.c.

struct ast_config* cfg

Definition at line 248 of file app_rpt.c.

Referenced by __load_resource(), ast_config_destroy(), ast_config_get_current_category(), ast_config_internal_load(), ast_config_load(), ast_config_set_current_category(), ast_enum_init(), ast_load_resource(), ast_readconfig(), ast_rtp_reload(), attempt_reconnect(), authenticate(), collect_function_digits(), conf_exec(), config_load(), config_odbc(), config_text_file_load(), config_text_file_save(), directory_exec(), do_directory(), festival_exec(), find_conf(), function_ilink(), function_remote(), get_wait_interval(), handle_save_dialplan(), iax_process_template(), iax_provision_reload(), iax_template_parse(), ind_load_module(), init_acf_query(), init_logger_chain(), init_manager(), load_config(), load_module(), load_modules(), load_moh_classes(), load_odbc_config(), loadconfigurationfile(), misdn_cfg_init(), my_load_module(), odbc_load_module(), osp_build(), parse_config(), pbx_load_module(), privacy_exec(), process_my_load_module(), process_text_line(), read_agent_config(), realtime_directory(), realtime_multi_odbc(), realtime_switch_common(), reload(), reload_config(), reload_queues(), retrieve_astcfgint(), rpt(), rpt_exec(), rpt_master(), rpt_tele_thread(), set_config(), setup_zap(), store_config(), tds_load_module(), and telem_lookup().

struct ast_cli_entry cli_debug [static]

Initial value:

        { { "rpt", "debug", "level" }, rpt_do_debug, "Enable app_rpt debugging", debug_usage }

Definition at line 406 of file app_rpt.c.

int debug = 0 [static]

Definition at line 241 of file app_rpt.c.

char debug_usage[] [static]

Initial value:

"Usage: rpt debug level {0-7}\n"
"       Enables debug messages in app_rpt\n"

Definition at line 402 of file app_rpt.c.

char* descrip [static]

Definition at line 206 of file app_rpt.c.

char* discstr = "!!DISCONNECT!!"

Definition at line 244 of file app_rpt.c.

struct function_table_tag function_table[] [static]

Definition at line 453 of file app_rpt.c.

Referenced by collect_function_digits().

LOCAL_USER_DECL

Definition at line 251 of file app_rpt.c.

int nrpts = 0 [static]

Definition at line 242 of file app_rpt.c.

char* remote_rig_ft897 = "ft897" [static]

Definition at line 245 of file app_rpt.c.

char* remote_rig_rbi = "rbi" [static]

Definition at line 246 of file app_rpt.c.

pthread_t rpt_master_thread [static]

Definition at line 261 of file app_rpt.c.

struct rpt rpt_vars[MAXRPTS] [static]

Referenced by rpt_exec(), rpt_master(), and unload_module().

STANDARD_LOCAL_USER

Definition at line 250 of file app_rpt.c.

char* synopsis = "Radio Repeater/Remote Base Control System" [static]

Definition at line 204 of file app_rpt.c.

char* tdesc = "Radio Repeater / Remote Base version 0.37 11/03/2005" [static]

Definition at line 200 of file app_rpt.c.

struct telem_defaults tele_defs[] [static]

Definition at line 416 of file app_rpt.c.

Referenced by telem_lookup().


Generated on Fri Sep 29 11:12:54 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7