Wed Oct 28 15:48:12 2009

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"
struct 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

#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(), and rpt_exec().

#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 4468 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(), 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().

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

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

Definition at line 3437 of file app_rpt.c.

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

Referenced by function_remote().

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

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

Definition at line 3042 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().

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

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

Definition at line 2951 of file app_rpt.c.

References REM_MODE_FM.

Referenced by check_freq().

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

static int closerem ( struct rpt myrpt  )  [static]

Definition at line 3425 of file app_rpt.c.

References closerem_ft897(), and rpt::remote.

Referenced by rpt_exec().

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

static int closerem_ft897 ( struct rpt myrpt  )  [static]

Definition at line 3359 of file app_rpt.c.

References simple_command_ft897().

Referenced by closerem().

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

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

Definition at line 2261 of file app_rpt.c.

References ast_variable_browse(), DC_ERROR, DC_INDETERMINATE, rpt::dphone_functions, rpt::dphone_longestfunc, 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().

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

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 6548 of file app_rpt.c.

06549 {
06550    return tdesc;
06551 }

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

Definition at line 2165 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.

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

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    pthread_attr_destroy(&attr);
02158    return DC_COMPLETE;
02159 }

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

Definition at line 2222 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.

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

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(), 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 3619 of file app_rpt.c.

References AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_safe_sleep(), ast_variable_retrieve(), 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.

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

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

Definition at line 2190 of file app_rpt.c.

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

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

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

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

Definition at line 2336 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().

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

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

Definition at line 2505 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().

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

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

Definition at line 4407 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.

Referenced by rpt_exec().

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

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

Definition at line 4312 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().

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

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

Definition at line 4442 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.

Referenced by rpt_exec().

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

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 6560 of file app_rpt.c.

References ASTERISK_GPL_KEY.

06561 {
06562    return ASTERISK_GPL_KEY;
06563 }

int load_module ( void   ) 

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.
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.
TE STUFF END

Definition at line 6538 of file app_rpt.c.

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

06539 {
06540    ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
06541 
06542    /* Register cli extensions */
06543    ast_cli_register(&cli_debug);
06544 
06545    return ast_register_application(app, rpt_exec, synopsis, descrip);
06546 }

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

Definition at line 3462 of file app_rpt.c.

References multimode_bump_freq_ft897(), and rpt::remote.

Referenced by function_remote(), and service_scan().

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

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

Definition at line 3371 of file app_rpt.c.

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

Referenced by multimode_bump_freq().

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

static int multimode_capable ( struct rpt myrpt  )  [static]

Definition at line 3451 of file app_rpt.c.

References rpt::remote.

Referenced by function_remote().

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

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 rpt_exec(), and 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 2648 of file app_rpt.c.

Referenced by setrbi().

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

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

Definition at line 2805 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().

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

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

Definition at line 2779 of file app_rpt.c.

References rpt::iobase.

Referenced by rbi_out().

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

static int rbi_pltocode ( char *  str  )  [static]

Definition at line 2684 of file app_rpt.c.

References s.

Referenced by setrbi().

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

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(), 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 3599 of file app_rpt.c.

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

Referenced by function_remote().

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

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

Definition at line 3585 of file app_rpt.c.

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

Referenced by function_remote().

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

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

Definition at line 3562 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(), rmt_sayfile(), and rpt_exec().

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

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

Definition at line 3550 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().

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

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

Definition at line 4528 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, 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.

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

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 5834 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_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_gethostbyname(), ast_hangup(), ast_indicate(), ast_inet_ntoa(), ast_log(), ast_masq_park_call(), ast_mutex_lock(), ast_mutex_unlock(), AST_PBX_KEEPALIVE, ast_read(), 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(), ast_write(), rpt::callmode, ast_channel::cid, ast_callerid::cid_num, closerem(), rpt::conf, ast_channel::context, context, ast_frame::data, ast_channel::data, ast_frame::datalen, rpt_link::disced, rpt::dtmf_time_rem, rpt::dtmfbuf, rpt::dtmfidx, ast_channel::exten, exten, ast_channel::fds, ast_frame::frametype, free, handle_remote_data(), handle_remote_phone_dtmf(), rpt::hfscanmode, rpt::hfscanstatus, hp, rpt::iobase, rpt_link::killme, rpt::links, LOCAL_USER_ADD, LOCAL_USER_REMOVE, 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(), play_tone(), ast_channel::priority, REDUNDANT_TX_TIME, REM_MODE_AM, REM_SCANTIME, rpt::remchannel, rpt::remote, rpt::remoteon, rpt::remoterx, rpt::remotetx, rpt_link::retries, rpt::retxtimer, REV_PATCH, rmt_telem_finish(), rpt_telemetry(), rpt_vars, rpt::rxchanname, rpt::rxchannel, s, sayfile(), saynum(), rpt::scantimer, service_scan(), set_mode_ft897(), setrem(), simple_command_ft897(), strsep(), ast_frame::subclass, rpt::tunerequest, rpt::txchanname, rpt::txchannel, VERBOSE_PREFIX_3, and ast_channel::whentohangup.

Referenced by load_module().

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

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

Definition at line 5609 of file app_rpt.c.

References rpt::acctcode, 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(), DEFAULT_IOBASE, rpt::dphone_functions, rpt::dphone_longestfunc, ENDCHAR, rpt::endchar, FUNCCHAR, rpt::funcchar, FUNCTIONS, rpt::functions, HANGTIME, rpt::hangtime, rpt::ident, IDTIME, rpt::idtime, rpt::iobase, rpt::lastthreadrestarttime, rpt::link_functions, rpt::link_longestfunc, lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, rpt::longestfunc, rpt::longestnode, n, name, ast_variable::name, rpt::name, ast_variable::next, rpt_tele::next, rpt::nobusyout, NODES, rpt::nodes, rpt::offset, rpt::ourcallerid, rpt::ourcontext, rpt::phone_functions, rpt::phone_longestfunc, POLITEID, rpt::politeid, rpt::powerlevel, rpt_tele::prev, REM_MEDPWR, REM_MODE_FM, REM_SIMPLEX, rpt::remmode, rpt::remote, retrieve_astcfgint(), rpt::rpt_thread, rpt_vars, rpt::rxchanname, rpt::simple, rpt::tele, rpt::threadrestarts, rpt::tonezone, TOTIME, rpt::totime, and rpt::txchanname.

Referenced by load_module().

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

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

Definition at line 964 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(), rpt_tele::chan, COMPLETE, CONNECTED, rpt_link::connected, CONNFAIL, DLY_CALLTERM, DLY_ID, DLY_TELEM, DLY_UNKEY, ast_channel::fds, free, ast_channel::generatordata, 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().

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

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

Definition at line 1491 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().

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

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 2827 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().

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

static int service_scan ( struct rpt myrpt  )  [static]

Definition at line 3486 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().

Referenced by rpt_exec().

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

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

Definition at line 3268 of file app_rpt.c.

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

Referenced by set_ft897().

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

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

Definition at line 3245 of file app_rpt.c.

References serial_remote_io().

Referenced by set_ft897().

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

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

Definition at line 3137 of file app_rpt.c.

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

Referenced by multimode_bump_freq_ft897(), and set_ft897().

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

static int set_ft897 ( struct rpt myrpt  )  [static]

Definition at line 3303 of file app_rpt.c.

References rpt::freq, rpt::offset, REM_MODE_FM, REM_MODE_LSB, REM_MODE_USB, rpt::remmode, rpt::rxpl, rpt::rxplon, set_ctcss_freq_ft897(), set_ctcss_mode_ft897(), set_freq_ft897(), set_mode_ft897(), set_offset_ft897(), simple_command_ft897(), rpt::txpl, and rpt::txplon.

Referenced by setrem().

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

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

Definition at line 3212 of file app_rpt.c.

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

Referenced by rpt_exec(), and set_ft897().

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

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

Definition at line 3182 of file app_rpt.c.

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

Referenced by set_ft897().

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

static int setrbi ( struct rpt myrpt  )  [static]

Definition at line 2857 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().

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

static int setrem ( struct rpt myrpt  )  [static]

Definition at line 3415 of file app_rpt.c.

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

Referenced by function_remote(), and rpt_exec().

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

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

Definition at line 3168 of file app_rpt.c.

References serial_remote_io().

Referenced by closerem_ft897(), rpt_exec(), and set_ft897().

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

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

Definition at line 3015 of file app_rpt.c.

References MAXREMSTR.

Referenced by set_ctcss_freq_ft897().

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

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

Definition at line 2992 of file app_rpt.c.

References MAXREMSTR.

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

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

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

Definition at line 3475 of file app_rpt.c.

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

Referenced by handle_remote_dtmf_digit(), and service_scan().

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

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(), LOG_WARNING, 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 6521 of file app_rpt.c.

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

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

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 6553 of file app_rpt.c.

References STANDARD_USECOUNT.

06554 {
06555    int res;
06556    STANDARD_USECOUNT(res);
06557    return res;
06558 }

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

Definition at line 955 of file app_rpt.c.

References ast_safe_sleep(), and get_wait_interval().

Referenced by rpt_tele_thread().

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


Variable Documentation

char* app = "Rpt" [static]

Definition at line 202 of file app_rpt.c.

struct ast_config* cfg

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.

Definition at line 453 of file app_rpt.c.

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().

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.


Generated on Wed Oct 28 15:48:13 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6