Sat Nov 25 00:45:46 2006

Asterisk developer's documentation


app_rpt.c File Reference

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

Go to the source code of this file.

Data Structures

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

Defines

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

Enumerations

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

Functions

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

Variables

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


Define Documentation

#define ACTIONSIZE   32
 

Definition at line 131 of file app_rpt.c.

#define DEFAULT_IOBASE   0x378
 

Definition at line 125 of file app_rpt.c.

Referenced by rpt_master().

#define DISC_TIME   10000
 

Definition at line 108 of file app_rpt.c.

Referenced by rpt().

#define DTMF_TIMEOUT   3
 

Definition at line 106 of file app_rpt.c.

Referenced by handle_remote_dtmf_digit(), and rpt().

#define ENDCHAR   '#'
 

Definition at line 123 of file app_rpt.c.

Referenced by rpt_master().

#define FUNCCHAR   '*'
 

Definition at line 122 of file app_rpt.c.

Referenced by rpt_master().

#define FUNCTDELAY   1500
 

Definition at line 259 of file app_rpt.c.

#define FUNCTIONS   "functions"
 

Definition at line 119 of file app_rpt.c.

Referenced by rpt_master().

#define HANGTIME   5000
 

Definition at line 254 of file app_rpt.c.

Referenced by rpt_master().

#define IDTIME   300000
 

Definition at line 256 of file app_rpt.c.

Referenced by rpt_master().

#define MAX_RETRIES   5
 

Definition at line 109 of file app_rpt.c.

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

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

#define MAXREMSTR   15
 

Definition at line 115 of file app_rpt.c.

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

#define MAXRPTS   20
 

Definition at line 257 of file app_rpt.c.

#define MEMORY   "memory"
 

Definition at line 118 of file app_rpt.c.

Referenced by function_remote().

#define MORSE   "morse"
 

Definition at line 121 of file app_rpt.c.

Referenced by telem_any().

#define MSWAIT   200
 

Definition at line 253 of file app_rpt.c.

Referenced by rpt(), and rpt_call().

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

#define REM_SCANTIME   100
 

Definition at line 135 of file app_rpt.c.

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

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

Referenced by rpt().

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

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

Definition at line 3435 of file app_rpt.c.

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

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

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

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

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

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

Definition at line 2949 of file app_rpt.c.

References REM_MODE_FM.

Referenced by check_freq().

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

static int closerem struct rpt myrpt  )  [static]
 

Definition at line 3423 of file app_rpt.c.

References closerem_ft897(), and rpt::remote.

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

static int closerem_ft897 struct rpt myrpt  )  [static]
 

Definition at line 3357 of file app_rpt.c.

References simple_command_ft897().

Referenced by closerem().

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

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

Definition at line 2259 of file app_rpt.c.

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

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

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

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 6543 of file app_rpt.c.

06544 {
06545    return tdesc;
06546 }

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

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

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

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

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

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

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

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

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

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

Definition at line 1765 of file app_rpt.c.

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

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

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

Definition at line 3617 of file app_rpt.c.

References ast_safe_sleep(), ast_variable_retrieve(), cfg, DC_COMPLETE, DC_ERROR, rpt::freq, MAXREMSTR, MEMORY, multimode_capable(), myatoi(), 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_SIMPLEX, rpt::remchannel, rpt::remmode, rpt::rxpl, rpt::rxplon, s, sayfile(), setrem(), SOURCE_LNK, SOURCE_RPT, rpt::txpl, and rpt::txplon.

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

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

Definition at line 2188 of file app_rpt.c.

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

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

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

Definition at line 898 of file app_rpt.c.

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

Referenced by 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 2334 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().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

References ASTERISK_GPL_KEY.

06556 {
06557    return ASTERISK_GPL_KEY;
06558 }

int load_module void   ) 
 

Initialize the module.

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

Returns:
int Always 0.

Definition at line 6533 of file app_rpt.c.

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

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

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

Definition at line 3460 of file app_rpt.c.

References multimode_bump_freq_ft897(), and rpt::remote.

Referenced by service_scan().

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

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

Definition at line 3369 of file app_rpt.c.

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

Referenced by multimode_bump_freq().

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

static int multimode_capable struct rpt myrpt  )  [static]
 

Definition at line 3449 of file app_rpt.c.

References rpt::remote.

Referenced by function_remote().

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

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

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

Referenced by setrbi().

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

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

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

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

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

Definition at line 2777 of file app_rpt.c.

References rpt::iobase.

Referenced by rbi_out().

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

static int rbi_pltocode char *  str  )  [static]
 

Definition at line 2682 of file app_rpt.c.

References s.

Referenced by setrbi().

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

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

Definition at line 776 of file app_rpt.c.

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

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

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

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

Definition at line 3597 of file app_rpt.c.

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

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

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

Definition at line 3583 of file app_rpt.c.

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

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

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

Definition at line 3560 of file app_rpt.c.

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

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

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

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

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

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

static void* rpt void *  this  )  [static]
 

Definition at line 4526 of file app_rpt.c.

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

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

static void* rpt_call void *  this  )  [static]
 

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

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

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

References ast_log(), ast_strlen_zero(), LOG_WARNING, name, rpt_vars, and strsep().

Referenced by load_module().

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

static void* rpt_master void *  ignore  )  [static]
 

Definition at line 5606 of file app_rpt.c.

References ast_category_browse(), ast_config_load(), ast_log(), ast_mutex_init(), AST_PTHREADT_NULL, ast_true(), ast_variable_retrieve(), cfg, DEFAULT_IOBASE, ENDCHAR, FUNCCHAR, FUNCTIONS, HANGTIME, IDTIME, lock, LOG_DEBUG, LOG_NOTICE, n, NODES, POLITEID, retrieve_astcfgint(), rpt_vars, and TOTIME.

Referenced by load_module().

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

static void* rpt_tele_thread void *  this  )  [static]
 

Definition at line 964 of file app_rpt.c.

References AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_strdupa, rpt_tele::chan, ast_channel::fds, free, ID, IDTALKOVER, LOG_WARNING, rpt_tele::mode, rpt_tele::rpt, t, and UNKEY.

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

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    return;
01525 }

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

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

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

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

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 morse_bits::ddcomb, morse_bits::len, and play_silence().

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_strdupa, 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 2825 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().

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

static int service_scan struct rpt myrpt  )  [static]
 

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

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

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

Definition at line 3266 of file app_rpt.c.

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

Referenced by set_ft897().

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

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

Definition at line 3243 of file app_rpt.c.

References serial_remote_io().

Referenced by set_ft897().

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

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

Definition at line 3135 of file app_rpt.c.

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

Referenced by multimode_bump_freq_ft897(), and set_ft897().

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

static int set_ft897 struct rpt myrpt  )  [static]
 

Definition at line 3301 of file app_rpt.c.

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

Referenced by setrem().

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

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

Definition at line 3210 of file app_rpt.c.

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

Referenced by set_ft897().

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

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

Definition at line 3180 of file app_rpt.c.

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

Referenced by set_ft897().

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

static int setrbi struct rpt myrpt  )  [static]
 

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

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

static int setrem struct rpt myrpt  )  [static]
 

Definition at line 3413 of file app_rpt.c.

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

Referenced by function_remote().

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

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

Definition at line 3166 of file app_rpt.c.

References serial_remote_io().

Referenced by closerem_ft897(), and set_ft897().

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

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

Definition at line 3013 of file app_rpt.c.

References MAXREMSTR.

Referenced by set_ctcss_freq_ft897().

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

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

Definition at line 2990 of file app_rpt.c.

References MAXREMSTR.

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

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

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

Definition at line 3473 of file app_rpt.c.

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

Referenced by handle_remote_dtmf_digit(), and service_scan().

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

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

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

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

Definition at line 850 of file app_rpt.c.

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

Referenced by handle_remote_data(), and handle_remote_phone_dtmf().

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

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

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

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

References STANDARD_USECOUNT.

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

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

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
 

Definition at line 248 of file app_rpt.c.

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

struct ast_cli_entry cli_debug [static]
 

Initial value:

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

Definition at line 406 of file app_rpt.c.

int debug = 0 [static]
 

Definition at line 241 of file app_rpt.c.

char debug_usage[] [static]
 

Initial value:

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

Definition at line 402 of file app_rpt.c.

char* descrip [static]
 

Definition at line 206 of file app_rpt.c.

char* discstr = "!!DISCONNECT!!"
 

Definition at line 244 of file app_rpt.c.

struct function_table_tag function_table[] [static]
 

Definition at line 453 of file app_rpt.c.

Referenced by collect_function_digits().

LOCAL_USER_DECL
 

Definition at line 251 of file app_rpt.c.

int nrpts = 0 [static]
 

Definition at line 242 of file app_rpt.c.

char* remote_rig_ft897 = "ft897" [static]
 

Definition at line 245 of file app_rpt.c.

char* remote_rig_rbi = "rbi" [static]
 

Definition at line 246 of file app_rpt.c.

pthread_t rpt_master_thread [static]
 

Definition at line 261 of file app_rpt.c.

struct rpt rpt_vars[MAXRPTS] [static]
 

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

STANDARD_LOCAL_USER
 

Definition at line 250 of file app_rpt.c.

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

Definition at line 204 of file app_rpt.c.

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

Definition at line 200 of file app_rpt.c.

struct telem_defaults tele_defs[] [static]
 

Definition at line 416 of file app_rpt.c.

Referenced by telem_lookup().


Generated on Sat Nov 25 00:45:46 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6