Thu Feb 5 16:25:55 2009

Asterisk developer's documentation


app_rpt.c File Reference

Radio Repeater / Remote Base program version 0.73 09/04/07. More...

#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 <sys/vfs.h>
#include <math.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <termios.h>
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/callerid.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/features.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/localtime.h"
#include "asterisk/cdr.h"
#include "asterisk/dahdi_compat.h"
#include "asterisk/tonezone_compat.h"

Go to the source code of this file.

Data Structures

struct  function_table_tag
struct  morse_bits
struct  nodelog
struct  rpt
struct  rpt_chan_stat
struct  rpt_link
struct  rpt_lstat
struct  rpt_tele
struct  rpt_xlat
struct  sysstate
struct  telem_defaults

Defines

#define ACTIONSIZE   32
#define ALLOW_LOCAL_CHANNELS
#define AUTHLOGOUTTIME   25000
#define AUTHTELLTIME   7000
#define AUTHTXTIME   1000
#define DEFAULT_CIV_ADDR   0x58
#define DEFAULT_IOBASE   0x378
#define DEFAULT_MONITOR_MIN_DISK_BLOCKS   10000
#define DEFAULT_REMOTE_INACT_TIMEOUT   (15 * 60)
#define DEFAULT_REMOTE_TIMEOUT   (60 * 60)
#define DEFAULT_REMOTE_TIMEOUT_WARNING   (3 * 60)
#define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ   30
#define DELIMCHR   ','
#define DISC_TIME   10000
#define DTMF_LOCAL_STARTTIME   500
#define DTMF_LOCAL_TIME   250
#define DTMF_TIMEOUT   3
#define ENDCHAR   '#'
#define EXTNODEFILE   "/var/lib/asterisk/rpt_extnodes"
#define EXTNODES   "extnodes"
#define FUNCCHAR   '*'
#define FUNCTDELAY   1500
#define FUNCTIONS   "functions"
#define HANGTIME   5000
#define IC706_PL_MEMORY_OFFSET   50
#define IDTIME   300000
#define KENWOOD_RETRIES   5
#define LINKLISTSHORTTIME   200
#define LINKLISTTIME   10000
#define MACRO   "macro"
#define MACROPTIME   500
#define MACROTIME   100
#define MAX_RETRIES   5
#define MAX_RETRIES_PERM   1000000000
#define MAX_STAT_LINKS   32
#define MAX_SYSSTATES   10
#define MAXCONNECTTIME   5000
#define MAXDTMF   32
#define MAXLINKLIST   512
#define MAXMACRO   2048
#define MAXNODESTR   300
#define MAXPATCHCONTEXT   100
#define MAXPEERSTR   31
#define MAXREMSTR   15
#define MAXRPTS   20
#define MAXXLAT   20
#define MAXXLATTIME   3
#define MEMORY   "memory"
#define MONITOR_DISK_BLOCKS_PER_MINUTE   38
#define MORSE   "morse"
#define MSWAIT   200
#define NODES   "nodes"
#define NRPTSTAT   7
#define OLDKEY
#define POLITEID   30000
#define QUOTECHR   34
#define REDUNDANT_TX_TIME   2000
#define REM_SCANTIME   100
#define RETRY_TIMER_MS   5000
#define rpt_mutex_lock(x)   ast_mutex_lock(x)
#define rpt_mutex_unlock(x)   ast_mutex_unlock(x)
#define START_DELAY   2
#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,
  TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY,
  FULLSTATUS, MEMNOTFOUND, INVFREQ, REMMODE,
  REMLOGIN, REMXXX, REMSHORTSTATUS, REMLONGSTATUS,
  LOGINREQ, SCAN, SCANSTAT, TUNE,
  SETREMOTE, TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY,
  UNAUTHTX
}
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_COMPLETEQUIET, DC_DOKEY
}
enum  {
  SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE,
  SOURCE_DPHONE
}
enum  {
  DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM,
  DLY_COMP, DLY_LINKUNKEY
}
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
}
enum  { TOP_TOP, TOP_WON, WON_BEFREAD, BEFREAD_AFTERREAD }

Functions

static void __kickshort (struct rpt *myrpt)
static void __mklinklist (struct rpt *myrpt, struct rpt_link *mylink, char *buf)
static void __reg_module (void)
static void __unreg_module (void)
int ast_playtones_start (struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
void ast_playtones_stop (struct ast_channel *chan)
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_ic706 (int m, int d, int *defmode)
static int check_freq_kenwood (int m, int d, int *defmode)
static int check_freq_rbi (int m, int d, int *defmode)
static char check_tx_freq (struct rpt *myrpt)
static int civ_cmd (struct rpt *myrpt, unsigned char *cmd, int cmdlen)
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)
static int connect_link (struct rpt *myrpt, char *node, int mode, int perma)
static int decimals2int (char *fraction)
static long diskavail (struct rpt *myrpt)
static void do_dtmf_local (struct rpt *myrpt, char c)
static void do_dtmf_phone (struct rpt *myrpt, struct rpt_link *mylink, char c)
static void do_scheduler (struct rpt *myrpt)
static void donodelog (struct rpt *myrpt, char *str)
static char * eatwhite (char *s)
static int finddelim (char *str, char *strp[], int limit)
static char func_xlat (struct rpt *myrpt, char c, struct rpt_xlat *xlat)
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_macro (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)
static int ic706_pltocode (char *str)
static int kenwood_pltocode (char *str)
static int load_module (void)
static void load_rpt_vars (int n, int init)
static void local_dtmf_helper (struct rpt *myrpt, char c)
static int matchkeyword (char *string, char **param, char *keywords[])
static void mdc1200_notify (struct rpt *myrpt, char *fromnode, unsigned int unit)
static int mem2vfo_ic706 (struct rpt *myrpt)
static int multimode_bump_freq (struct rpt *myrpt, int interval)
static int multimode_bump_freq_ft897 (struct rpt *myrpt, int interval)
static int multimode_bump_freq_ic706 (struct rpt *myrpt, int interval)
static int multimode_capable (struct rpt *myrpt)
static int myatoi (char *str)
static int mycompar (const void *a, const void *b)
static char * node_lookup (struct rpt *myrpt, char *digitbuf)
static int openserial (char *fname)
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 void queue_id (struct rpt *myrpt)
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 reload (void)
static int retreive_memory (struct rpt *myrpt, char *memory)
static int retrieve_astcfgint (struct rpt *myrpt, char *category, char *name, int min, int max, int defl)
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_do_dump (int fd, int argc, char *argv[])
static int rpt_do_fun (int fd, int argc, char *argv[])
static int rpt_do_lstats (int fd, int argc, char *argv[])
static int rpt_do_nodes (int fd, int argc, char *argv[])
static int rpt_do_reload (int fd, int argc, char *argv[])
static int rpt_do_restart (int fd, int argc, char *argv[])
static int rpt_do_stats (int fd, int argc, char *argv[])
static int rpt_exec (struct ast_channel *chan, void *data)
static void rpt_localtime (time_t *t, struct tm *lt)
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 int select_mem_ic706 (struct rpt *myrpt, int slot)
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 sendkenwood (struct rpt *myrpt, char *txstr, char *rxstr)
static int sendrxkenwood (struct rpt *myrpt, char *txstr, char *rxstr, char *cmpstr)
static int serial_remote_io (struct rpt *myrpt, unsigned char *txbuf, int txbytes, unsigned 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_ctcss_mode_ic706 (struct rpt *myrpt, char txplon, char rxplon)
static int set_freq_ft897 (struct rpt *myrpt, char *newfreq)
static int set_freq_ic706 (struct rpt *myrpt, char *newfreq)
static int set_ft897 (struct rpt *myrpt)
static int set_ic706 (struct rpt *myrpt)
static int set_mode_ft897 (struct rpt *myrpt, char newmode)
static int set_mode_ic706 (struct rpt *myrpt, char newmode)
static int set_offset_ft897 (struct rpt *myrpt, char offset)
static int set_offset_ic706 (struct rpt *myrpt, char offset)
static int setkenwood (struct rpt *myrpt)
static int setrbi (struct rpt *myrpt)
static int setrbi_check (struct rpt *myrpt)
static int setrem (struct rpt *myrpt)
static int simple_command_ft897 (struct rpt *myrpt, char command)
static int simple_command_ic706 (struct rpt *myrpt, char command, char subcommand)
static char * skipchars (char *string, char *charlist)
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)
static int telem_any (struct rpt *myrpt, struct ast_channel *chan, char *entry)
static int telem_lookup (struct rpt *myrpt, struct ast_channel *chan, char *node, char *name)
static int unload_module (void)
static int vfo_ic706 (struct rpt *myrpt)
static void wait_interval (struct rpt *myrpt, int type, struct ast_channel *chan)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Radio Repeater/Remote Base Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, }
static char * app = "Rpt"
static const struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_debug
static struct ast_cli_entry cli_dump
static struct ast_cli_entry cli_fun
static struct ast_cli_entry cli_lstats
static struct ast_cli_entry cli_nodes
static struct ast_cli_entry cli_reload
static struct ast_cli_entry cli_restart
static struct ast_cli_entry cli_stats
static int debug = 0
static char debug_usage []
static char * descrip
char * discstr = "!!DISCONNECT!!"
static char dump_lstats []
static char dump_nodes []
static char dump_stats []
static char dump_usage []
static char fun_usage []
static struct function_table_tag function_table []
int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000}
static ast_mutex_t nodeloglock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static ast_mutex_t nodelookuplock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static int nrpts = 0
static char reload_usage []
static char remdtmfstr [] = "0123456789*#ABCD"
static char * remote_rig_ft897 = "ft897"
static char * remote_rig_ic706 = "ic706"
static char * remote_rig_kenwood = "kenwood"
static char * remote_rig_rbi = "rbi"
static char restart_usage []
static pthread_t rpt_master_thread
static struct rpt rpt_vars [MAXRPTS]
static time_t starttime = 0
static char * synopsis = "Radio Repeater/Remote Base Control System"
static char * tdesc = "Radio Repeater / Remote Base version 0.73 09/04/2007"
static struct telem_defaults tele_defs []


Detailed Description

Radio Repeater / Remote Base program version 0.73 09/04/07.

Author:
Jim Dixon, WB6NIL <jim@lambdatel.com>
Note:
Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
See http://www.zapatatelephony.org/app_rpt.html

Repeater / Remote Functions: "Simple" Mode: * - autopatch access, # - autopatch hangup Normal mode: See the function list in rpt.conf (autopatchup, autopatchdn) autopatchup can optionally take comma delimited setting=value pairs:

context=string : Override default context with "string" dialtime=ms : Specify the max number of milliseconds between phone number digits (1000 milliseconds = 1 second) farenddisconnect=1 : Automatically disconnect when called party hangs up noct=1 : Don't send repeater courtesy tone during autopatch calls quiet=1 : Don't send dial tone, or connect messages. Do not send patch down message when called party hangs up

Example: 123=autopatchup,dialtime=20000,noct=1,farenddisconnect=1

To send an asterisk (*) while dialing or talking on phone, use the autopatch acess code.

status cmds:

1 - Force ID 2 - Give Time of Day 3 - Give software Version

cop (control operator) cmds:

1 - System warm boot 2 - System enable 3 - System disable 4 - Test Tone On/Off 5 - Dump System Variables on Console (debug) 6 - PTT (phone mode only) 7 - Time out timer enable 8 - Time out timer disable 9 - Autopatch enable 10 - Autopatch disable 11 - Link enable 12 - Link disable 13 - Query System State 14 - Change System State 15 - Scheduler Enable 16 - Scheduler Disable 17 - User functions (time, id, etc) enable 18 - User functions (time, id, etc) disable 19 - Select alternate hang timer 20 - Select standard hang timer

ilink cmds:

1 - Disconnect specified link 2 - Connect specified link -- monitor only 3 - Connect specified link -- tranceive 4 - Enter command mode on specified link 5 - System status 6 - Disconnect all links 11 - Disconnect a previously permanently connected link 12 - Permanently connect specified link -- monitor only 13 - Permanently connect specified link -- tranceive 15 - Full system status (all nodes) 16 - Reconnect links disconnected with "disconnect all links" 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)

remote cmds:

1 - Recall Memory MM (*000-*099) (Gets memory from rpt.conf) 2 - Set VFO MMMMM*KKK*O (Mhz digits, Khz digits, Offset) 3 - Set Rx PL Tone HHH*D* 4 - Set Tx PL Tone HHH*D* (Not currently implemented with DHE RBI-1) 5 - Link Status (long) 6 - Set operating mode M (FM, USB, LSB, AM, etc) 100 - RX PL off (Default) 101 - RX PL On 102 - TX PL Off (Default) 103 - TX PL On 104 - Low Power 105 - Med Power 106 - Hi Power 107 - Bump Down 20 Hz 108 - Bump Down 100 Hz 109 - Bump Down 500 Hz 110 - Bump Up 20 Hz 111 - Bump Up 100 Hz 112 - Bump Up 500 Hz 113 - Scan Down Slow 114 - Scan Down Medium 115 - Scan Down Fast 116 - Scan Up Slow 117 - Scan Up Medium 118 - Scan Up Fast 119 - Transmit allowing auto-tune 140 - Link Status (brief) 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)

'duplex' modes: (defaults to duplex=2)

0 - Only remote links key Tx and no main repeat audio. 1 - Everything other then main Rx keys Tx, no main repeat audio. 2 - Normal mode 3 - Normal except no main repeat audio. 4 - Normal except no main repeat audio during autopatch only

Definition in file app_rpt.c.


Define Documentation

#define ACTIONSIZE   32

Definition at line 218 of file app_rpt.c.

#define ALLOW_LOCAL_CHANNELS

Definition at line 229 of file app_rpt.c.

#define AUTHLOGOUTTIME   25000

Definition at line 167 of file app_rpt.c.

#define AUTHTELLTIME   7000

Definition at line 165 of file app_rpt.c.

#define AUTHTXTIME   1000

Definition at line 166 of file app_rpt.c.

#define DEFAULT_CIV_ADDR   0x58

Definition at line 210 of file app_rpt.c.

Referenced by load_rpt_vars().

#define DEFAULT_IOBASE   0x378

Definition at line 208 of file app_rpt.c.

Referenced by load_rpt_vars().

#define DEFAULT_MONITOR_MIN_DISK_BLOCKS   10000

Definition at line 191 of file app_rpt.c.

Referenced by load_rpt_vars().

#define DEFAULT_REMOTE_INACT_TIMEOUT   (15 * 60)

Definition at line 192 of file app_rpt.c.

Referenced by load_rpt_vars().

#define DEFAULT_REMOTE_TIMEOUT   (60 * 60)

Definition at line 193 of file app_rpt.c.

Referenced by load_rpt_vars().

#define DEFAULT_REMOTE_TIMEOUT_WARNING   (3 * 60)

Definition at line 194 of file app_rpt.c.

Referenced by load_rpt_vars().

#define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ   30

Definition at line 195 of file app_rpt.c.

Referenced by load_rpt_vars().

#define DELIMCHR   ','

Definition at line 186 of file app_rpt.c.

Referenced by finddelim().

#define DISC_TIME   10000

Definition at line 173 of file app_rpt.c.

Referenced by rpt().

#define DTMF_LOCAL_STARTTIME   500

Definition at line 225 of file app_rpt.c.

Referenced by do_dtmf_local().

#define DTMF_LOCAL_TIME   250

Definition at line 224 of file app_rpt.c.

Referenced by do_dtmf_local().

#define DTMF_TIMEOUT   3

Definition at line 162 of file app_rpt.c.

Referenced by handle_remote_dtmf_digit(), and rpt().

#define ENDCHAR   '#'

Definition at line 205 of file app_rpt.c.

Referenced by load_rpt_vars().

#define EXTNODEFILE   "/var/lib/asterisk/rpt_extnodes"

Definition at line 206 of file app_rpt.c.

Referenced by load_rpt_vars().

#define EXTNODES   "extnodes"

Definition at line 198 of file app_rpt.c.

Referenced by load_rpt_vars().

#define FUNCCHAR   '*'

Definition at line 204 of file app_rpt.c.

Referenced by load_rpt_vars().

#define FUNCTDELAY   1500

Definition at line 390 of file app_rpt.c.

#define FUNCTIONS   "functions"

Definition at line 201 of file app_rpt.c.

Referenced by load_rpt_vars().

#define HANGTIME   5000

Definition at line 384 of file app_rpt.c.

Referenced by load_rpt_vars().

#define IC706_PL_MEMORY_OFFSET   50

Definition at line 227 of file app_rpt.c.

Referenced by set_ic706().

#define IDTIME   300000

Definition at line 386 of file app_rpt.c.

Referenced by load_rpt_vars().

#define KENWOOD_RETRIES   5

Definition at line 163 of file app_rpt.c.

Referenced by sendrxkenwood().

#define LINKLISTSHORTTIME   200

Definition at line 159 of file app_rpt.c.

Referenced by __kickshort().

#define LINKLISTTIME   10000

Definition at line 158 of file app_rpt.c.

Referenced by rpt().

#define MACRO   "macro"

Definition at line 200 of file app_rpt.c.

Referenced by load_rpt_vars().

#define MACROPTIME   500

Definition at line 161 of file app_rpt.c.

Referenced by rpt().

#define MACROTIME   100

Definition at line 160 of file app_rpt.c.

Referenced by do_scheduler(), function_macro(), rpt(), and rpt_do_fun().

#define MAX_RETRIES   5

Definition at line 174 of file app_rpt.c.

Referenced by connect_link(), and function_ilink().

#define MAX_RETRIES_PERM   1000000000

Definition at line 175 of file app_rpt.c.

Referenced by connect_link().

#define MAX_STAT_LINKS   32

Definition at line 388 of file app_rpt.c.

Referenced by rpt_do_stats().

#define MAX_SYSSTATES   10

Definition at line 395 of file app_rpt.c.

Referenced by load_rpt_vars().

#define MAXCONNECTTIME   5000

Definition at line 212 of file app_rpt.c.

Referenced by rpt().

#define MAXDTMF   32

Definition at line 155 of file app_rpt.c.

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

#define MAXLINKLIST   512

Definition at line 157 of file app_rpt.c.

Referenced by __mklinklist(), connect_link(), function_ilink(), rpt(), rpt_do_nodes(), and rpt_tele_thread().

#define MAXMACRO   2048

Definition at line 156 of file app_rpt.c.

Referenced by do_scheduler(), function_macro(), rpt(), and rpt_do_fun().

#define MAXNODESTR   300

Definition at line 214 of file app_rpt.c.

Referenced by connect_link(), and function_ilink().

#define MAXPATCHCONTEXT   100

Definition at line 216 of file app_rpt.c.

Referenced by function_autopatchup(), and local_dtmf_helper().

#define MAXPEERSTR   31

Definition at line 183 of file app_rpt.c.

Referenced by rpt_do_lstats().

#define MAXREMSTR   15

Definition at line 184 of file app_rpt.c.

Referenced by check_tx_freq(), function_remote(), multimode_bump_freq_ft897(), multimode_bump_freq_ic706(), rpt_do_lstats(), rpt_tele_thread(), service_scan(), set_ctcss_freq_ft897(), set_freq_ft897(), set_freq_ic706(), setkenwood(), setrbi(), setrbi_check(), split_ctcss_freq(), and split_freq().

#define MAXRPTS   20

Definition at line 387 of file app_rpt.c.

#define MAXXLAT   20

Definition at line 392 of file app_rpt.c.

Referenced by load_rpt_vars().

#define MAXXLATTIME   3

Definition at line 393 of file app_rpt.c.

Referenced by func_xlat().

#define MEMORY   "memory"

Definition at line 199 of file app_rpt.c.

Referenced by load_rpt_vars().

#define MONITOR_DISK_BLOCKS_PER_MINUTE   38

Definition at line 189 of file app_rpt.c.

#define MORSE   "morse"

Definition at line 203 of file app_rpt.c.

Referenced by telem_any().

#define MSWAIT   200

Definition at line 383 of file app_rpt.c.

Referenced by rpt(), and rpt_call().

#define NODES   "nodes"

Definition at line 197 of file app_rpt.c.

Referenced by load_rpt_vars().

#define NRPTSTAT   7

Definition at line 361 of file app_rpt.c.

Referenced by rpt_do_lstats().

#define OLDKEY

Definition at line 2 of file app_rpt.c.

#define POLITEID   30000

Definition at line 389 of file app_rpt.c.

Referenced by load_rpt_vars().

#define QUOTECHR   34

Definition at line 187 of file app_rpt.c.

Referenced by finddelim().

#define REDUNDANT_TX_TIME   2000

Definition at line 177 of file app_rpt.c.

Referenced by rpt().

#define REM_SCANTIME   100

Definition at line 222 of file app_rpt.c.

Referenced by function_remote().

#define RETRY_TIMER_MS   5000

Definition at line 179 of file app_rpt.c.

Referenced by rpt().

#define rpt_mutex_lock (  )     ast_mutex_lock(x)

Definition at line 869 of file app_rpt.c.

Referenced by attempt_reconnect(), connect_link(), do_dtmf_local(), function_autopatchdn(), function_autopatchup(), function_ilink(), function_macro(), handle_link_data(), handle_link_phone_dtmf(), handle_remote_dtmf_digit(), local_dtmf_helper(), queue_id(), rpt(), rpt_call(), rpt_do_fun(), rpt_do_lstats(), rpt_do_nodes(), rpt_do_stats(), rpt_tele_thread(), and rpt_telemetry().

#define rpt_mutex_unlock (  )     ast_mutex_unlock(x)

Definition at line 870 of file app_rpt.c.

Referenced by attempt_reconnect(), connect_link(), do_dtmf_local(), function_autopatchdn(), function_autopatchup(), function_ilink(), function_macro(), handle_link_data(), handle_link_phone_dtmf(), handle_remote_dtmf_digit(), local_dtmf_helper(), queue_id(), rpt(), rpt_call(), rpt_do_fun(), rpt_do_lstats(), rpt_do_nodes(), rpt_do_stats(), rpt_tele_thread(), and rpt_telemetry().

#define START_DELAY   2

Definition at line 181 of file app_rpt.c.

Referenced by rpt(), and rpt_exec().

#define TELEMETRY   "telemetry"

Definition at line 202 of file app_rpt.c.

Referenced by telem_lookup().

#define TELEPARAMSIZE   256

Definition at line 220 of file app_rpt.c.

Referenced by rpt_telemetry().

#define TOTIME   180000

Definition at line 385 of file app_rpt.c.

Referenced by load_rpt_vars().


Enumeration Type Documentation

anonymous enum

Enumerator:
REM_OFF 
REM_MONITOR 
REM_TX 

Definition at line 231 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 
TAILMSG 
MACRO_NOTFOUND 
MACRO_BUSY 
LASTNODEKEY 
FULLSTATUS 
MEMNOTFOUND 
INVFREQ 
REMMODE 
REMLOGIN 
REMXXX 
REMSHORTSTATUS 
REMLONGSTATUS 
LOGINREQ 
SCAN 
SCANSTAT 
TUNE 
SETREMOTE 
TIMEOUT_WARNING 
ACT_TIMEOUT_WARNING 
LINKUNKEY 
UNAUTHTX 

Definition at line 233 of file app_rpt.c.

anonymous enum

Enumerator:
REM_SIMPLEX 
REM_MINUS 
REM_PLUS 

Definition at line 242 of file app_rpt.c.

anonymous enum

Enumerator:
REM_LOWPWR 
REM_MEDPWR 
REM_HIPWR 

Definition at line 244 of file app_rpt.c.

anonymous enum

Enumerator:
DC_INDETERMINATE 
DC_REQ_FLUSH 
DC_ERROR 
DC_COMPLETE 
DC_COMPLETEQUIET 
DC_DOKEY 

Definition at line 246 of file app_rpt.c.

anonymous enum

Enumerator:
SOURCE_RPT 
SOURCE_LNK 
SOURCE_RMT 
SOURCE_PHONE 
SOURCE_DPHONE 

Definition at line 248 of file app_rpt.c.

anonymous enum

Enumerator:
DLY_TELEM 
DLY_ID 
DLY_UNKEY 
DLY_CALLTERM 
DLY_COMP 
DLY_LINKUNKEY 

Definition at line 250 of file app_rpt.c.

anonymous enum

Enumerator:
REM_MODE_FM 
REM_MODE_USB 
REM_MODE_LSB 
REM_MODE_AM 

Definition at line 252 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 254 of file app_rpt.c.

anonymous enum

Enumerator:
TOP_TOP 
TOP_WON 
WON_BEFREAD 
BEFREAD_AFTERREAD 

Definition at line 357 of file app_rpt.c.


Function Documentation

static void __kickshort ( struct rpt myrpt  )  [static]

Definition at line 1395 of file app_rpt.c.

References LINKLISTSHORTTIME, rpt_link::linklisttimer, rpt::links, rpt_link::name, and rpt_link::next.

Referenced by connect_link(), and rpt().

01396 {
01397 struct rpt_link *l;
01398 
01399    for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01400    {
01401       /* if is not a real link, ignore it */
01402       if (l->name[0] == '0') continue;
01403       l->linklisttimer = LINKLISTSHORTTIME;
01404    }
01405    return;
01406 }

static void __mklinklist ( struct rpt myrpt,
struct rpt_link mylink,
char *  buf 
) [static]

Definition at line 1346 of file app_rpt.c.

References rpt_link::linklist, rpt::links, MAXLINKLIST, rpt_link::mode, rpt_link::name, rpt_link::next, and rpt_link::thisconnected.

Referenced by connect_link(), rpt(), rpt_do_nodes(), and rpt_tele_thread().

01347 {
01348 struct rpt_link *l;
01349 char mode;
01350 int   i,spos;
01351 
01352    buf[0] = 0; /* clear output buffer */
01353    /* go thru all links */
01354    for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
01355    {
01356       /* if is not a real link, ignore it */
01357       if (l->name[0] == '0') continue;
01358       /* dont count our stuff */
01359       if (l == mylink) continue;
01360       if (mylink && (!strcmp(l->name,mylink->name))) continue;
01361       /* figure out mode to report */
01362       mode = 'T'; /* use Tranceive by default */
01363       if (!l->mode) mode = 'R'; /* indicate RX for our mode */
01364       if (!l->thisconnected)  mode = 'C'; /* indicate connecting */
01365       spos = strlen(buf); /* current buf size (b4 we add our stuff) */
01366       if (spos)
01367       {
01368          strcat(buf,",");
01369          spos++;
01370       }
01371       /* add nodes into buffer */
01372       if (l->linklist[0])
01373       {
01374          snprintf(buf + spos,MAXLINKLIST - spos,
01375             "%c%s,%s",mode,l->name,l->linklist);
01376       }
01377       else /* if no nodes, add this node into buffer */
01378       {
01379          snprintf(buf + spos,MAXLINKLIST - spos,
01380             "%c%s",mode,l->name);
01381       }
01382       /* if we are in tranceive mode, let all modes stand */
01383       if (mode == 'T') continue;
01384       /* downgrade everyone on this node if appropriate */
01385       for(i = spos; buf[i]; i++)
01386       {
01387          if (buf[i] == 'T') buf[i] = mode;
01388          if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
01389       }
01390    }
01391    return;
01392 }

static void __reg_module ( void   )  [static]

Definition at line 11927 of file app_rpt.c.

static void __unreg_module ( void   )  [static]

Definition at line 11927 of file app_rpt.c.

int ast_playtones_start ( struct ast_channel chan,
int  vol,
const char *  tonelist,
int  interruptible 
)

Definition at line 212 of file indications.c.

References ast_activate_generator(), ast_log(), ast_realloc, ast_strdupa, playtones_item::duration, playtones_item::fac1, playtones_item::fac2, free, playtones_item::init_v2_1, playtones_item::init_v2_2, playtones_item::init_v3_1, playtones_item::init_v3_2, playtones_def::interruptible, playtones_def::items, LOG_WARNING, playtones_item::modulate, ast_channel::name, playtones_def::nitems, playtones, playtones_def::reppos, s, and playtones_def::vol.

Referenced by ast_app_dtget(), ast_indicate_data(), ast_senddigit_begin(), dialtone_indicate(), do_dtmf_local(), handle_playtones(), play_dialtone(), playtone(), read_exec(), and send_digit_to_chan().

00213 {
00214    char *s, *data = ast_strdupa(playlst); /* cute */
00215    struct playtones_def d = { vol, -1, 0, 1, NULL};
00216    char *stringp;
00217    char *separator;
00218    
00219    if (vol < 1)
00220       d.vol = 7219; /* Default to -8db */
00221 
00222    d.interruptible = interruptible;
00223    
00224    stringp=data;
00225    /* the stringp/data is not null here */
00226    /* check if the data is separated with '|' or with ',' by default */
00227    if (strchr(stringp,'|'))
00228       separator = "|";
00229    else
00230       separator = ",";
00231    s = strsep(&stringp,separator);
00232    while (s && *s) {
00233       int freq1, freq2, time, modulate=0, midinote=0;
00234 
00235       if (s[0]=='!')
00236          s++;
00237       else if (d.reppos == -1)
00238          d.reppos = d.nitems;
00239       if (sscanf(s, "%d+%d/%d", &freq1, &freq2, &time) == 3) {
00240          /* f1+f2/time format */
00241       } else if (sscanf(s, "%d+%d", &freq1, &freq2) == 2) {
00242          /* f1+f2 format */
00243          time = 0;
00244       } else if (sscanf(s, "%d*%d/%d", &freq1, &freq2, &time) == 3) {
00245          /* f1*f2/time format */
00246          modulate = 1;
00247       } else if (sscanf(s, "%d*%d", &freq1, &freq2) == 2) {
00248          /* f1*f2 format */
00249          time = 0;
00250          modulate = 1;
00251       } else if (sscanf(s, "%d/%d", &freq1, &time) == 2) {
00252          /* f1/time format */
00253          freq2 = 0;
00254       } else if (sscanf(s, "%d", &freq1) == 1) {
00255          /* f1 format */
00256          freq2 = 0;
00257          time = 0;
00258       } else if (sscanf(s, "M%d+M%d/%d", &freq1, &freq2, &time) == 3) {
00259          /* Mf1+Mf2/time format */
00260          midinote = 1;
00261       } else if (sscanf(s, "M%d+M%d", &freq1, &freq2) == 2) {
00262          /* Mf1+Mf2 format */
00263          time = 0;
00264          midinote = 1;
00265       } else if (sscanf(s, "M%d*M%d/%d", &freq1, &freq2, &time) == 3) {
00266          /* Mf1*Mf2/time format */
00267          modulate = 1;
00268          midinote = 1;
00269       } else if (sscanf(s, "M%d*M%d", &freq1, &freq2) == 2) {
00270          /* Mf1*Mf2 format */
00271          time = 0;
00272          modulate = 1;
00273          midinote = 1;
00274       } else if (sscanf(s, "M%d/%d", &freq1, &time) == 2) {
00275          /* Mf1/time format */
00276          freq2 = -1;
00277          midinote = 1;
00278       } else if (sscanf(s, "M%d", &freq1) == 1) {
00279          /* Mf1 format */
00280          freq2 = -1;
00281          time = 0;
00282          midinote = 1;
00283       } else {
00284          ast_log(LOG_WARNING,"%s: tone component '%s' of '%s' is no good\n",chan->name,s,playlst);
00285          return -1;
00286       }
00287 
00288       if (midinote) {
00289          /* midi notes must be between 0 and 127 */
00290          if ((freq1 >= 0) && (freq1 <= 127))
00291             freq1 = midi_tohz[freq1];
00292          else
00293             freq1 = 0;
00294 
00295          if ((freq2 >= 0) && (freq2 <= 127))
00296             freq2 = midi_tohz[freq2];
00297          else
00298             freq2 = 0;
00299       }
00300 
00301       if (!(d.items = ast_realloc(d.items, (d.nitems + 1) * sizeof(*d.items)))) {
00302          return -1;
00303       }
00304       d.items[d.nitems].fac1 = 2.0 * cos(2.0 * M_PI * (freq1 / 8000.0)) * 32768.0;
00305       d.items[d.nitems].init_v2_1 = sin(-4.0 * M_PI * (freq1 / 8000.0)) * d.vol;
00306       d.items[d.nitems].init_v3_1 = sin(-2.0 * M_PI * (freq1 / 8000.0)) * d.vol;
00307 
00308       d.items[d.nitems].fac2 = 2.0 * cos(2.0 * M_PI * (freq2 / 8000.0)) * 32768.0;
00309       d.items[d.nitems].init_v2_2 = sin(-4.0 * M_PI * (freq2 / 8000.0)) * d.vol;
00310       d.items[d.nitems].init_v3_2 = sin(-2.0 * M_PI * (freq2 / 8000.0)) * d.vol;
00311       d.items[d.nitems].duration = time;
00312       d.items[d.nitems].modulate = modulate;
00313       d.nitems++;
00314 
00315       s = strsep(&stringp,separator);
00316    }
00317 
00318    if (ast_activate_generator(chan, &playtones, &d)) {
00319       free(d.items);
00320       return -1;
00321    }
00322    return 0;
00323 }

void ast_playtones_stop ( struct ast_channel chan  ) 

Stop the tones from playing

Definition at line 325 of file indications.c.

References ast_deactivate_generator().

Referenced by ast_app_dtget(), ast_indicate_data(), ast_senddigit_end(), disa_exec(), handle_stopplaytones(), playtone(), read_exec(), and stop_indicate().

00326 {
00327    ast_deactivate_generator(chan);
00328 }

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

Definition at line 8404 of file app_rpt.c.

References ast_call(), AST_FORMAT_SLINEAR, ast_log(), ast_request(), ast_set_read_format(), ast_set_write_format(), ast_verbose(), free, rpt::links, rpt::lock, LOG_NOTICE, rpt::name, rpt_link::name, rpt_link::next, node_lookup(), option_verbose, rpt_mutex_lock, rpt_mutex_unlock, s, strdup, and VERBOSE_PREFIX_3.

Referenced by rpt().

08405 {
08406    char *val, *s, *s1, *s2, *tele;
08407    char tmp[300], deststr[300] = "";
08408 
08409    val = node_lookup(myrpt,l->name);
08410    if (!val)
08411    {
08412       fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
08413       return -1;
08414    }
08415 
08416    rpt_mutex_lock(&myrpt->lock);
08417    /* remove from queue */
08418    remque((struct qelem *) l);
08419    rpt_mutex_unlock(&myrpt->lock);
08420    strncpy(tmp,val,sizeof(tmp) - 1);
08421    s = tmp;
08422    s1 = strsep(&s,",");
08423    s2 = strsep(&s,",");
08424    snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
08425    tele = strchr(deststr, '/');
08426    if (!tele) {
08427       fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
08428       return -1;
08429    }
08430    *tele++ = 0;
08431    l->elaptime = 0;
08432    l->connecttime = 0;
08433    l->thisconnected = 0;
08434    l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
08435    if (l->chan){
08436       ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
08437       ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
08438       l->chan->whentohangup = 0;
08439       l->chan->appl = "Apprpt";
08440       l->chan->data = "(Remote Rx)";
08441       if (option_verbose > 2)
08442          ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
08443             deststr, tele, l->chan->name);
08444       if(l->chan->cid.cid_num)
08445          free(l->chan->cid.cid_num);
08446       l->chan->cid.cid_num = strdup(myrpt->name);
08447                 ast_call(l->chan,tele,999); 
08448 
08449    }
08450    else 
08451    {
08452       if (option_verbose > 2)
08453          ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
08454             deststr,tele,l->chan->name);
08455       return -1;
08456    }
08457    rpt_mutex_lock(&myrpt->lock);
08458    /* put back in queue */
08459    insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
08460    rpt_mutex_unlock(&myrpt->lock);
08461    ast_log(LOG_NOTICE,"Reconnect Attempt to %s in process\n",l->name);
08462    return 0;
08463 }

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

Definition at line 7403 of file app_rpt.c.

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

Referenced by function_remote().

07404 {
07405    if(!strcmp(myrpt->remote, remote_rig_ft897))
07406       return check_freq_ft897(m, d, defmode);
07407    else if(!strcmp(myrpt->remote, remote_rig_ic706))
07408       return check_freq_ic706(m, d, defmode);
07409    else if(!strcmp(myrpt->remote, remote_rig_rbi))
07410       return check_freq_rbi(m, d, defmode);
07411    else if(!strcmp(myrpt->remote, remote_rig_kenwood))
07412       return check_freq_kenwood(m, d, defmode);
07413    else
07414       return -1;
07415 }

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

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

06419 {
06420    int dflmd = REM_MODE_FM;
06421 
06422    if(m == 1){ /* 160 meters */
06423       dflmd =  REM_MODE_LSB; 
06424       if(d < 80000)
06425          return -1;
06426    }
06427    else if(m == 3){ /* 80 meters */
06428       dflmd = REM_MODE_LSB;
06429       if(d < 50000)
06430          return -1;
06431    }
06432    else if(m == 7){ /* 40 meters */
06433       dflmd = REM_MODE_LSB;
06434       if(d > 30000)
06435          return -1;
06436    }
06437    else if(m == 14){ /* 20 meters */
06438       dflmd = REM_MODE_USB;
06439       if(d > 35000)
06440          return -1;
06441    }
06442    else if(m == 18){ /* 17 meters */
06443       dflmd = REM_MODE_USB;
06444       if((d < 6800) || (d > 16800))
06445          return -1;
06446    }
06447    else if(m == 21){ /* 15 meters */
06448       dflmd = REM_MODE_USB;
06449       if((d < 20000) || (d > 45000))
06450          return -1;
06451    }
06452    else if(m == 24){ /* 12 meters */
06453       dflmd = REM_MODE_USB;
06454       if((d < 89000) || (d > 99000))
06455          return -1;
06456    }
06457    else if(m == 28){ /* 10 meters */
06458       dflmd = REM_MODE_USB;
06459    }
06460    else if(m == 29){ 
06461       if(d >= 51000)
06462          dflmd = REM_MODE_FM;
06463       else
06464          dflmd = REM_MODE_USB;
06465       if(d > 70000)
06466          return -1;
06467    }
06468    else if(m == 50){ /* 6 meters */
06469       if(d >= 30000)
06470          dflmd = REM_MODE_FM;
06471       else
06472          dflmd = REM_MODE_USB;
06473 
06474    }
06475    else if((m >= 51) && ( m < 54)){
06476       dflmd = REM_MODE_FM;
06477    }
06478    else if(m == 144){ /* 2 meters */
06479       if(d >= 30000)
06480          dflmd = REM_MODE_FM;
06481       else
06482          dflmd = REM_MODE_USB;
06483    }
06484    else if((m >= 145) && (m < 148)){
06485       dflmd = REM_MODE_FM;
06486    }
06487    else if((m >= 430) && (m < 450)){ /* 70 centimeters */
06488       if(m  < 438)
06489          dflmd = REM_MODE_USB;
06490       else
06491          dflmd = REM_MODE_FM;
06492       ;
06493    }
06494    else
06495       return -1;
06496 
06497    if(defmode)
06498       *defmode = dflmd;
06499 
06500    return 0;
06501 }

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

Definition at line 6789 of file app_rpt.c.

References REM_MODE_FM, REM_MODE_LSB, and REM_MODE_USB.

Referenced by check_freq(), and multimode_bump_freq_ic706().

06790 {
06791    int dflmd = REM_MODE_FM;
06792 
06793    if(m == 1){ /* 160 meters */
06794       dflmd =  REM_MODE_LSB; 
06795       if(d < 80000)
06796          return -1;
06797    }
06798    else if(m == 3){ /* 80 meters */
06799       dflmd = REM_MODE_LSB;
06800       if(d < 50000)
06801          return -1;
06802    }
06803    else if(m == 7){ /* 40 meters */
06804       dflmd = REM_MODE_LSB;
06805       if(d > 30000)
06806          return -1;
06807    }
06808    else if(m == 14){ /* 20 meters */
06809       dflmd = REM_MODE_USB;
06810       if(d > 35000)
06811          return -1;
06812    }
06813    else if(m == 18){ /* 17 meters */
06814       dflmd = REM_MODE_USB;
06815       if((d < 6800) || (d > 16800))
06816          return -1;
06817    }
06818    else if(m == 21){ /* 15 meters */
06819       dflmd = REM_MODE_USB;
06820       if((d < 20000) || (d > 45000))
06821          return -1;
06822    }
06823    else if(m == 24){ /* 12 meters */
06824       dflmd = REM_MODE_USB;
06825       if((d < 89000) || (d > 99000))
06826          return -1;
06827    }
06828    else if(m == 28){ /* 10 meters */
06829       dflmd = REM_MODE_USB;
06830    }
06831    else if(m == 29){ 
06832       if(d >= 51000)
06833          dflmd = REM_MODE_FM;
06834       else
06835          dflmd = REM_MODE_USB;
06836       if(d > 70000)
06837          return -1;
06838    }
06839    else if(m == 50){ /* 6 meters */
06840       if(d >= 30000)
06841          dflmd = REM_MODE_FM;
06842       else
06843          dflmd = REM_MODE_USB;
06844 
06845    }
06846    else if((m >= 51) && ( m < 54)){
06847       dflmd = REM_MODE_FM;
06848    }
06849    else if(m == 144){ /* 2 meters */
06850       if(d >= 30000)
06851          dflmd = REM_MODE_FM;
06852       else
06853          dflmd = REM_MODE_USB;
06854    }
06855    else if((m >= 145) && (m < 148)){
06856       dflmd = REM_MODE_FM;
06857    }
06858    else if((m >= 430) && (m < 450)){ /* 70 centimeters */
06859       if(m  < 438)
06860          dflmd = REM_MODE_USB;
06861       else
06862          dflmd = REM_MODE_FM;
06863       ;
06864    }
06865    else
06866       return -1;
06867 
06868    if(defmode)
06869       *defmode = dflmd;
06870 
06871    return 0;
06872 }

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

Definition at line 6280 of file app_rpt.c.

References REM_MODE_FM.

Referenced by check_freq().

06281 {
06282    int dflmd = REM_MODE_FM;
06283 
06284    if (m == 144){ /* 2 meters */
06285       if(d < 10100)
06286          return -1;
06287    }
06288    else if((m >= 145) && (m < 148)){
06289       ;
06290    }
06291    else if((m >= 430) && (m < 450)){ /* 70 centimeters */
06292       ;
06293    }
06294    else
06295       return -1;
06296    
06297    if(defmode)
06298       *defmode = dflmd; 
06299 
06300 
06301    return 0;
06302 }

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

Definition at line 6308 of file app_rpt.c.

References REM_MODE_FM.

Referenced by check_freq().

06309 {
06310    int dflmd = REM_MODE_FM;
06311 
06312    if(m == 50){ /* 6 meters */
06313       if(d < 10100)
06314          return -1;
06315    }
06316    else if((m >= 51) && ( m < 54)){
06317                 ;
06318    }
06319    else if(m == 144){ /* 2 meters */
06320       if(d < 10100)
06321          return -1;
06322    }
06323    else if((m >= 145) && (m < 148)){
06324       ;
06325    }
06326    else if((m >= 222) && (m < 225)){ /* 1.25 meters */
06327       ;
06328    }
06329    else if((m >= 430) && (m < 450)){ /* 70 centimeters */
06330       ;
06331    }
06332    else if((m >= 1240) && (m < 1300)){ /* 23 centimeters */
06333       ;
06334    }
06335    else
06336       return -1;
06337    
06338    if(defmode)
06339       *defmode = dflmd; 
06340 
06341 
06342    return 0;
06343 }

static char check_tx_freq ( struct rpt myrpt  )  [static]

Definition at line 7421 of file app_rpt.c.

References ast_log(), ast_variable_browse(), rpt::cfg, decimals2int(), eatwhite(), finddelim(), rpt::freq, LOG_NOTICE, LOG_WARNING, rpt::loginlevel, rpt::loginuser, MAXREMSTR, ast_variable::name, ast_variable::next, rpt::p, s, split_freq(), rpt::txlimitsstanzaname, and ast_variable::value.

07422 {
07423    int i;
07424    int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
07425    char radio_mhz_char[MAXREMSTR];
07426    char radio_decimals_char[MAXREMSTR];
07427    char limit_mhz_char[MAXREMSTR];
07428    char limit_decimals_char[MAXREMSTR];
07429    char limits[256];
07430    char *limit_ranges[40];
07431    struct ast_variable *limitlist;
07432    
07433 
07434    /* Must have user logged in and tx_limits defined */
07435 
07436    if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
07437       if(debug > 3){
07438          ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in\n");
07439       }
07440       return 1; /* Assume it's ok otherwise */
07441    }
07442 
07443    /* Retrieve the band table for the loginlevel */
07444    limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
07445 
07446    if(!limitlist){
07447       ast_log(LOG_WARNING, "No entries in %s band table stanza\n", myrpt->p.txlimitsstanzaname);
07448       return 0;
07449    }
07450 
07451    split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
07452    radio_mhz = atoi(radio_mhz_char);
07453    radio_decimals = decimals2int(radio_decimals_char);
07454 
07455 
07456    if(debug > 3){
07457       ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
07458    }
07459 
07460    /* Find our entry */
07461 
07462    for(;limitlist; limitlist=limitlist->next){
07463       if(!strcmp(limitlist->name, myrpt->loginlevel))
07464          break;
07465    }
07466 
07467    if(!limitlist){
07468       ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
07469       return 0;
07470    }
07471    
07472    if(debug > 3){
07473       ast_log(LOG_NOTICE, "Auth %s = %s\n", limitlist->name, limitlist->value);
07474    }
07475 
07476    /* Parse the limits */
07477 
07478    strncpy(limits, limitlist->value, 256);
07479    limits[255] = 0;
07480    finddelim(limits, limit_ranges, 40);
07481    for(i = 0; i < 40 && limit_ranges[i] ; i++){
07482       char range[40];
07483       char *r,*s;
07484       strncpy(range, limit_ranges[i], 40);
07485       range[39] = 0;
07486                 if(debug > 3){
07487          ast_log(LOG_NOTICE, "Checking to see if %s is within limits of %s\n", myrpt->freq, range);
07488                 }        
07489    
07490       r = strchr(range, '-');
07491       if(!r){
07492          ast_log(LOG_WARNING, "Malformed range in %s tx band table entry\n", limitlist->name);
07493          return 0;
07494       }
07495       *r++ = 0;
07496       s = eatwhite(range);
07497       r = eatwhite(r);
07498       split_freq(limit_mhz_char, limit_decimals_char, s);
07499       llimit_mhz = atoi(limit_mhz_char);
07500       llimit_decimals = decimals2int(limit_decimals_char);
07501       split_freq(limit_mhz_char, limit_decimals_char, r);
07502       ulimit_mhz = atoi(limit_mhz_char);
07503       ulimit_decimals = decimals2int(limit_decimals_char);
07504          
07505       if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
07506          if(radio_mhz == llimit_mhz){ /* CASE 1: TX freq is in llimit mhz portion of band */
07507             if(radio_decimals >= llimit_decimals){ /* Cannot be below llimit decimals */
07508                if(llimit_mhz == ulimit_mhz){ /* If bandwidth < 1Mhz, check ulimit decimals */
07509                   if(radio_decimals <= ulimit_decimals){
07510                      return 1;
07511                   }
07512                   else{
07513                      if(debug > 3)
07514                         ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
07515                      return 0;
07516                   }
07517                }
07518                else{
07519                   return 1;
07520                }
07521             }
07522             else{ /* Is below llimit decimals */
07523                if(debug > 3)
07524                   ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
07525                return 0;
07526             }
07527          }
07528          else if(radio_mhz == ulimit_mhz){ /* CASE 2: TX freq not in llimit mhz portion of band */
07529             if(radio_decimals <= ulimit_decimals){
07530                return 1;
07531             }
07532             else{ /* Is above ulimit decimals */
07533                if(debug > 3)
07534                   ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
07535                return 0;
07536             }
07537          }
07538          else /* CASE 3: TX freq within a multi-Mhz band and ok */
07539             return 1; 
07540       }
07541    }
07542    if(debug > 3) /* No match found in TX band table */
07543       ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 4\n");
07544    return 0;
07545 }

static int civ_cmd ( struct rpt myrpt,
unsigned char *  cmd,
int  cmdlen 
) [static]

Definition at line 5956 of file app_rpt.c.

References serial_remote_io().

Referenced by mem2vfo_ic706(), select_mem_ic706(), set_ctcss_mode_ic706(), set_freq_ic706(), simple_command_ic706(), and vfo_ic706().

05957 {
05958 unsigned char rxbuf[100];
05959 int   i,rv ;
05960 
05961    rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
05962    if (rv == -1) return(-1);
05963    if (rv != (cmdlen + 6)) return(1);
05964    for(i = 0; i < 6; i++)
05965       if (rxbuf[i] != cmd[i]) return(1);
05966    if (rxbuf[cmdlen] != 0xfe) return(1);
05967    if (rxbuf[cmdlen + 1] != 0xfe) return(1);
05968    if (rxbuf[cmdlen + 4] != 0xfb) return(1);
05969    if (rxbuf[cmdlen + 5] != 0xfd) return(1);
05970    return(0);
05971 }

static int closerem ( struct rpt myrpt  )  [static]

Definition at line 7391 of file app_rpt.c.

References closerem_ft897(), and rpt::remote.

07392 {
07393    if(!strcmp(myrpt->remote, remote_rig_ft897))
07394       return closerem_ft897(myrpt);
07395    else
07396       return 0;
07397 }

static int closerem_ft897 ( struct rpt myrpt  )  [static]

Definition at line 6729 of file app_rpt.c.

References simple_command_ft897().

Referenced by closerem().

06730 {
06731    simple_command_ft897(myrpt, 0x88); /* PTT off */
06732    return 0;
06733 }  

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

Definition at line 5226 of file app_rpt.c.

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

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

05228 {
05229    int i;
05230    char *stringp,*action,*param,*functiondigits;
05231    char function_table_name[30] = "";
05232    char workstring[200];
05233    
05234    struct ast_variable *vp;
05235    
05236    if(debug)   
05237       printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
05238    
05239    if (command_source == SOURCE_DPHONE) {
05240       if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
05241       strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
05242       }
05243    else if (command_source == SOURCE_PHONE) {
05244       if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
05245       strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
05246       }
05247    else if (command_source == SOURCE_LNK)
05248       strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
05249    else
05250       strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
05251    vp = ast_variable_browse(myrpt->cfg, function_table_name);
05252    while(vp) {
05253       if(!strncasecmp(vp->name, digits, strlen(vp->name)))
05254          break;
05255       vp = vp->next;
05256    }  
05257    if(!vp) {
05258       int n;
05259 
05260       n = myrpt->longestfunc;
05261       if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
05262       else 
05263       if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
05264       else 
05265       if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
05266       
05267       if(strlen(digits) >= n)
05268          return DC_ERROR;
05269       else
05270          return DC_INDETERMINATE;
05271    }  
05272    /* Found a match, retrieve value part and parse */
05273    strncpy(workstring, vp->value, sizeof(workstring) - 1 );
05274    stringp = workstring;
05275    action = strsep(&stringp, ",");
05276    param = stringp;
05277    if(debug)
05278       printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
05279    /* Look up the action */
05280    for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
05281       if(!strncasecmp(action, function_table[i].action, strlen(action)))
05282          break;
05283    }
05284    if(debug)
05285       printf("@@@@ table index i = %d\n",i);
05286    if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
05287       /* Error, action not in table */
05288       return DC_ERROR;
05289    }
05290    if(function_table[i].function == NULL){
05291       /* Error, function undefined */
05292       if(debug)
05293          printf("@@@@ NULL for action: %s\n",action);
05294       return DC_ERROR;
05295    }
05296    functiondigits = digits + strlen(vp->name);
05297    return (*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
05298 }

static int connect_link ( struct rpt myrpt,
char *  node,
int  mode,
int  perma 
) [static]

Definition at line 4466 of file app_rpt.c.

References __kickshort(), __mklinklist(), rpt::archivedir, ast_call(), AST_CDR_FLAG_POST_DISABLED, AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_request(), ast_set_flag, ast_set_read_format(), ast_set_write_format(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_true(), rpt_link::chan, rpt::conf, rpt_link::disced, donodelog(), finddelim(), free, rpt::lastlinknode, rpt::links, rpt::lock, LOG_NOTICE, LOG_WARNING, rpt::longestnode, malloc, MAX_RETRIES, rpt_link::max_retries, MAX_RETRIES_PERM, MAXLINKLIST, MAXNODESTR, rpt_link::mode, rpt::name, rpt_link::name, rpt_link::next, node_lookup(), rpt::p, rpt_link::reconnects, rpt_link::retries, rpt_mutex_lock, rpt_mutex_unlock, s, and strdup.

Referenced by function_ilink().

04467 {
04468    char *val, *s, *s1, *s2, *tele;
04469    char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
04470    char tmp[300], deststr[300] = "",modechange = 0;
04471    struct rpt_link *l;
04472    int reconnects = 0;
04473    int i,n;
04474    struct dahdi_confinfo ci;  /* conference info */
04475 
04476    val = node_lookup(myrpt,node);
04477    if (!val){
04478       if(strlen(node) >= myrpt->longestnode)
04479          return -1; /* No such node */
04480       return 1; /* No match yet */
04481    }
04482    if(debug > 3){
04483       ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
04484       ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
04485       ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
04486    }
04487 
04488    strncpy(tmp,val,sizeof(tmp) - 1);
04489    s = tmp;
04490    s1 = strsep(&s,",");
04491    s2 = strsep(&s,",");
04492    rpt_mutex_lock(&myrpt->lock);
04493    l = myrpt->links.next;
04494    /* try to find this one in queue */
04495    while(l != &myrpt->links){
04496       if (l->name[0] == '0') 
04497       {
04498          l = l->next;
04499          continue;
04500       }
04501    /* if found matching string */
04502       if (!strcmp(l->name, node))
04503          break;
04504       l = l->next;
04505    }
04506    /* if found */
04507    if (l != &myrpt->links){ 
04508    /* if already in this mode, just ignore */
04509       if ((l->mode) || (!l->chan)) {
04510          rpt_mutex_unlock(&myrpt->lock);
04511          return 2; /* Already linked */
04512       }
04513       reconnects = l->reconnects;
04514       rpt_mutex_unlock(&myrpt->lock);
04515       if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
04516       l->retries = l->max_retries + 1;
04517       l->disced = 2;
04518       modechange = 1;
04519    } else
04520    {
04521       __mklinklist(myrpt,NULL,lstr);
04522       rpt_mutex_unlock(&myrpt->lock);
04523       n = finddelim(lstr,strs,MAXLINKLIST);
04524       for(i = 0; i < n; i++)
04525       {
04526          if ((*strs[i] < '0') || 
04527              (*strs[i] > '9')) strs[i]++;
04528          if (!strcmp(strs[i],node))
04529          {
04530             return 2; /* Already linked */
04531          }
04532       }
04533    }
04534    strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
04535    /* establish call */
04536    l = malloc(sizeof(struct rpt_link));
04537    if (!l)
04538    {
04539       ast_log(LOG_WARNING, "Unable to malloc\n");
04540       return -1;
04541    }
04542    /* zero the silly thing */
04543    memset((char *)l,0,sizeof(struct rpt_link));
04544    l->mode = mode;
04545    l->outbound = 1;
04546    l->thisconnected = 0;
04547    strncpy(l->name, node, MAXNODESTR - 1);
04548    l->isremote = (s && ast_true(s));
04549    if (modechange) l->connected = 1;
04550    l->hasconnected = l->perma = perma;
04551 #ifdef ALLOW_LOCAL_CHANNELS
04552    if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
04553          strncpy(deststr, s1, sizeof(deststr));
04554    else
04555            snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
04556 #else
04557    snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
04558 #endif
04559    tele = strchr(deststr, '/');
04560    if (!tele){
04561       ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
04562       free(l);
04563       return -1;
04564    }
04565    *tele++ = 0;
04566    l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
04567    if (l->chan){
04568       ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
04569       ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
04570 #ifdef   AST_CDR_FLAG_POST_DISABLED
04571       ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
04572 #endif
04573       l->chan->whentohangup = 0;
04574       l->chan->appl = "Apprpt";
04575       l->chan->data = "(Remote Rx)";
04576       if (debug > 3)
04577          ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
04578       deststr, tele, l->chan->name);
04579       if(l->chan->cid.cid_num)
04580          free(l->chan->cid.cid_num);
04581       l->chan->cid.cid_num = strdup(myrpt->name);
04582       ast_call(l->chan,tele,999);
04583    }
04584    else {
04585       if(debug > 3) 
04586          ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
04587       deststr,tele,l->chan->name);
04588       if (myrpt->p.archivedir)
04589       {
04590          char str[100];
04591          sprintf(str,"LINKFAIL,%s",l->name);
04592          donodelog(myrpt,str);
04593       }
04594       free(l);
04595       return -1;
04596    }
04597    /* allocate a pseudo-channel thru asterisk */
04598    l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04599    if (!l->pchan){
04600       ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
04601       ast_hangup(l->chan);
04602       free(l);
04603       return -1;
04604    }
04605    ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
04606    ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
04607 #ifdef   AST_CDR_FLAG_POST_DISABLED
04608    ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
04609 #endif
04610    /* make a conference for the tx */
04611    ci.chan = 0;
04612    ci.confno = myrpt->conf;
04613    ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
04614    /* first put the channel on the conference in proper mode */
04615    if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
04616    {
04617       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04618       ast_hangup(l->chan);
04619       ast_hangup(l->pchan);
04620       free(l);
04621       return -1;
04622    }
04623    rpt_mutex_lock(&myrpt->lock);
04624    l->reconnects = reconnects;
04625    /* insert at end of queue */
04626    l->max_retries = MAX_RETRIES;
04627    if (perma)
04628       l->max_retries = MAX_RETRIES_PERM;
04629    if (l->isremote) l->retries = l->max_retries + 1;
04630    insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
04631    __kickshort(myrpt);
04632    rpt_mutex_unlock(&myrpt->lock);
04633    return 0;
04634 }

static int decimals2int ( char *  fraction  )  [static]

Definition at line 6349 of file app_rpt.c.

Referenced by check_tx_freq().

06350 {
06351    int i;
06352    char len = strlen(fraction);
06353    int multiplier = 100000;
06354    int res = 0;
06355 
06356    if(!len)
06357       return 0;
06358    for( i = 0 ; i < len ; i++, multiplier /= 10)
06359       res += (fraction[i] - '0') * multiplier;
06360    return res;
06361 }

static long diskavail ( struct rpt myrpt  )  [static]

Definition at line 1023 of file app_rpt.c.

References rpt::archivedir, ast_log(), LOG_WARNING, rpt::name, and rpt::p.

Referenced by rpt().

01024 {
01025 struct   statfs statfsbuf;
01026 
01027    if (!myrpt->p.archivedir) return(0);
01028    if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
01029    {
01030       ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
01031          myrpt->p.archivedir,myrpt->name);
01032       return(-1);
01033    }
01034    return(statfsbuf.f_bavail);
01035 }

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

Definition at line 1088 of file app_rpt.c.

References ast_log(), ast_playtones_start(), DTMF_LOCAL_STARTTIME, rpt::dtmf_local_str, DTMF_LOCAL_TIME, rpt::dtmf_local_timer, rpt::lock, LOG_DEBUG, ast_channel::name, rpt_mutex_lock, rpt_mutex_unlock, and rpt::txchannel.

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

01089 {
01090 int   i;
01091 char  digit;
01092 static const char* dtmf_tones[] = {
01093    "!941+1336/200,!0/200", /* 0 */
01094    "!697+1209/200,!0/200", /* 1 */
01095    "!697+1336/200,!0/200", /* 2 */
01096    "!697+1477/200,!0/200", /* 3 */
01097    "!770+1209/200,!0/200", /* 4 */
01098    "!770+1336/200,!0/200", /* 5 */
01099    "!770+1477/200,!0/200", /* 6 */
01100    "!852+1209/200,!0/200", /* 7 */
01101    "!852+1336/200,!0/200", /* 8 */
01102    "!852+1477/200,!0/200", /* 9 */
01103    "!697+1633/200,!0/200", /* A */
01104    "!770+1633/200,!0/200", /* B */
01105    "!852+1633/200,!0/200", /* C */
01106    "!941+1633/200,!0/200", /* D */
01107    "!941+1209/200,!0/200", /* * */
01108    "!941+1477/200,!0/200" };  /* # */
01109 
01110 
01111    if (c)
01112    {
01113       snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
01114       if (!myrpt->dtmf_local_timer) 
01115           myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
01116    }
01117    /* if at timeout */
01118    if (myrpt->dtmf_local_timer == 1)
01119    {
01120       /* if anything in the string */
01121       if (myrpt->dtmf_local_str[0])
01122       {
01123          digit = myrpt->dtmf_local_str[0];
01124          myrpt->dtmf_local_str[0] = 0;
01125          for(i = 1; myrpt->dtmf_local_str[i]; i++)
01126          {
01127             myrpt->dtmf_local_str[i - 1] =
01128                myrpt->dtmf_local_str[i];
01129          }
01130          myrpt->dtmf_local_str[i - 1] = 0;
01131          myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
01132          rpt_mutex_unlock(&myrpt->lock);
01133          if (digit >= '0' && digit <='9')
01134             ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
01135          else if (digit >= 'A' && digit <= 'D')
01136             ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
01137          else if (digit == '*')
01138             ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
01139          else if (digit == '#')
01140             ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
01141          else {
01142             /* not handled */
01143             ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
01144          }
01145          rpt_mutex_lock(&myrpt->lock);
01146       }
01147       else
01148       {
01149          myrpt->dtmf_local_timer = 0;
01150       }
01151    }
01152 }

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

Definition at line 1037 of file app_rpt.c.

References ast_senddigit(), rpt_link::chan, rpt::links, rpt_link::next, and rpt_link::phonemode.

Referenced by handle_link_data(), and local_dtmf_helper().

01038 {
01039 struct        rpt_link *l;
01040 
01041        l = myrpt->links.next;
01042        /* go thru all the links */
01043        while(l != &myrpt->links)
01044        {
01045                if (!l->phonemode)
01046                {
01047                        l = l->next;
01048                        continue;
01049                }
01050                /* dont send to self */
01051                if (mylink && (l == mylink))
01052                {
01053                        l = l->next;
01054                        continue;
01055                }
01056                if (l->chan) ast_senddigit(l->chan,c);
01057                l = l->next;
01058        }
01059        return;
01060 }

static void do_scheduler ( struct rpt myrpt  )  [static]

Definition at line 8639 of file app_rpt.c.

References ast_log(), ast_variable_browse(), ast_variable_retrieve(), rpt::cfg, rpt::curtv, rpt::dailyexecdcommands, rpt::dailykerchunks, rpt::dailykeyups, rpt::dailytxtime, LOG_NOTICE, LOG_WARNING, rpt::macro, rpt::macrobuf, MACROTIME, rpt::macrotimer, MAXMACRO, ast_variable::name, ast_variable::next, rpt::p, rpt::remote, rpt_localtime(), rpt::s, rpt::skedstanzaname, rpt::sysstate_cur, and ast_variable::value.

Referenced by rpt().

08640 {
08641    int i,res;
08642    struct tm tmnow;
08643    struct ast_variable *skedlist;
08644    char *strs[5],*vp,*val,value[100];
08645 
08646    memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
08647    
08648    if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
08649       ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
08650 
08651    /* Try to get close to a 1 second resolution */
08652    
08653    if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
08654       return;
08655 
08656    rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
08657 
08658    /* If midnight, then reset all daily statistics */
08659    
08660    if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
08661       myrpt->dailykeyups = 0;
08662       myrpt->dailytxtime = 0;
08663       myrpt->dailykerchunks = 0;
08664       myrpt->dailyexecdcommands = 0;
08665    }
08666 
08667    if(tmnow.tm_sec != 0)
08668       return;
08669 
08670    /* Code below only executes once per minute */
08671 
08672 
08673    /* Don't schedule if remote */
08674 
08675         if (myrpt->remote)
08676                 return;
08677 
08678    /* Don't schedule if disabled */
08679 
08680         if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
08681       if(debug > 6)
08682          ast_log(LOG_NOTICE, "Scheduler disabled\n");
08683       return;
08684    }
08685 
08686    if(!myrpt->p.skedstanzaname){ /* No stanza means we do nothing */
08687       if(debug > 6)
08688          ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
08689       return;
08690    }
08691 
08692         /* get pointer to linked list of scheduler entries */
08693         skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
08694 
08695    if(debug > 6){
08696       ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
08697          tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday); 
08698    }
08699    /* walk the list */
08700    for(; skedlist; skedlist = skedlist->next){
08701       if(debug > 6)
08702          ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
08703       strncpy(value,skedlist->value,99);
08704       value[99] = 0;
08705       /* point to the substrings for minute, hour, dom, month, and dow */
08706       for( i = 0, vp = value ; i < 5; i++){
08707          if(!*vp)
08708             break;
08709          while((*vp == ' ') || (*vp == 0x09)) /* get rid of any leading white space */
08710             vp++;
08711          strs[i] = vp; /* save pointer to beginning of substring */
08712          while((*vp != ' ') && (*vp != 0x09) && (*vp != 0)) /* skip over substring */
08713             vp++;
08714          if(*vp)
08715             *vp++ = 0; /* mark end of substring */
08716       }
08717       if(debug > 6)
08718          ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
08719             strs[0], strs[1], strs[2], strs[3], strs[4]); 
08720       if(i == 5){
08721          if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
08722             continue;
08723          if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
08724             continue;
08725          if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
08726             continue;
08727          if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
08728             continue;
08729          if(atoi(strs[4]) == 7)
08730             strs[4] = "0";
08731          if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
08732             continue;
08733          if(debug)
08734             ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
08735          if(atoi(skedlist->name) == 0)
08736             return; /* Zero is reserved for the startup macro */
08737          val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
08738          if (!val){
08739             ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
08740             return; /* Macro not found */
08741          }
08742          if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
08743             ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
08744                skedlist->name);
08745             return; /* Macro buffer full */
08746          }
08747          myrpt->macrotimer = MACROTIME;
08748          strncat(myrpt->macrobuf,val,MAXMACRO - strlen(myrpt->macrobuf) - 1);
08749       }
08750       else{
08751          ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
08752             skedlist->name, skedlist->value);
08753       }
08754    }
08755 
08756 }

static void donodelog ( struct rpt myrpt,
char *  str 
) [static]

Definition at line 1063 of file app_rpt.c.

References nodelog::archivedir, rpt::archivedir, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_ERROR, malloc, rpt::name, nodeloglock, rpt::p, nodelog::prev, nodelog::str, and nodelog::timestamp.

Referenced by connect_link(), function_remote(), handle_link_data(), handle_link_phone_dtmf(), handle_remote_data(), handle_remote_phone_dtmf(), local_dtmf_helper(), rpt(), and setrem().

01064 {
01065 struct nodelog *nodep;
01066 char  datestr[100];
01067 
01068    if (!myrpt->p.archivedir) return;
01069    nodep = (struct nodelog *)malloc(sizeof(struct nodelog));
01070    if (nodep == NULL)
01071    {
01072       ast_log(LOG_ERROR,"Cannot get memory for node log");
01073       return;
01074    }
01075    time(&nodep->timestamp);
01076    strncpy(nodep->archivedir,myrpt->p.archivedir,
01077       sizeof(nodep->archivedir) - 1);
01078    strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
01079       localtime(&nodep->timestamp));
01080    snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
01081       myrpt->name,datestr,str);
01082    ast_mutex_lock(&nodeloglock);
01083    insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
01084    ast_mutex_unlock(&nodeloglock);
01085 }

static char* eatwhite ( char *  s  )  [static]

Definition at line 1286 of file app_rpt.c.

Referenced by check_tx_freq().

01287 {
01288    while((*s == ' ') || (*s == 0x09)){ /* get rid of any leading white space */
01289       if(!*s)
01290          break;
01291       s++;
01292    }
01293    return s;
01294 }

static int finddelim ( char *  str,
char *  strp[],
int  limit 
) [static]

Definition at line 1306 of file app_rpt.c.

References DELIMCHR, and QUOTECHR.

Referenced by check_tx_freq(), connect_link(), function_autopatchup(), function_ilink(), load_rpt_vars(), rpt_do_nodes(), and rpt_tele_thread().

01307 {
01308 int     i,l,inquo;
01309 
01310         inquo = 0;
01311         i = 0;
01312         strp[i++] = str;
01313         if (!*str)
01314            {
01315                 strp[0] = 0;
01316                 return(0);
01317            }
01318         for(l = 0; *str && (l < limit) ; str++)
01319            {
01320                 if (*str == QUOTECHR)
01321                    {
01322                         if (inquo)
01323                            {
01324                                 *str = 0;
01325                                 inquo = 0;
01326                            }
01327                         else
01328                            {
01329                                 strp[i - 1] = str + 1;
01330                                 inquo = 1;
01331                            }
01332       }
01333                 if ((*str == DELIMCHR) && (!inquo))
01334                 {
01335                         *str = 0;
01336          l++;
01337                         strp[i++] = str + 1;
01338                 }
01339            }
01340         strp[i] = 0;
01341         return(i);
01342 
01343 }

static char func_xlat ( struct rpt myrpt,
char  c,
struct rpt_xlat xlat 
) [static]

Definition at line 1241 of file app_rpt.c.

References rpt::endchar, rpt_xlat::endcharseq, rpt_xlat::endindex, rpt::funcchar, rpt_xlat::funccharseq, rpt_xlat::funcindex, rpt_xlat::lastone, MAXXLATTIME, rpt::p, and rpt_xlat::passchars.

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

01242 {
01243 time_t   now;
01244 int   gotone;
01245 
01246    time(&now);
01247    gotone = 0;
01248    /* if too much time, reset the skate machine */
01249    if ((now - xlat->lastone) > MAXXLATTIME)
01250    {
01251       xlat->funcindex = xlat->endindex = 0;
01252    }
01253    if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
01254    {
01255       time(&xlat->lastone);
01256       gotone = 1;
01257       if (!xlat->funccharseq[xlat->funcindex])
01258       {
01259          xlat->funcindex = xlat->endindex = 0;
01260          return(myrpt->p.funcchar);
01261       }
01262    } else xlat->funcindex = 0;
01263    if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
01264    {
01265       time(&xlat->lastone);
01266       gotone = 1;
01267       if (!xlat->endcharseq[xlat->endindex])
01268       {
01269          xlat->funcindex = xlat->endindex = 0;
01270          return(myrpt->p.endchar);
01271       }
01272    } else xlat->endindex = 0;
01273    /* if in middle of decode seq, send nothing back */
01274    if (gotone) return(0);
01275    /* if no pass chars specified, return em all */
01276    if (!xlat->passchars[0]) return(c);
01277    /* if a "pass char", pass it */
01278    if (strchr(xlat->passchars,c)) return(c);
01279    return(0);
01280 }

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

Definition at line 4997 of file app_rpt.c.

References rpt::callmode, DC_COMPLETE, DC_ERROR, rpt::lock, rpt::p, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), rpt::s, rpt::sysstate_cur, and TERM.

04998 {
04999    if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
05000       return DC_ERROR;
05001    
05002    if(debug)
05003       printf("@@@@ Autopatch down\n");
05004       
05005    rpt_mutex_lock(&myrpt->lock);
05006    
05007    if (!myrpt->callmode){
05008       rpt_mutex_unlock(&myrpt->lock);
05009       return DC_COMPLETE;
05010    }
05011    
05012    myrpt->callmode = 0;
05013    rpt_mutex_unlock(&myrpt->lock);
05014    rpt_telemetry(myrpt, TERM, NULL);
05015    return DC_COMPLETE;
05016 }

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

Definition at line 4900 of file app_rpt.c.

References ast_log(), ast_pthread_create, ast_strdupa, rpt::callmode, rpt::cidx, DC_COMPLETE, DC_ERROR, rpt::endchar, rpt::exten, finddelim(), rpt::lock, LOG_ERROR, matchkeyword(), MAXPATCHCONTEXT, rpt::mydtmf, rpt::ourcontext, rpt::p, rpt::patchcontext, rpt::patchdialtime, rpt::patchfarenddisconnect, rpt::patchnoct, rpt::patchquiet, rpt_call(), rpt::rpt_call_thread, rpt_mutex_lock, rpt_mutex_unlock, rpt::s, skipchars(), and rpt::sysstate_cur.

04901 {
04902    pthread_attr_t attr;
04903    int i, index, paramlength;
04904    char *lparam;
04905    char *value = NULL;
04906    char *paramlist[20];
04907 
04908    static char *keywords[] = {
04909    "context",
04910    "dialtime",
04911    "farenddisconnect",
04912    "noct",
04913    "quiet",
04914    NULL
04915    };
04916       
04917    if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
04918       return DC_ERROR;
04919       
04920    if(debug)
04921       printf("@@@@ Autopatch up\n");
04922 
04923    if(!myrpt->callmode){
04924       /* Set defaults */
04925       myrpt->patchnoct = 0;
04926       myrpt->patchdialtime = 0;
04927       myrpt->patchfarenddisconnect = 0;
04928       myrpt->patchquiet = 0;
04929       strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
04930 
04931       if(param){
04932          /* Process parameter list */
04933          lparam = ast_strdupa(param);
04934          if(!lparam){
04935             ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
04936             return DC_ERROR;  
04937          }
04938          paramlength = finddelim(lparam, paramlist, 20);          
04939          for(i = 0; i < paramlength; i++){
04940             index = matchkeyword(paramlist[i], &value, keywords);
04941             if(value)
04942                value = skipchars(value, "= ");
04943             switch(index){
04944 
04945                case 1: /* context */
04946                   strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
04947                   break;
04948                   
04949                case 2: /* dialtime */
04950                   myrpt->patchdialtime = atoi(value);
04951                   break;
04952 
04953                case 3: /* farenddisconnect */
04954                   myrpt->patchfarenddisconnect = atoi(value);
04955                   break;
04956 
04957                case 4:  /* noct */
04958                   myrpt->patchnoct = atoi(value);
04959                   break;
04960 
04961                case 5: /* quiet */
04962                   myrpt->patchquiet = atoi(value);
04963                   break;
04964                            
04965                default:
04966                   break;
04967             }
04968          }
04969       }
04970    }
04971                
04972    rpt_mutex_lock(&myrpt->lock);
04973 
04974    /* if on call, force * into current audio stream */
04975    
04976    if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
04977       myrpt->mydtmf = myrpt->p.endchar;
04978    }
04979    if (myrpt->callmode){
04980       rpt_mutex_unlock(&myrpt->lock);
04981       return DC_COMPLETE;
04982    }
04983    myrpt->callmode = 1;
04984    myrpt->cidx = 0;
04985    myrpt->exten[myrpt->cidx] = 0;
04986    rpt_mutex_unlock(&myrpt->lock);
04987    pthread_attr_init(&attr);
04988    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04989    ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
04990    return DC_COMPLETE;
04991 }

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

Definition at line 5098 of file app_rpt.c.

References sysstate::alternatetail, ARB_ALPHA, sysstate::autopatchdisable, DC_COMPLETE, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, rpt::disgorgetime, sysstate::linkfundisable, myatoi(), rpt::p, rpt_telemetry(), rpt::s, sysstate::schedulerdisable, SOURCE_PHONE, rpt::stopgen, rpt::sysstate_cur, TEST_TONE, sysstate::totdisable, sysstate::txdisable, and sysstate::userfundisable.

05099 {
05100    char string[16];
05101 
05102    if(!param)
05103       return DC_ERROR;
05104    
05105    switch(myatoi(param)){
05106       case 1: /* System reset */
05107          system("killall -9 asterisk");
05108          return DC_COMPLETE;
05109 
05110       case 2:
05111          myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
05112          rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
05113          return DC_COMPLETE;
05114          
05115       case 3:
05116          myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
05117          return DC_COMPLETE;
05118          
05119       case 4: /* test tone on */
05120          if (myrpt->stopgen < 0) 
05121          {
05122             myrpt->stopgen = 1;
05123          }
05124          else 
05125          {
05126             myrpt->stopgen = 0;
05127             rpt_telemetry(myrpt, TEST_TONE, NULL);
05128          }
05129          return DC_COMPLETE;
05130 
05131       case 5: /* Disgorge variables to log for debug purposes */
05132          myrpt->disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
05133          return DC_COMPLETE;
05134 
05135       case 6: /* Simulate COR being activated (phone only) */
05136          if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
05137          return DC_DOKEY;  
05138 
05139 
05140       case 7: /* Time out timer enable */
05141          myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
05142          rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
05143          return DC_COMPLETE;
05144          
05145       case 8: /* Time out timer disable */
05146          myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
05147          rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
05148          return DC_COMPLETE;
05149 
05150                 case 9: /* Autopatch enable */
05151                         myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
05152                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
05153                         return DC_COMPLETE;
05154 
05155                 case 10: /* Autopatch disable */
05156                         myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
05157                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
05158                         return DC_COMPLETE;
05159 
05160                 case 11: /* Link Enable */
05161                         myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
05162                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
05163                         return DC_COMPLETE;
05164 
05165                 case 12: /* Link Disable */
05166                         myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
05167                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
05168                         return DC_COMPLETE;
05169 
05170       case 13: /* Query System State */
05171          string[0] = string[1] = 'S';
05172          string[2] = myrpt->p.sysstate_cur + '0';
05173          string[3] = '\0';
05174          rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
05175          return DC_COMPLETE;
05176 
05177       case 14: /* Change System State */
05178          if(strlen(digitbuf) == 0)
05179             break;
05180          if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
05181             return DC_ERROR;
05182          myrpt->p.sysstate_cur = digitbuf[0] - '0';
05183                         string[0] = string[1] = 'S';
05184                         string[2] = myrpt->p.sysstate_cur + '0';
05185                         string[3] = '\0';
05186                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
05187                         return DC_COMPLETE;
05188 
05189                 case 15: /* Scheduler Enable */
05190                         myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
05191                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
05192                         return DC_COMPLETE;
05193 
05194                 case 16: /* Scheduler Disable */
05195                         myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
05196                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
05197                         return DC_COMPLETE;
05198 
05199                 case 17: /* User functions Enable */
05200                         myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
05201                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
05202                         return DC_COMPLETE;
05203 
05204                 case 18: /* User Functions Disable */
05205                         myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
05206                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
05207                         return DC_COMPLETE;
05208 
05209                 case 19: /* Alternate Tail Enable */
05210                         myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
05211                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
05212                         return DC_COMPLETE;
05213 
05214                 case 20: /* Alternate Tail Disable */
05215                         myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
05216                         rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
05217                         return DC_COMPLETE;
05218    }  
05219    return DC_INDETERMINATE;
05220 }

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

Definition at line 4642 of file app_rpt.c.

References AST_FRAME_TEXT, ast_log(), ast_safe_sleep(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_write(), rpt_link::chan, rpt::cmdnode, COMPLETE, connect_link(), CONNFAIL, ast_frame::data, ast_frame::datalen, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt_link::disced, do_dtmf_local(), finddelim(), ast_frame::frametype, FULLSTATUS, rpt::lastlinknode, LASTNODEKEY, rpt::links, rpt::lock, LOG_NOTICE, rpt::longestnode, ast_frame::mallocd, MAX_RETRIES, rpt_link::max_retries, MAXLINKLIST, MAXNODESTR, mdc1200_notify(), rpt_link::mode, myatoi(), rpt::name, rpt_link::name, rpt_link::next, node_lookup(), ast_frame::offset, rpt::p, rpt_link::perma, rpt::propagate_dtmf, rpt::propagate_phonedtmf, REMALREADY, REMGO, rpt_link::retries, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), rpt::s, s, ast_frame::samples, rpt::savednodes, SOURCE_DPHONE, SOURCE_LNK, SOURCE_PHONE, SOURCE_RPT, STATUS, ast_frame::subclass, and rpt::sysstate_cur.

04643 {
04644 
04645    char *val, *s, *s1, *s2;
04646    char tmp[300];
04647    char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
04648    char mode,perma;
04649    struct rpt_link *l;
04650    int i,r;
04651 
04652    if(!param)
04653       return DC_ERROR;
04654       
04655          
04656    if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
04657       return DC_ERROR;
04658 
04659    strncpy(digitbuf,digits,MAXNODESTR - 1);
04660 
04661    if(debug > 6)
04662       printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
04663       
04664    switch(myatoi(param)){
04665       case 11: /* Perm Link off */
04666       case 1: /* Link off */
04667          if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
04668             strcpy(digitbuf,myrpt->lastlinknode);
04669          val = node_lookup(myrpt,digitbuf);
04670          if (!val){
04671             if(strlen(digitbuf) >= myrpt->longestnode)
04672                return DC_ERROR;
04673             break;
04674          }
04675          strncpy(tmp,val,sizeof(tmp) - 1);
04676          s = tmp;
04677          s1 = strsep(&s,",");
04678          s2 = strsep(&s,",");
04679          rpt_mutex_lock(&myrpt->lock);
04680          l = myrpt->links.next;
04681          /* try to find this one in queue */
04682          while(l != &myrpt->links){
04683             if (l->name[0] == '0') 
04684             {
04685                l = l->next;
04686                continue;
04687             }
04688             /* if found matching string */
04689             if (!strcmp(l->name, digitbuf))
04690                break;
04691             l = l->next;
04692          }
04693          if (l != &myrpt->links){ /* if found */
04694             struct   ast_frame wf;
04695 
04696             /* must use perm command on perm link */
04697             if ((myatoi(param) < 10) && 
04698                 (l->max_retries > MAX_RETRIES))
04699             {
04700                rpt_mutex_unlock(&myrpt->lock);
04701                return DC_COMPLETE;
04702             }
04703             strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
04704             l->retries = l->max_retries + 1;
04705             l->disced = 1;
04706             rpt_mutex_unlock(&myrpt->lock);
04707             wf.frametype = AST_FRAME_TEXT;
04708             wf.subclass = 0;
04709             wf.offset = 0;
04710             wf.mallocd = 0;
04711             wf.datalen = strlen(discstr) + 1;
04712             wf.samples = 0;
04713             wf.data = discstr;
04714             if (l->chan)
04715             {
04716                ast_write(l->chan,&wf);
04717                if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
04718                ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
04719             }
04720             rpt_telemetry(myrpt, COMPLETE, NULL);
04721             return DC_COMPLETE;
04722          }
04723          rpt_mutex_unlock(&myrpt->lock);  
04724          return DC_COMPLETE;
04725       case 2: /* Link Monitor */
04726       case 3: /* Link transceive */
04727       case 12: /* Link Monitor permanent */
04728       case 13: /* Link transceive permanent */
04729          if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
04730             strcpy(digitbuf,myrpt->lastlinknode);
04731          /* Attempt connection  */
04732          perma = (atoi(param) > 10) ? 1 : 0;
04733          mode = (atoi(param) & 1) ? 1 : 0;
04734          r = connect_link(myrpt, digitbuf, mode, perma);
04735          switch(r){
04736             case 0:
04737                rpt_telemetry(myrpt, COMPLETE, NULL);
04738                return DC_COMPLETE;
04739 
04740             case 1:
04741                break;
04742             
04743             case 2:
04744                rpt_telemetry(myrpt, REMALREADY, NULL);
04745                return DC_COMPLETE;
04746             
04747             default:
04748                rpt_telemetry(myrpt, CONNFAIL, NULL);
04749                return DC_COMPLETE;
04750          }
04751          break;
04752 
04753       case 4: /* Enter Command Mode */
04754       
04755          /* if doesnt allow link cmd, or no links active, return */
04756          if (((command_source != SOURCE_RPT) && 
04757             (command_source != SOURCE_PHONE) &&
04758             (command_source != SOURCE_DPHONE)) ||
04759              (myrpt->links.next == &myrpt->links))
04760             return DC_COMPLETE;
04761          
04762          /* if already in cmd mode, or selected self, fughetabahtit */
04763          if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
04764          
04765             rpt_telemetry(myrpt, REMALREADY, NULL);
04766             return DC_COMPLETE;
04767          }
04768          if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
04769             strcpy(digitbuf,myrpt->lastlinknode);
04770          /* node must at least exist in list */
04771          val = node_lookup(myrpt,digitbuf);
04772          if (!val){
04773             if(strlen(digitbuf) >= myrpt->longestnode)
04774                return DC_ERROR;
04775             break;
04776          
04777          }
04778          rpt_mutex_lock(&myrpt->lock);
04779          strcpy(myrpt->lastlinknode,digitbuf);
04780          strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
04781          rpt_mutex_unlock(&myrpt->lock);
04782          rpt_telemetry(myrpt, REMGO, NULL);  
04783          return DC_COMPLETE;
04784          
04785       case 5: /* Status */
04786          rpt_telemetry(myrpt, STATUS, NULL);
04787          return DC_COMPLETE;
04788 
04789       case 15: /* Full Status */
04790          rpt_telemetry(myrpt, FULLSTATUS, NULL);
04791          return DC_COMPLETE;
04792          
04793          
04794       case 6: /* All Links Off, including permalinks */
04795                        rpt_mutex_lock(&myrpt->lock);
04796          myrpt->savednodes[0] = 0;
04797                         l = myrpt->links.next;
04798                         /* loop through all links */
04799                         while(l != &myrpt->links){
04800             struct   ast_frame wf;
04801                                 if (l->name[0] == '0') /* Skip any IAXRPT monitoring */
04802                                 {
04803                                         l = l->next;
04804                                         continue;
04805                                 }
04806             /* Make a string of disconnected nodes for possible restoration */
04807             sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
04808             if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){ 
04809                if(myrpt->savednodes[0])
04810                   strcat(myrpt->savednodes, ",");
04811                strcat(myrpt->savednodes, tmp);
04812             }
04813                               l->retries = l->max_retries + 1;
04814                                 l->disced = 2; /* Silently disconnect */
04815                                 rpt_mutex_unlock(&myrpt->lock);
04816             /* ast_log(LOG_NOTICE,"dumping link %s\n",l->name); */
04817                                 
04818                                 wf.frametype = AST_FRAME_TEXT;
04819                                 wf.subclass = 0;
04820                                 wf.offset = 0;
04821                                 wf.mallocd = 0;
04822                                 wf.datalen = strlen(discstr) + 1;
04823                                 wf.samples = 0;
04824                                 wf.data = discstr;
04825                                 if (l->chan)
04826                                 {
04827                                         ast_write(l->chan,&wf);
04828                                         ast_safe_sleep(l->chan,250); /* It's dead already, why check the return value? */
04829                                         ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
04830                                 }
04831             rpt_mutex_lock(&myrpt->lock);
04832                                 l = l->next;
04833                         }
04834          rpt_mutex_unlock(&myrpt->lock);
04835          if(debug > 3)
04836             ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
04837                         rpt_telemetry(myrpt, COMPLETE, NULL);
04838          return DC_COMPLETE;
04839 
04840       case 7: /* Identify last node which keyed us up */
04841          rpt_telemetry(myrpt, LASTNODEKEY, NULL);
04842          break;
04843 
04844 
04845 #ifdef   _MDC_DECODE_H_
04846       case 8:
04847          myrpt->lastunit = 0xd00d; 
04848          mdc1200_notify(myrpt,NULL,myrpt->lastunit);
04849          mdc1200_send(myrpt,myrpt->lastunit);
04850          break;
04851 #endif
04852 
04853       case 16: /* Restore links disconnected with "disconnect all links" command */
04854          strcpy(tmp, myrpt->savednodes); /* Make a copy */
04855          finddelim(tmp, strs, MAXLINKLIST); /* convert into substrings */
04856          for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
04857             s1 = strs[i];
04858             mode = (s1[0] == 'X') ? 1 : 0;
04859             perma = (s1[1] == 'P') ? 1 : 0;
04860             connect_link(myrpt, s1 + 2, mode, perma); /* Try to reconnect */
04861          }
04862                         rpt_telemetry(myrpt, COMPLETE, NULL);
04863          break;
04864    
04865       case 200:
04866       case 201:
04867       case 202:
04868       case 203:
04869       case 204:
04870       case 205:
04871       case 206:
04872       case 207:
04873       case 208:
04874       case 209:
04875       case 210:
04876       case 211:
04877       case 212:
04878       case 213:
04879       case 214:
04880       case 215:
04881          if (((myrpt->p.propagate_dtmf) && 
04882               (command_source == SOURCE_LNK)) ||
04883              ((myrpt->p.propagate_phonedtmf) &&
04884             ((command_source == SOURCE_PHONE) ||
04885                 (command_source == SOURCE_DPHONE))))
04886                do_dtmf_local(myrpt,
04887                   remdtmfstr[myatoi(param) - 200]);
04888       default:
04889          return DC_ERROR;
04890          
04891    }
04892    
04893    return DC_INDETERMINATE;
04894 }  

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

Definition at line 5053 of file app_rpt.c.

References ast_variable_retrieve(), rpt::cfg, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt::lock, rpt::macro, MACRO_BUSY, rpt::macro_longest, MACRO_NOTFOUND, rpt::macrobuf, MACROTIME, rpt::macrotimer, MAXMACRO, rpt::p, rpt::remote, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), and rpt::startupmacro.

05054 {
05055 
05056 char  *val;
05057 int   i;
05058    if (myrpt->remote)
05059       return DC_ERROR;
05060 
05061    if(debug) 
05062       printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05063    
05064    if(strlen(digitbuf) < 1) /* needs 1 digit */
05065       return DC_INDETERMINATE;
05066          
05067    for(i = 0 ; i < digitbuf[i] ; i++) {
05068       if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
05069          return DC_ERROR;
05070    }
05071    
05072    if (*digitbuf == '0') val = myrpt->p.startupmacro;
05073    else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
05074    /* param was 1 for local buf */
05075    if (!val){
05076                 if (strlen(digitbuf) < myrpt->macro_longest)
05077                         return DC_INDETERMINATE;
05078       rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
05079       return DC_COMPLETE;
05080    }        
05081    rpt_mutex_lock(&myrpt->lock);
05082    if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
05083    {
05084       rpt_mutex_unlock(&myrpt->lock);
05085       rpt_telemetry(myrpt, MACRO_BUSY, NULL);
05086       return DC_ERROR;
05087    }
05088    myrpt->macrotimer = MACROTIME;
05089    strncat(myrpt->macrobuf, val, MAXMACRO - strlen(myrpt->macrobuf) - 1);
05090    rpt_mutex_unlock(&myrpt->lock);
05091    return DC_COMPLETE;  
05092 }

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

Definition at line 7748 of file app_rpt.c.

References rpt::archivedir, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_mutex_lock(), ast_mutex_unlock(), rpt::authlevel, check_freq(), DC_COMPLETE, DC_COMPLETEQUIET, DC_ERROR, DC_INDETERMINATE, do_dtmf_local(), donodelog(), free, 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, INVFREQ, rpt::lock, rpt::loginlevel, rpt::loginuser, MAXREMSTR, MEMNOTFOUND, multimode_bump_freq(), multimode_capable(), myatoi(), rpt::offset, offset, rpt::p, rpt::powerlevel, REM_HIPWR, REM_LOWPWR, REM_MEDPWR, REM_MINUS, REM_MODE_AM, REM_MODE_FM, REM_MODE_LSB, REM_MODE_USB, REM_PLUS, REM_SCANTIME, REM_SIMPLEX, REMLOGIN, REMLONGSTATUS, REMMODE, rpt::remmode, rpt::remote, rpt::remotetx, REMSHORTSTATUS, REMXXX, retreive_memory(), rpt_telemetry(), rpt::rxpl, rpt::rxplon, s, rpt::scantimer, setrem(), SOURCE_LNK, SOURCE_RPT, split_freq(), strdup, TUNE, rpt::tunerequest, rpt::txchannel, rpt::txpl, and rpt::txplon.

07749 {
07750    char *s,*s1,*s2;
07751    int i,j,p,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode;
07752    char multimode = 0;
07753    char oc,*cp,*cp1,*cp2;
07754    char tmp[20], freq[20] = "", savestr[20] = "";
07755    char mhz[MAXREMSTR], decimals[MAXREMSTR];
07756 
07757    if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
07758       return DC_ERROR;
07759       
07760    p = myatoi(param);
07761 
07762    if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel && 
07763       (!myrpt->loginlevel[0])) return DC_ERROR;
07764    multimode = multimode_capable(myrpt);
07765 
07766    switch(p){
07767 
07768       case 1:  /* retrieve memory */
07769          if(strlen(digitbuf) < 2) /* needs 2 digits */
07770             break;
07771          
07772          for(i = 0 ; i < 2 ; i++){
07773             if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07774                return DC_ERROR;
07775          }
07776        
07777          r = retreive_memory(myrpt, digitbuf);
07778          if (r < 0){
07779             rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
07780             return DC_COMPLETE;
07781          }
07782          if (r > 0){
07783             return DC_ERROR;
07784          }
07785          if (setrem(myrpt) == -1) return DC_ERROR;
07786          return DC_COMPLETE;  
07787          
07788       case 2:  /* set freq and offset */
07789       
07790          
07791             for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for M+*K+*O or M+*H+* depending on mode */
07792             if(digitbuf[i] == '*'){
07793                j++;
07794                continue;
07795             }
07796             if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07797                goto invalid_freq;
07798             else{
07799                if(j == 0)
07800                   l++; /* # of digits before first * */
07801                if(j == 1)
07802                   k++; /* # of digits after first * */
07803             }
07804          }
07805       
07806          i = strlen(digitbuf) - 1;
07807          if(multimode){
07808             if((j > 2) || (l > 3) || (k > 6))
07809                goto invalid_freq; /* &^@#! */
07810          }
07811          else{
07812             if((j > 2) || (l > 4) || (k > 3))
07813                goto invalid_freq; /* &^@#! */
07814          }
07815 
07816          /* Wait for M+*K+* */
07817 
07818          if(j < 2)
07819             break; /* Not yet */
07820 
07821          /* We have a frequency */
07822 
07823          strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
07824          
07825          s = tmp;
07826          s1 = strsep(&s, "*"); /* Pick off MHz */
07827          s2 = strsep(&s,"*"); /* Pick off KHz and Hz */
07828          ls2 = strlen(s2); 
07829          
07830          switch(ls2){ /* Allow partial entry of khz and hz digits for laziness support */
07831             case 1:
07832                ht = 0;
07833                k = 100 * atoi(s2);
07834                break;
07835             
07836             case 2:
07837                ht = 0;
07838                k = 10 * atoi(s2);
07839                break;
07840                
07841             case 3:
07842                if(!multimode){
07843                   if((s2[2] != '0')&&(s2[2] != '5'))
07844                      goto invalid_freq;
07845                }
07846                ht = 0;
07847                k = atoi(s2);
07848                   break;
07849             case 4:
07850                k = atoi(s2)/10;
07851                ht = 10 * (atoi(s2+(ls2-1)));
07852                break;
07853 
07854             case 5:
07855                k = atoi(s2)/100;
07856                ht = (atoi(s2+(ls2-2)));
07857                break;
07858                
07859             default:
07860                goto invalid_freq;
07861          }
07862 
07863          /* Check frequency for validity and establish a default mode */
07864          
07865          snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
07866 
07867          if(debug)
07868             printf("New frequency: %s\n", freq);      
07869    
07870          split_freq(mhz, decimals, freq);
07871          m = atoi(mhz);
07872          d = atoi(decimals);
07873 
07874                         if(check_freq(myrpt, m, d, &defmode)) /* Check to see if frequency entered is legit */
07875                                 goto invalid_freq;
07876 
07877 
07878          if((defmode == REM_MODE_FM) && (digitbuf[i] == '*')) /* If FM, user must enter and additional offset digit */
07879             break; /* Not yet */
07880 
07881 
07882          offset = REM_SIMPLEX; /* Assume simplex */
07883 
07884          if(defmode == REM_MODE_FM){
07885             oc = *s; /* Pick off offset */
07886          
07887             if (oc){
07888                switch(oc){
07889                   case '1':
07890                      offset = REM_MINUS;
07891                      break;
07892                   
07893                   case '2':
07894                      offset = REM_SIMPLEX;
07895                   break;
07896                   
07897                   case '3':
07898                      offset = REM_PLUS;
07899                      break;
07900                   
07901                   default:
07902                      goto invalid_freq;
07903                } 
07904             } 
07905          }  
07906          offsave = myrpt->offset;
07907          modesave = myrpt->remmode;
07908          strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
07909          strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
07910          myrpt->offset = offset;
07911          myrpt->remmode = defmode;
07912 
07913          if (setrem(myrpt) == -1){
07914             myrpt->offset = offsave;
07915             myrpt->remmode = modesave;
07916             strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
07917             goto invalid_freq;
07918          }
07919 
07920          return DC_COMPLETE;
07921 
07922 invalid_freq:
07923          rpt_telemetry(myrpt,INVFREQ,NULL);
07924          return DC_ERROR; 
07925       
07926       case 3: /* set rx PL tone */
07927             for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N */
07928             if(digitbuf[i] == '*'){
07929                j++;
07930                continue;
07931             }
07932             if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07933                return DC_ERROR;
07934             else{
07935                if(j)
07936                   l++;
07937                else
07938                   k++;
07939             }
07940          }
07941          if((j > 1) || (k > 3) || (l > 1))
07942             return DC_ERROR; /* &$@^! */
07943          i = strlen(digitbuf) - 1;
07944          if((j != 1) || (k < 2)|| (l != 1))
07945             break; /* Not yet */
07946          if(debug)
07947             printf("PL digits entered %s\n", digitbuf);
07948             
07949          strncpy(tmp, digitbuf, sizeof(tmp) - 1);
07950          /* see if we have at least 1 */
07951          s = strchr(tmp,'*');
07952          if(s)
07953             *s = '.';
07954          strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
07955          strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
07956          if(!strcmp(myrpt->remote, remote_rig_rbi))
07957          {
07958             strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
07959          }
07960          if (setrem(myrpt) == -1){
07961             strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
07962             return DC_ERROR;
07963          }
07964       
07965       
07966          return DC_COMPLETE;
07967       
07968       case 4: /* set tx PL tone */
07969          /* cant set tx tone on RBI (rx tone does both) */
07970          if(!strcmp(myrpt->remote, remote_rig_rbi))
07971             return DC_ERROR;
07972          if(!strcmp(myrpt->remote, remote_rig_ic706))
07973             return DC_ERROR;
07974             for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N */
07975             if(digitbuf[i] == '*'){
07976                j++;
07977                continue;
07978             }
07979             if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
07980                return DC_ERROR;
07981             else{
07982                if(j)
07983                   l++;
07984                else
07985                   k++;
07986             }
07987          }
07988          if((j > 1) || (k > 3) || (l > 1))
07989             return DC_ERROR; /* &$@^! */
07990          i = strlen(digitbuf) - 1;
07991          if((j != 1) || (k < 2)|| (l != 1))
07992             break; /* Not yet */
07993          if(debug)
07994             printf("PL digits entered %s\n", digitbuf);
07995             
07996          strncpy(tmp, digitbuf, sizeof(tmp) - 1);
07997          /* see if we have at least 1 */
07998          s = strchr(tmp,'*');
07999          if(s)
08000             *s = '.';
08001          strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
08002          strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
08003          
08004          if (setrem(myrpt) == -1){
08005             strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
08006             return DC_ERROR;
08007          }
08008       
08009       
08010          return DC_COMPLETE;
08011       
08012 
08013       case 6: /* MODE (FM,USB,LSB,AM) */
08014          if(strlen(digitbuf) < 1)
08015             break;
08016 
08017          if(!multimode)
08018             return DC_ERROR; /* Multimode radios only */
08019 
08020          switch(*digitbuf){
08021             case '1':
08022                split_freq(mhz, decimals, myrpt->freq); 
08023                m=atoi(mhz);
08024                if(m < 29) /* No FM allowed below 29MHz! */
08025                   return DC_ERROR;
08026                myrpt->remmode = REM_MODE_FM;
08027                
08028                rpt_telemetry(myrpt,REMMODE,NULL);
08029                break;
08030 
08031             case '2':
08032                myrpt->remmode = REM_MODE_USB;
08033                rpt_telemetry(myrpt,REMMODE,NULL);
08034                break;   
08035 
08036             case '3':
08037                myrpt->remmode = REM_MODE_LSB;
08038                rpt_telemetry(myrpt,REMMODE,NULL);
08039                break;
08040             
08041             case '4':
08042                myrpt->remmode = REM_MODE_AM;
08043                rpt_telemetry(myrpt,REMMODE,NULL);
08044                break;
08045       
08046             default:
08047                return DC_ERROR;
08048          }
08049 
08050          if(setrem(myrpt))
08051             return DC_ERROR;
08052          return DC_COMPLETEQUIET;
08053       case 99:
08054          /* cant log in when logged in */
08055          if (myrpt->loginlevel[0]) 
08056             return DC_ERROR;
08057          *myrpt->loginuser = 0;
08058          myrpt->loginlevel[0] = 0;
08059          cp = strdup(param);
08060          cp1 = strchr(cp,',');
08061          ast_mutex_lock(&myrpt->lock);
08062          if (cp1) 
08063          {
08064             *cp1 = 0;
08065             cp2 = strchr(cp1 + 1,',');
08066             if (cp2) 
08067             {
08068                *cp2 = 0;
08069                strncpy(myrpt->loginlevel,cp2 + 1,
08070                   sizeof(myrpt->loginlevel) - 1);
08071             }
08072             strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
08073             ast_mutex_unlock(&myrpt->lock);
08074             if (myrpt->p.archivedir)
08075             {
08076                char str[100];
08077 
08078                sprintf(str,"LOGIN,%s,%s",
08079                    myrpt->loginuser,myrpt->loginlevel);
08080                donodelog(myrpt,str);
08081             }
08082             if (debug) 
08083                printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
08084             rpt_telemetry(myrpt,REMLOGIN,NULL);
08085          }
08086          free(cp);
08087          return DC_COMPLETEQUIET;
08088       case 100: /* RX PL Off */
08089          myrpt->rxplon = 0;
08090          setrem(myrpt);
08091          rpt_telemetry(myrpt,REMXXX,(void *)p);
08092          return DC_COMPLETEQUIET;
08093       case 101: /* RX PL On */
08094          myrpt->rxplon = 1;
08095          setrem(myrpt);
08096          rpt_telemetry(myrpt,REMXXX,(void *)p);
08097          return DC_COMPLETEQUIET;
08098       case 102: /* TX PL Off */
08099          myrpt->txplon = 0;
08100          setrem(myrpt);
08101          rpt_telemetry(myrpt,REMXXX,(void *)p);
08102          return DC_COMPLETEQUIET;
08103       case 103: /* TX PL On */
08104          myrpt->txplon = 1;
08105          setrem(myrpt);
08106          rpt_telemetry(myrpt,REMXXX,(void *)p);
08107          return DC_COMPLETEQUIET;
08108       case 104: /* Low Power */
08109          if(!strcmp(myrpt->remote, remote_rig_ic706))
08110             return DC_ERROR;
08111          myrpt->powerlevel = REM_LOWPWR;
08112          setrem(myrpt);
08113          rpt_telemetry(myrpt,REMXXX,(void *)p);
08114          return DC_COMPLETEQUIET;
08115       case 105: /* Medium Power */
08116          if(!strcmp(myrpt->remote, remote_rig_ic706))
08117             return DC_ERROR;
08118          myrpt->powerlevel = REM_MEDPWR;
08119          setrem(myrpt);
08120          rpt_telemetry(myrpt,REMXXX,(void *)p);
08121          return DC_COMPLETEQUIET;
08122       case 106: /* Hi Power */
08123          if(!strcmp(myrpt->remote, remote_rig_ic706))
08124             return DC_ERROR;
08125          myrpt->powerlevel = REM_HIPWR;
08126          setrem(myrpt);
08127          rpt_telemetry(myrpt,REMXXX,(void *)p);
08128          return DC_COMPLETEQUIET;
08129       case 107: /* Bump down 20Hz */
08130          multimode_bump_freq(myrpt, -20);
08131          return DC_COMPLETE;
08132       case 108: /* Bump down 100Hz */
08133          multimode_bump_freq(myrpt, -100);
08134          return DC_COMPLETE;
08135       case 109: /* Bump down 500Hz */
08136          multimode_bump_freq(myrpt, -500);
08137          return DC_COMPLETE;
08138       case 110: /* Bump up 20Hz */
08139          multimode_bump_freq(myrpt, 20);
08140          return DC_COMPLETE;
08141       case 111: /* Bump up 100Hz */
08142          multimode_bump_freq(myrpt, 100);
08143          return DC_COMPLETE;
08144       case 112: /* Bump up 500Hz */
08145          multimode_bump_freq(myrpt, 500);
08146          return DC_COMPLETE;
08147       case 113: /* Scan down slow */
08148          myrpt->scantimer = REM_SCANTIME;
08149          myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
08150          rpt_telemetry(myrpt,REMXXX,(void *)p);
08151          return DC_COMPLETEQUIET;
08152       case 114: /* Scan down quick */
08153          myrpt->scantimer = REM_SCANTIME;
08154          myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
08155          rpt_telemetry(myrpt,REMXXX,(void *)p);
08156          return DC_COMPLETEQUIET;
08157       case 115: /* Scan down fast */
08158          myrpt->scantimer = REM_SCANTIME;
08159          myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
08160          rpt_telemetry(myrpt,REMXXX,(void *)p);
08161          return DC_COMPLETEQUIET;
08162       case 116: /* Scan up slow */
08163          myrpt->scantimer = REM_SCANTIME;
08164          myrpt->hfscanmode = HF_SCAN_UP_SLOW;
08165          rpt_telemetry(myrpt,REMXXX,(void *)p);
08166          return DC_COMPLETEQUIET;
08167       case 117: /* Scan up quick */
08168          myrpt->scantimer = REM_SCANTIME;
08169          myrpt->hfscanmode = HF_SCAN_UP_QUICK;
08170          rpt_telemetry(myrpt,REMXXX,(void *)p);
08171          return DC_COMPLETEQUIET;
08172       case 118: /* Scan up fast */
08173          myrpt->scantimer = REM_SCANTIME;
08174          myrpt->hfscanmode = HF_SCAN_UP_FAST;
08175          rpt_telemetry(myrpt,REMXXX,(void *)p);
08176          return DC_COMPLETEQUIET;
08177       case 119: /* Tune Request */
08178          /* if not currently going, and valid to do */
08179          if((!myrpt->tunerequest) && 
08180              ((!strcmp(myrpt->remote, remote_rig_ft897) || 
08181             !strcmp(myrpt->remote, remote_rig_ic706)) )) { 
08182             myrpt->remotetx = 0;
08183             ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
08184             myrpt->tunerequest = 1;
08185             rpt_telemetry(myrpt,TUNE,NULL);
08186             return DC_COMPLETEQUIET;
08187          }
08188          return DC_ERROR;        
08189       case 5: /* Long Status */
08190          rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
08191          return DC_COMPLETEQUIET;
08192       case 140: /* Short Status */
08193          rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
08194          return DC_COMPLETEQUIET;
08195       case 200:
08196       case 201:
08197       case 202:
08198       case 203:
08199       case 204:
08200       case 205:
08201       case 206:
08202       case 207:
08203       case 208:
08204       case 209:
08205       case 210:
08206       case 211:
08207       case 212:
08208       case 213:
08209       case 214:
08210       case 215:
08211          do_dtmf_local(myrpt,remdtmfstr[p - 200]);
08212          return DC_COMPLETEQUIET;
08213       default:
08214          break;
08215    }
08216    return DC_INDETERMINATE;
08217 }

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

Definition at line 5022 of file app_rpt.c.

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

05023 {
05024 
05025    if (!param)
05026       return DC_ERROR;
05027 
05028    if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
05029       return DC_ERROR;
05030 
05031    if(debug)
05032       printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
05033    
05034    switch(myatoi(param)){
05035       case 1: /* System ID */
05036          rpt_telemetry(myrpt, ID1, NULL);
05037          return DC_COMPLETE;
05038       case 2: /* System Time */
05039          rpt_telemetry(myrpt, STATS_TIME, NULL);
05040          return DC_COMPLETE;
05041       case 3: /* app_rpt.c version */
05042          rpt_telemetry(myrpt, STATS_VERSION, NULL);
05043       default:
05044          return DC_ERROR;
05045    }
05046    return DC_INDETERMINATE;
05047 }

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

Definition at line 2817 of file app_rpt.c.

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

Referenced by rpt_tele_thread(), and wait_interval().

02818 {
02819         int interval;
02820         char *wait_times;
02821         char *wait_times_save;
02822                                                                                                                   
02823         wait_times_save = NULL;
02824         wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
02825                                                                                                                   
02826         if(wait_times){
02827                 wait_times_save = ast_strdupa(wait_times);
02828                 if(!wait_times_save){
02829                         ast_log(LOG_WARNING, "Out of memory in wait_interval()\n");
02830                         wait_times = NULL;
02831                 }
02832         }
02833                                                                                                                   
02834         switch(type){
02835                 case DLY_TELEM:
02836                         if(wait_times)
02837                                 interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
02838                         else
02839                                 interval = 1000;
02840                         break;
02841                                                                                                                   
02842                 case DLY_ID:
02843                         if(wait_times)
02844                                 interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
02845                         else
02846                                 interval = 500;
02847                         break;
02848                                                                                                                   
02849                 case DLY_UNKEY:
02850                         if(wait_times)
02851                                 interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",500,5000,1000);
02852                         else
02853                                 interval = 1000;
02854                         break;
02855                                                                                                                   
02856                 case DLY_LINKUNKEY:
02857                         if(wait_times)
02858                                 interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
02859                         else
02860                                 interval = 1000;
02861                         break;
02862                                                                                                                   
02863                 case DLY_CALLTERM:
02864                         if(wait_times)
02865                                 interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
02866                         else
02867                                 interval = 1500;
02868                         break;
02869                                                                                                                   
02870                 case DLY_COMP:
02871                         if(wait_times)
02872                                 interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
02873                         else
02874                                 interval = 200;
02875                         break;
02876                                                                                                                   
02877                 default:
02878                         return 0;
02879         }
02880    return interval;
02881 }                                                                                                                  

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

Definition at line 5301 of file app_rpt.c.

References rpt::archivedir, ast_canmatch_extension(), ast_exists_extension(), AST_FRAME_TEXT, ast_log(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_write(), rpt::callmode, rpt_link::chan, rpt::cidx, collect_function_digits(), rpt::dailyexecdcommands, ast_frame::data, ast_frame::datalen, DC_COMPLETE, DC_COMPLETEQUIET, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, rpt_link::disced, do_dtmf_local(), do_dtmf_phone(), donodelog(), rpt::endchar, rpt::exten, ast_frame::frametype, func_xlat(), rpt::funcchar, rpt::lastdtmfcommand, rpt_link::linklist, rpt_link::linklistreceived, rpt::links, rpt::lock, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, rpt_link::max_retries, MAXDTMF, mdc1200_notify(), rpt::mydtmf, rpt_link::name, rpt::name, rpt_link::next, ast_frame::offset, rpt::outxlat, rpt::p, rpt::patchcontext, rpt::patchquiet, rpt::pchannel, PROC, rpt::propagate_dtmf, rpt::propagate_phonedtmf, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, rpt_link::retries, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), ast_frame::samples, seq, SOURCE_LNK, rpt::stopgen, ast_frame::subclass, and rpt::totalexecdcommands.

Referenced by rpt().

05303 {
05304 char  tmp[512],cmd[300] = "",dest[300],src[300],c;
05305 int   seq, res;
05306 struct rpt_link *l;
05307 struct   ast_frame wf;
05308 
05309    wf.frametype = AST_FRAME_TEXT;
05310    wf.subclass = 0;
05311    wf.offset = 0;
05312    wf.mallocd = 0;
05313    wf.datalen = strlen(str) + 1;
05314    wf.samples = 0;
05315    /* put string in our buffer */
05316    strncpy(tmp,str,sizeof(tmp) - 1);
05317 
05318         if (!strcmp(tmp,discstr))
05319         {
05320                 mylink->disced = 1;
05321       mylink->retries = mylink->max_retries + 1;
05322                 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
05323                 return;
05324         }
05325    if (tmp[0] == 'L')
05326    {
05327       rpt_mutex_lock(&myrpt->lock);
05328       strcpy(mylink->linklist,tmp + 2);
05329       time(&mylink->linklistreceived);
05330       rpt_mutex_unlock(&myrpt->lock);
05331       if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s recieved node list %s from node %s\n",
05332          myrpt->name,tmp,mylink->name);
05333       return;
05334    }
05335    if (tmp[0] == 'I')
05336    {
05337       if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
05338       {
05339          ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
05340          return;
05341       }
05342       mdc1200_notify(myrpt,src,seq);
05343       strcpy(dest,"*");
05344    }
05345    else
05346    {
05347       if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
05348       {
05349          ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
05350          return;
05351       }
05352       if (strcmp(cmd,"D"))
05353       {
05354          ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
05355          return;
05356       }
05357    }
05358    if (dest[0] == '0')
05359    {
05360       strcpy(dest,myrpt->name);
05361    }     
05362 
05363    /* if not for me, redistribute to all links */
05364    if (strcmp(dest,myrpt->name))
05365    {
05366       l = myrpt->links.next;
05367       /* see if this is one in list */
05368       while(l != &myrpt->links)
05369       {
05370          if (l->name[0] == '0') 
05371          {
05372             l = l->next;
05373             continue;
05374          }
05375          /* dont send back from where it came */
05376          if ((l == mylink) || (!strcmp(l->name,mylink->name)))
05377          {
05378             l = l->next;
05379             continue;
05380          }
05381          /* if it is, send it and we're done */
05382          if (!strcmp(l->name,dest))
05383          {
05384             /* send, but not to src */
05385             if (strcmp(l->name,src)) {
05386                wf.data = str;
05387                if (l->chan) ast_write(l->chan,&wf);
05388             }
05389             return;
05390          }
05391          l = l->next;
05392       }
05393       l = myrpt->links.next;
05394       /* otherwise, send it to all of em */
05395       while(l != &myrpt->links)
05396       {
05397          if (l->name[0] == '0') 
05398          {
05399             l = l->next;
05400             continue;
05401          }
05402          /* dont send back from where it came */
05403          if ((l == mylink) || (!strcmp(l->name,mylink->name)))
05404          {
05405             l = l->next;
05406             continue;
05407          }
05408          /* send, but not to src */
05409          if (strcmp(l->name,src)) {
05410             wf.data = str;
05411             if (l->chan) ast_write(l->chan,&wf); 
05412          }
05413          l = l->next;
05414       }
05415       return;
05416    }
05417    if (myrpt->p.archivedir)
05418    {
05419       char str[100];
05420 
05421       sprintf(str,"DTMF,%s,%c",mylink->name,c);
05422       donodelog(myrpt,str);
05423    }
05424    c = func_xlat(myrpt,c,&myrpt->p.outxlat);
05425    if (!c) return;
05426    rpt_mutex_lock(&myrpt->lock);
05427    if (c == myrpt->p.endchar) myrpt->stopgen = 1;
05428    if (myrpt->callmode == 1)
05429    {
05430       myrpt->exten[myrpt->cidx++] = c;
05431       myrpt->exten[myrpt->cidx] = 0;
05432       /* if this exists */
05433       if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
05434       {
05435          myrpt->callmode = 2;
05436          if(!myrpt->patchquiet){
05437             rpt_mutex_unlock(&myrpt->lock);
05438             rpt_telemetry(myrpt,PROC,NULL); 
05439             rpt_mutex_lock(&myrpt->lock);
05440          }
05441       }
05442       /* if can continue, do so */
05443       if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL)) 
05444       {
05445          /* call has failed, inform user */
05446          myrpt->callmode = 4;
05447       }
05448    }
05449    if (c == myrpt->p.funcchar)
05450    {
05451       myrpt->rem_dtmfidx = 0;
05452       myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05453       time(&myrpt->rem_dtmf_time);
05454       rpt_mutex_unlock(&myrpt->lock);
05455       return;
05456    } 
05457    else if (myrpt->rem_dtmfidx < 0)
05458    {
05459       if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
05460       {
05461          myrpt->mydtmf = c;
05462       }
05463       if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
05464       if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
05465       rpt_mutex_unlock(&myrpt->lock);
05466       return;
05467    }
05468    else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0))
05469    {
05470       time(&myrpt->rem_dtmf_time);
05471       if (myrpt->rem_dtmfidx < MAXDTMF)
05472       {
05473          myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
05474          myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05475          
05476          rpt_mutex_unlock(&myrpt->lock);
05477          strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
05478          res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
05479          rpt_mutex_lock(&myrpt->lock);
05480          
05481          switch(res){
05482 
05483             case DC_INDETERMINATE:
05484                break;
05485             
05486             case DC_REQ_FLUSH:
05487                myrpt->rem_dtmfidx = 0;
05488                myrpt->rem_dtmfbuf[0] = 0;
05489                break;
05490             
05491             
05492             case DC_COMPLETE:
05493             case DC_COMPLETEQUIET:
05494                myrpt->totalexecdcommands++;
05495                myrpt->dailyexecdcommands++;
05496                strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
05497                myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
05498                myrpt->rem_dtmfbuf[0] = 0;
05499                myrpt->rem_dtmfidx = -1;
05500                myrpt->rem_dtmf_time = 0;
05501                break;
05502             
05503             case DC_ERROR:
05504             default:
05505                myrpt->rem_dtmfbuf[0] = 0;
05506                myrpt->rem_dtmfidx = -1;
05507                myrpt->rem_dtmf_time = 0;
05508                break;
05509          }
05510       }
05511 
05512    }
05513    rpt_mutex_unlock(&myrpt->lock);
05514    return;
05515 }

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

Definition at line 5517 of file app_rpt.c.

References rpt::archivedir, ast_canmatch_extension(), ast_exists_extension(), rpt::callmode, rpt::cidx, rpt::cmdnode, collect_function_digits(), COMPLETE, rpt::dailyexecdcommands, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, donodelog(), rpt::dtmfbuf, rpt::dtmfidx, rpt::endchar, rpt::exten, rpt::funcchar, rpt::lastdtmfcommand, rpt_link::lastrx, rpt::lock, MAXDTMF, rpt::mydtmf, rpt_link::name, rpt::p, rpt::patchcontext, rpt::patchquiet, rpt::pchannel, rpt_link::phonemode, PROC, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), send_link_dtmf(), SOURCE_DPHONE, SOURCE_LNK, SOURCE_PHONE, rpt::stopgen, and rpt::totalexecdcommands.

Referenced by rpt().

05519 {
05520 
05521 char  cmd[300];
05522 int   res;
05523 
05524    if (myrpt->p.archivedir)
05525    {
05526       char str[100];
05527 
05528       sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
05529       donodelog(myrpt,str);
05530    }
05531    rpt_mutex_lock(&myrpt->lock);
05532    if (c == myrpt->p.endchar)
05533    {
05534       if (mylink->lastrx)
05535       {
05536          mylink->lastrx = 0;
05537          rpt_mutex_unlock(&myrpt->lock);
05538          return;
05539       }
05540       myrpt->stopgen = 1;
05541       if (myrpt->cmdnode[0])
05542       {
05543          myrpt->cmdnode[0] = 0;
05544          myrpt->dtmfidx = -1;
05545          myrpt->dtmfbuf[0] = 0;
05546          rpt_mutex_unlock(&myrpt->lock);
05547          rpt_telemetry(myrpt,COMPLETE,NULL);
05548          return;
05549       }
05550    }
05551    if (myrpt->cmdnode[0])
05552    {
05553       rpt_mutex_unlock(&myrpt->lock);
05554       send_link_dtmf(myrpt,c);
05555       return;
05556    }
05557    if (myrpt->callmode == 1)
05558    {
05559       myrpt->exten[myrpt->cidx++] = c;
05560       myrpt->exten[myrpt->cidx] = 0;
05561       /* if this exists */
05562       if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
05563       {
05564          myrpt->callmode = 2;
05565          if(!myrpt->patchquiet){
05566             rpt_mutex_unlock(&myrpt->lock);
05567             rpt_telemetry(myrpt,PROC,NULL); 
05568             rpt_mutex_lock(&myrpt->lock);
05569          }
05570       }
05571       /* if can continue, do so */
05572       if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL)) 
05573       {
05574          /* call has failed, inform user */
05575          myrpt->callmode = 4;
05576       }
05577    }
05578    if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
05579    {
05580       myrpt->mydtmf = c;
05581    }
05582    if (c == myrpt->p.funcchar)
05583    {
05584       myrpt->rem_dtmfidx = 0;
05585       myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05586       time(&myrpt->rem_dtmf_time);
05587       rpt_mutex_unlock(&myrpt->lock);
05588       return;
05589    } 
05590    else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0))
05591    {
05592       time(&myrpt->rem_dtmf_time);
05593       if (myrpt->rem_dtmfidx < MAXDTMF)
05594       {
05595          myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
05596          myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
05597          
05598          rpt_mutex_unlock(&myrpt->lock);
05599          strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
05600          switch(mylink->phonemode)
05601          {
05602              case 1:
05603             res = collect_function_digits(myrpt, cmd, 
05604                SOURCE_PHONE, mylink);
05605             break;
05606              case 2:
05607             res = collect_function_digits(myrpt, cmd, 
05608                SOURCE_DPHONE,mylink);
05609             break;
05610              default:
05611             res = collect_function_digits(myrpt, cmd, 
05612                SOURCE_LNK, mylink);
05613             break;
05614          }
05615 
05616          rpt_mutex_lock(&myrpt->lock);
05617          
05618          switch(res){
05619 
05620             case DC_INDETERMINATE:
05621                break;
05622             
05623             case DC_DOKEY:
05624                mylink->lastrx = 1;
05625                break;
05626             
05627             case DC_REQ_FLUSH:
05628                myrpt->rem_dtmfidx = 0;
05629                myrpt->rem_dtmfbuf[0] = 0;
05630                break;
05631             
05632             
05633             case DC_COMPLETE:
05634             case DC_COMPLETEQUIET:
05635                myrpt->totalexecdcommands++;
05636                myrpt->dailyexecdcommands++;
05637                strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
05638                myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
05639                myrpt->rem_dtmfbuf[0] = 0;
05640                myrpt->rem_dtmfidx = -1;
05641                myrpt->rem_dtmf_time = 0;
05642                break;
05643             
05644             case DC_ERROR:
05645             default:
05646                myrpt->rem_dtmfbuf[0] = 0;
05647                myrpt->rem_dtmfidx = -1;
05648                myrpt->rem_dtmf_time = 0;
05649                break;
05650          }
05651       }
05652 
05653    }
05654    rpt_mutex_unlock(&myrpt->lock);
05655    return;
05656 }

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

Definition at line 8330 of file app_rpt.c.

References rpt::archivedir, ast_log(), COMPLETE, donodelog(), func_xlat(), handle_remote_dtmf_digit(), LOG_WARNING, mdc1200_notify(), rpt::name, rpt::outxlat, rpt::p, rpt_telemetry(), and seq.

08331 {
08332 char  tmp[300],cmd[300],dest[300],src[300],c;
08333 int   seq,res;
08334 
08335    /* put string in our buffer */
08336    strncpy(tmp,str,sizeof(tmp) - 1);
08337    if (!strcmp(tmp,discstr)) return 0;
08338 
08339 #ifndef  DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
08340    if (tmp[0] == 'I')
08341    {
08342       if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
08343       {
08344          ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
08345          return 0;
08346       }
08347       mdc1200_notify(myrpt,src,seq);
08348       return 0;
08349    }
08350 #endif
08351    if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
08352    {
08353       ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
08354       return 0;
08355    }
08356    if (strcmp(cmd,"D"))
08357    {
08358       ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
08359       return 0;
08360    }
08361    /* if not for me, ignore */
08362    if (strcmp(dest,myrpt->name)) return 0;
08363    if (myrpt->p.archivedir)
08364    {
08365       char str[100];
08366 
08367       sprintf(str,"DTMF,%c",c);
08368       donodelog(myrpt,str);
08369    }
08370    c = func_xlat(myrpt,c,&myrpt->p.outxlat);
08371    if (!c) return(0);
08372    res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
08373    if (res != 1)
08374       return res;
08375    rpt_telemetry(myrpt,COMPLETE,NULL);
08376    return 0;
08377 }

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

Definition at line 8220 of file app_rpt.c.

References collect_function_digits(), rpt::dailyexecdcommands, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, do_dtmf_local(), rpt::dtmf_time_rem, DTMF_TIMEOUT, rpt::dtmfbuf, rpt::dtmfidx, rpt::funcchar, rpt::hfscanmode, rpt::last_activity_time, rpt::lastdtmfcommand, rpt::lock, MAXDTMF, rpt::p, rpt::propagate_dtmf, rpt_mutex_lock, rpt_mutex_unlock, SOURCE_DPHONE, SOURCE_PHONE, SOURCE_RMT, stop_scan(), and rpt::totalexecdcommands.

Referenced by handle_remote_data(), and handle_remote_phone_dtmf().

08221 {
08222 time_t   now;
08223 int   ret,res = 0,src;
08224 
08225    time(&myrpt->last_activity_time);
08226    /* Stop scan mode if in scan mode */
08227    if(myrpt->hfscanmode){
08228       stop_scan(myrpt);
08229       return 0;
08230    }
08231 
08232    time(&now);
08233    /* if timed-out */
08234    if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
08235    {
08236       myrpt->dtmfidx = -1;
08237       myrpt->dtmfbuf[0] = 0;
08238       myrpt->dtmf_time_rem = 0;
08239    }
08240    /* if decode not active */
08241    if (myrpt->dtmfidx == -1)
08242    {
08243       /* if not lead-in digit, dont worry */
08244       if (c != myrpt->p.funcchar)
08245       {
08246          if (!myrpt->p.propagate_dtmf)
08247          {
08248             rpt_mutex_lock(&myrpt->lock);
08249             do_dtmf_local(myrpt,c);
08250             rpt_mutex_unlock(&myrpt->lock);
08251          }
08252          return 0;
08253       }
08254       myrpt->dtmfidx = 0;
08255       myrpt->dtmfbuf[0] = 0;
08256       myrpt->dtmf_time_rem = now;
08257       return 0;
08258    }
08259    /* if too many in buffer, start over */
08260    if (myrpt->dtmfidx >= MAXDTMF)
08261    {
08262       myrpt->dtmfidx = 0;
08263       myrpt->dtmfbuf[0] = 0;
08264       myrpt->dtmf_time_rem = now;
08265    }
08266    if (c == myrpt->p.funcchar)
08267    {
08268       /* if star at beginning, or 2 together, erase buffer */
08269       if ((myrpt->dtmfidx < 1) || 
08270          (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
08271       {
08272          myrpt->dtmfidx = 0;
08273          myrpt->dtmfbuf[0] = 0;
08274          myrpt->dtmf_time_rem = now;
08275          return 0;
08276       }
08277    }
08278    myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
08279    myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
08280    myrpt->dtmf_time_rem = now;
08281    
08282    
08283    src = SOURCE_RMT;
08284    if (phonemode > 1) src = SOURCE_DPHONE;
08285    else if (phonemode) src = SOURCE_PHONE;
08286    ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
08287    
08288    switch(ret){
08289    
08290       case DC_INDETERMINATE:
08291          res = 0;
08292          break;
08293             
08294       case DC_DOKEY:
08295          if (keyed) *keyed = 1;
08296          res = 0;
08297          break;
08298             
08299       case DC_REQ_FLUSH:
08300          myrpt->dtmfidx = 0;
08301          myrpt->dtmfbuf[0] = 0;
08302          res = 0;
08303          break;
08304             
08305             
08306       case DC_COMPLETE:
08307          res = 1;
08308       case DC_COMPLETEQUIET:
08309          myrpt->totalexecdcommands++;
08310          myrpt->dailyexecdcommands++;
08311          strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
08312          myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
08313          myrpt->dtmfbuf[0] = 0;
08314          myrpt->dtmfidx = -1;
08315          myrpt->dtmf_time_rem = 0;
08316          break;
08317             
08318       case DC_ERROR:
08319       default:
08320          myrpt->dtmfbuf[0] = 0;
08321          myrpt->dtmfidx = -1;
08322          myrpt->dtmf_time_rem = 0;
08323          res = 0;
08324          break;
08325    }
08326 
08327    return res;
08328 }

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

Definition at line 8379 of file app_rpt.c.

References rpt::archivedir, COMPLETE, DC_INDETERMINATE, donodelog(), rpt::endchar, handle_remote_dtmf_digit(), rpt::p, and rpt_telemetry().

08380 {
08381 int   res;
08382 
08383 
08384    if (keyed && *keyed && (c == myrpt->p.endchar))
08385    {
08386       *keyed = 0;
08387       return DC_INDETERMINATE;
08388    }
08389 
08390    if (myrpt->p.archivedir)
08391    {
08392       char str[100];
08393 
08394       sprintf(str,"DTMF(P),%c",c);
08395       donodelog(myrpt,str);
08396    }
08397    res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
08398    if (res != 1)
08399       return res;
08400    rpt_telemetry(myrpt,COMPLETE,NULL);
08401    return 0;
08402 }

static int ic706_pltocode ( char *  str  )  [static]

Definition at line 6875 of file app_rpt.c.

References s.

Referenced by set_ic706().

06876 {
06877 int i;
06878 char *s;
06879 
06880    s = strchr(str,'.');
06881    i = 0;
06882    if (s) i = atoi(s + 1);
06883    i += atoi(str) * 10;
06884    switch(i)
06885    {
06886        case 670:
06887       return 0;
06888        case 693:
06889       return 1;
06890        case 719:
06891       return 2;
06892        case 744:
06893       return 3;
06894        case 770:
06895       return 4;
06896        case 797:
06897       return 5;
06898        case 825:
06899       return 6;
06900        case 854:
06901       return 7;
06902        case 885:
06903       return 8;
06904        case 915:
06905       return 9;
06906        case 948:
06907       return 10;
06908        case 974:
06909       return 11;
06910        case 1000:
06911       return 12;
06912        case 1035:
06913       return 13;
06914        case 1072:
06915       return 14;
06916        case 1109:
06917       return 15;
06918        case 1148:
06919       return 16;
06920        case 1188:
06921       return 17;
06922        case 1230:
06923       return 18;
06924        case 1273:
06925       return 19;
06926        case 1318:
06927       return 20;
06928        case 1365:
06929       return 21;
06930        case 1413:
06931       return 22;
06932        case 1462:
06933       return 23;
06934        case 1514:
06935       return 24;
06936        case 1567:
06937       return 25;
06938        case 1598:
06939       return 26;
06940        case 1622:
06941       return 27;
06942        case 1655:
06943       return 28;     
06944        case 1679:
06945       return 29;
06946        case 1713:
06947       return 30;
06948        case 1738:
06949       return 31;
06950        case 1773:
06951       return 32;
06952        case 1799:
06953       return 33;
06954             case 1835:
06955       return 34;
06956        case 1862:
06957       return 35;
06958        case 1899:
06959       return 36;
06960        case 1928:
06961       return 37;
06962        case 1966:
06963       return 38;
06964        case 1995:
06965       return 39;
06966        case 2035:
06967       return 40;
06968        case 2065:
06969       return 41;
06970        case 2107:
06971       return 42;
06972        case 2181:
06973       return 43;
06974        case 2257:
06975       return 44;
06976        case 2291:
06977       return 45;
06978        case 2336:
06979       return 46;
06980        case 2418:
06981       return 47;
06982        case 2503:
06983       return 48;
06984        case 2541:
06985       return 49;
06986    }
06987    return -1;
06988 }

static int kenwood_pltocode ( char *  str  )  [static]

Definition at line 5988 of file app_rpt.c.

References s.

Referenced by setkenwood().

05989 {
05990 int i;
05991 char *s;
05992 
05993    s = strchr(str,'.');
05994    i = 0;
05995    if (s) i = atoi(s + 1);
05996    i += atoi(str) * 10;
05997    switch(i)
05998    {
05999        case 670:
06000       return 1;
06001        case 719:
06002       return 3;
06003        case 744:
06004       return 4;
06005        case 770:
06006       return 5;
06007        case 797:
06008       return 6;
06009        case 825:
06010       return 7;
06011        case 854:
06012       return 8;
06013        case 885:
06014       return 9;
06015        case 915:
06016       return 10;
06017        case 948:
06018       return 11;
06019        case 974:
06020       return 12;
06021        case 1000:
06022       return 13;
06023        case 1035:
06024       return 14;
06025        case 1072:
06026       return 15;
06027        case 1109:
06028       return 16;
06029        case 1148:
06030       return 17;
06031        case 1188:
06032       return 18;
06033        case 1230:
06034       return 19;
06035        case 1273:
06036       return 20;
06037        case 1318:
06038       return 21;
06039        case 1365:
06040       return 22;
06041        case 1413:
06042       return 23;
06043        case 1462:
06044       return 24;
06045        case 1514:
06046       return 25;
06047        case 1567:
06048       return 26;
06049        case 1622:
06050       return 27;
06051        case 1679:
06052       return 28;
06053        case 1738:
06054       return 29;
06055        case 1799:
06056       return 30;
06057        case 1862:
06058       return 31;
06059        case 1928:
06060       return 32;
06061        case 2035:
06062       return 33;
06063        case 2107:
06064       return 34;
06065        case 2181:
06066       return 35;
06067        case 2257:
06068       return 36;
06069        case 2336:
06070       return 37;
06071        case 2418:
06072       return 38;
06073        case 2503:
06074       return 39;
06075    }
06076    return -1;
06077 }

static int load_module ( void   )  [static]

Definition at line 11873 of file app_rpt.c.

References ast_cli_register(), ast_pthread_create, ast_register_application(), cli_debug, cli_dump, cli_fun, cli_lstats, cli_nodes, cli_reload, cli_restart, cli_stats, rpt_exec(), and rpt_master().

static void load_rpt_vars ( int  n,
int  init 
) [static]

Definition at line 1620 of file app_rpt.c.

References rpt::acctcode, sysstate::alternatetail, rpt::althangtime, rpt::archivedir, ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), rpt::authlevel, sysstate::autopatchdisable, rpt::cfg, rpt::civaddr, rpt::csstanzaname, DEFAULT_CIV_ADDR, DEFAULT_IOBASE, DEFAULT_MONITOR_MIN_DISK_BLOCKS, DEFAULT_REMOTE_INACT_TIMEOUT, DEFAULT_REMOTE_TIMEOUT, DEFAULT_REMOTE_TIMEOUT_WARNING, DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ, desc, rpt::dphone_functions, rpt::dphone_longestfunc, rpt::duplex, ENDCHAR, rpt::endchar, rpt_xlat::endcharseq, rpt::extnodefile, EXTNODEFILE, rpt::extnodes, EXTNODES, finddelim(), FUNCCHAR, rpt::funcchar, rpt_xlat::funccharseq, rpt::functions, FUNCTIONS, HANGTIME, rpt::hangtime, rpt::ident, IDTIME, rpt::idtime, rpt::inxlat, rpt::iobase, rpt::ioport, rpt::link_functions, rpt::link_longestfunc, sysstate::linkfundisable, rpt::linktolink, lock, LOG_NOTICE, LOG_WARNING, rpt::longestfunc, rpt::longestnode, rpt::macro, MACRO, rpt::macro_longest, MAX_SYSSTATES, MAXXLAT, rpt::memory, MEMORY, rpt::monminblocks, ast_variable::name, rpt::name, name, ast_variable::next, rpt::nobusyout, rpt::nodes, NODES, rpt::notelemtx, option_verbose, rpt::ourcallerid, rpt::ourcontext, rpt::outxlat, rpt::p, rpt_xlat::passchars, rpt::phone_functions, rpt::phone_longestfunc, POLITEID, rpt::politeid, rpt::propagate_dtmf, rpt::propagate_phonedtmf, rpt::remoteinacttimeout, rpt::remotetimeout, rpt::remotetimeoutwarning, rpt::remotetimeoutwarningfreq, retrieve_astcfgint(), rpt_vars, rpt::s, sysstate::schedulerdisable, rpt::simple, rpt::skedstanzaname, rpt::startupmacro, rpt::tailmessagemax, rpt::tailmessages, rpt::tailmessagetime, rpt::tailsquashedtime, rpt::tonezone, sysstate::totdisable, TOTIME, rpt::totime, sysstate::txdisable, rpt::txlimitsstanzaname, typeof(), sysstate::userfundisable, ast_variable::value, and VERBOSE_PREFIX_3.

Referenced by rpt(), and rpt_master().

01621 {
01622 char *this,*val;
01623 int   i,j,longestnode;
01624 struct ast_variable *vp;
01625 struct ast_config *cfg;
01626 char *strs[100];
01627 char s1[256];
01628 static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
01629             "ufena","ufdis","atena","atdis",NULL};
01630 
01631    if (option_verbose > 2)
01632       ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
01633          (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
01634    ast_mutex_lock(&rpt_vars[n].lock);
01635    if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
01636    cfg = ast_config_load("rpt.conf");
01637    if (!cfg) {
01638       ast_mutex_unlock(&rpt_vars[n].lock);
01639       ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf.  Radio Repeater disabled.\n");
01640       pthread_exit(NULL);
01641    }
01642    rpt_vars[n].cfg = cfg; 
01643    this = rpt_vars[n].name;
01644    memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
01645    if (init)
01646    {
01647       /* clear all the fields in the structure after 'p' */
01648       memset(&rpt_vars[n].p + sizeof(rpt_vars[0].p), 0, sizeof(rpt_vars[0]) - sizeof(rpt_vars[0].p) - offsetof(typeof(rpt_vars[0]), p));
01649       rpt_vars[n].tele.next = &rpt_vars[n].tele;
01650       rpt_vars[n].tele.prev = &rpt_vars[n].tele;
01651       rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
01652       rpt_vars[n].tailmessagen = 0;
01653    }
01654 #ifdef   __RPT_NOTCH
01655    /* zot out filters stuff */
01656    memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
01657 #endif
01658    val = (char *) ast_variable_retrieve(cfg,this,"context");
01659    if (val) rpt_vars[n].p.ourcontext = val;
01660    else rpt_vars[n].p.ourcontext = this;
01661    val = (char *) ast_variable_retrieve(cfg,this,"callerid");
01662    if (val) rpt_vars[n].p.ourcallerid = val;
01663    val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
01664    if (val) rpt_vars[n].p.acctcode = val;
01665    val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
01666    if (val) rpt_vars[n].p.ident = val;
01667    val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
01668    if (val) rpt_vars[n].p.hangtime = atoi(val);
01669       else rpt_vars[n].p.hangtime = HANGTIME;
01670    val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
01671    if (val) rpt_vars[n].p.althangtime = atoi(val);
01672       else rpt_vars[n].p.althangtime = HANGTIME;
01673    val = (char *) ast_variable_retrieve(cfg,this,"totime");
01674    if (val) rpt_vars[n].p.totime = atoi(val);
01675       else rpt_vars[n].p.totime = TOTIME;
01676    rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);    
01677    rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);     
01678    rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
01679    rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME);   /* Enforce a min max including zero */
01680    rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID); /* Enforce a min max */
01681    val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
01682    if (val) rpt_vars[n].p.tonezone = val;
01683    rpt_vars[n].p.tailmessages[0] = 0;
01684    rpt_vars[n].p.tailmessagemax = 0;
01685    val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
01686    if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
01687    val = (char *) ast_variable_retrieve(cfg,this,"memory");
01688    if (!val) val = MEMORY;
01689    rpt_vars[n].p.memory = val;
01690    val = (char *) ast_variable_retrieve(cfg,this,"macro");
01691    if (!val) val = MACRO;
01692    rpt_vars[n].p.macro = val;
01693    val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
01694    if (val) rpt_vars[n].p.startupmacro = val;
01695    val = (char *) ast_variable_retrieve(cfg,this,"iobase");
01696    /* do not use atoi() here, we need to be able to have
01697       the input specified in hex or decimal so we use
01698       sscanf with a %i */
01699    if ((!val) || (sscanf(val,"%i",&rpt_vars[n].p.iobase) != 1))
01700    rpt_vars[n].p.iobase = DEFAULT_IOBASE;
01701    val = (char *) ast_variable_retrieve(cfg,this,"ioport");
01702    rpt_vars[n].p.ioport = val;
01703    val = (char *) ast_variable_retrieve(cfg,this,"functions");
01704    if (!val)
01705       {
01706          val = FUNCTIONS;
01707          rpt_vars[n].p.simple = 1;
01708       } 
01709    rpt_vars[n].p.functions = val;
01710    val =  (char *) ast_variable_retrieve(cfg,this,"link_functions");
01711    if (val) rpt_vars[n].p.link_functions = val;
01712    else 
01713       rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
01714    val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
01715    if (val) rpt_vars[n].p.phone_functions = val;
01716    val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
01717    if (val) rpt_vars[n].p.dphone_functions = val;
01718    val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
01719    if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else 
01720       rpt_vars[n].p.funcchar = *val;      
01721    val = (char *) ast_variable_retrieve(cfg,this,"endchar");
01722    if (!val) rpt_vars[n].p.endchar = ENDCHAR; else 
01723       rpt_vars[n].p.endchar = *val;    
01724    val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
01725    if (val) rpt_vars[n].p.nobusyout = ast_true(val);
01726    val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
01727    if (val) rpt_vars[n].p.notelemtx = ast_true(val);
01728    val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
01729    if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
01730    val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
01731    if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
01732    val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
01733    if (val) rpt_vars[n].p.linktolink = ast_true(val);
01734    val = (char *) ast_variable_retrieve(cfg,this,"nodes");
01735    if (!val) val = NODES;
01736    rpt_vars[n].p.nodes = val;
01737    val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
01738    if (!val) val = EXTNODES;
01739    rpt_vars[n].p.extnodes = val;
01740    val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
01741    if (!val) val = EXTNODEFILE;
01742    rpt_vars[n].p.extnodefile = val;
01743    val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
01744    if (val) rpt_vars[n].p.archivedir = val;
01745    val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
01746    if (val) rpt_vars[n].p.authlevel = atoi(val); 
01747    else rpt_vars[n].p.authlevel = 0;
01748    val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
01749    if (val) rpt_vars[n].p.monminblocks = atol(val); 
01750    else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
01751    val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
01752    if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val); 
01753    else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
01754    val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
01755    if (val) rpt_vars[n].p.civaddr = atoi(val); 
01756    else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
01757    val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
01758    if (val) rpt_vars[n].p.remotetimeout = atoi(val); 
01759    else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
01760    val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
01761    if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val); 
01762    else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
01763    val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
01764    if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val); 
01765    else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
01766 #ifdef   __RPT_NOTCH
01767    val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
01768    if (val) {
01769       i = finddelim(val,strs,MAXFILTERS * 2);
01770       i &= ~1; /* force an even number, rounded down */
01771       if (i >= 2) for(j = 0; j < i; j += 2)
01772       {
01773          rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
01774            &rpt_vars[n].filters[j >> 1].gain,
01775              &rpt_vars[n].filters[j >> 1].const0,
01776             &rpt_vars[n].filters[j >> 1].const1,
01777                 &rpt_vars[n].filters[j >> 1].const2);
01778          sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
01779             strs[j],strs[j + 1]);
01780       }
01781 
01782    }
01783 #endif
01784    val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
01785    if (val) {
01786       memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
01787       i = finddelim(val,strs,3);
01788       if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
01789       if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
01790       if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
01791    }
01792    val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
01793    if (val) {
01794       memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
01795       i = finddelim(val,strs,3);
01796       if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
01797       if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
01798       if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
01799    }
01800    /* retreive the stanza name for the control states if there is one */
01801    val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
01802    rpt_vars[n].p.csstanzaname = val;
01803       
01804    /* retreive the stanza name for the scheduler if there is one */
01805    val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
01806    rpt_vars[n].p.skedstanzaname = val;
01807 
01808    /* retreive the stanza name for the txlimits */
01809    val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
01810    rpt_vars[n].p.txlimitsstanzaname = val;
01811 
01812    longestnode = 0;
01813 
01814    vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
01815       
01816    while(vp){
01817       j = strlen(vp->name);
01818       if (j > longestnode)
01819          longestnode = j;
01820       vp = vp->next;
01821    }
01822 
01823    rpt_vars[n].longestnode = longestnode;
01824       
01825    /*
01826    * For this repeater, Determine the length of the longest function 
01827    */
01828    rpt_vars[n].longestfunc = 0;
01829    vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
01830    while(vp){
01831       j = strlen(vp->name);
01832       if (j > rpt_vars[n].longestfunc)
01833          rpt_vars[n].longestfunc = j;
01834       vp = vp->next;
01835    }
01836    /*
01837    * For this repeater, Determine the length of the longest function 
01838    */
01839    rpt_vars[n].link_longestfunc = 0;
01840    vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
01841    while(vp){
01842       j = strlen(vp->name);
01843       if (j > rpt_vars[n].link_longestfunc)
01844          rpt_vars[n].link_longestfunc = j;
01845       vp = vp->next;
01846    }
01847    rpt_vars[n].phone_longestfunc = 0;
01848    if (rpt_vars[n].p.phone_functions)
01849    {
01850       vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
01851       while(vp){
01852          j = strlen(vp->name);
01853          if (j > rpt_vars[n].phone_longestfunc)
01854             rpt_vars[n].phone_longestfunc = j;
01855          vp = vp->next;
01856       }
01857    }
01858    rpt_vars[n].dphone_longestfunc = 0;
01859    if (rpt_vars[n].p.dphone_functions)
01860    {
01861       vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
01862       while(vp){
01863          j = strlen(vp->name);
01864          if (j > rpt_vars[n].dphone_longestfunc)
01865             rpt_vars[n].dphone_longestfunc = j;
01866          vp = vp->next;
01867       }
01868    }
01869    rpt_vars[n].macro_longest = 1;
01870    vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
01871    while(vp){
01872       j = strlen(vp->name);
01873       if (j > rpt_vars[n].macro_longest)
01874          rpt_vars[n].macro_longest = j;
01875       vp = vp->next;
01876    }
01877    
01878    /* Browse for control states */
01879    if(rpt_vars[n].p.csstanzaname)
01880       vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
01881    else
01882       vp = NULL;
01883    for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){ /* Iterate over the number of control state lines in the stanza */
01884       int k,nukw,statenum;
01885       statenum=atoi(vp->name);
01886       strncpy(s1, vp->value, 255);
01887       s1[255] = 0;
01888       nukw  = finddelim(s1,strs,32);
01889       
01890       for (k = 0 ; k < nukw ; k++){ /* for each user specified keyword */  
01891          for(j = 0 ; cs_keywords[j] != NULL ; j++){ /* try to match to one in our internal table */
01892             if(!strcmp(strs[k],cs_keywords[j])){
01893                switch(j){
01894                   case 0: /* rptena */
01895                      rpt_vars[n].p.s[statenum].txdisable = 0;
01896                      break;
01897                   case 1: /* rptdis */
01898                      rpt_vars[n].p.s[statenum].txdisable = 1;
01899                      break;
01900          
01901                   case 2: /* apena */
01902                      rpt_vars[n].p.s[statenum].autopatchdisable = 0;
01903                      break;
01904 
01905                   case 3: /* apdis */
01906                      rpt_vars[n].p.s[statenum].autopatchdisable = 1;
01907                      break;
01908 
01909                   case 4: /* lnkena */
01910                      rpt_vars[n].p.s[statenum].linkfundisable = 0;
01911                      break;
01912    
01913                   case 5: /* lnkdis */
01914                      rpt_vars[n].p.s[statenum].linkfundisable = 1;
01915                      break;
01916 
01917                   case 6: /* totena */
01918                      rpt_vars[n].p.s[statenum].totdisable = 0;
01919                      break;
01920                
01921                   case 7: /* totdis */
01922                      rpt_vars[n].p.s[statenum].totdisable = 1;
01923                      break;
01924 
01925                   case 8: /* skena */
01926                      rpt_vars[n].p.s[statenum].schedulerdisable = 0;
01927                      break;
01928 
01929                   case 9: /* skdis */
01930                      rpt_vars[n].p.s[statenum].schedulerdisable = 1;
01931                      break;
01932 
01933                   case 10: /* ufena */
01934                      rpt_vars[n].p.s[statenum].userfundisable = 0;
01935                      break;
01936 
01937                   case 11: /* ufdis */
01938                      rpt_vars[n].p.s[statenum].userfundisable = 1;
01939                      break;
01940 
01941                   case 12: /* atena */
01942                      rpt_vars[n].p.s[statenum].alternatetail = 1;
01943                      break;
01944 
01945                   case 13: /* atdis */
01946                      rpt_vars[n].p.s[statenum].alternatetail = 0;
01947                      break;
01948          
01949                   default:
01950                      ast_log(LOG_WARNING,
01951                         "Unhandled control state keyword %s", cs_keywords[i]);
01952                      break;
01953                }
01954             }
01955          }
01956       }
01957       vp = vp->next;
01958    }
01959    ast_mutex_unlock(&rpt_vars[n].lock);
01960 }

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

Definition at line 8466 of file app_rpt.c.

References rpt::archivedir, ast_canmatch_extension(), ast_exists_extension(), ast_pthread_create, rpt::callmode, rpt::cidx, rpt::cmdnode, collect_function_digits(), COMPLETE, rpt::dailyexecdcommands, DC_COMPLETE, DC_COMPLETEQUIET, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, do_dtmf_phone(), donodelog(), rpt::dtmf_time, rpt::dtmfbuf, rpt::dtmfidx, rpt::endchar, rpt::exten, rpt::funcchar, rpt::lastdtmfcommand, rpt::lock, MAXDTMF, MAXPATCHCONTEXT, rpt::mydtmf, rpt::ourcontext, rpt::p, rpt::patchcontext, rpt::patchdialtime, rpt::patchfarenddisconnect, rpt::patchnoct, rpt::patchquiet, rpt::pchannel, PROC, rpt::propagate_phonedtmf, rpt_call(), rpt::rpt_call_thread, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), send_link_dtmf(), rpt::simple, SOURCE_RPT, rpt::stopgen, TERM, and rpt::totalexecdcommands.

Referenced by rpt().

08467 {
08468 int   res;
08469 pthread_attr_t attr;
08470 char  cmd[MAXDTMF+1] = "";
08471 
08472    if (myrpt->p.archivedir)
08473    {
08474       char str[100];
08475 
08476       sprintf(str,"DTMF,MAIN,%c",c);
08477       donodelog(myrpt,str);
08478    }
08479    if (c == myrpt->p.endchar)
08480    {
08481    /* if in simple mode, kill autopatch */
08482       if (myrpt->p.simple && myrpt->callmode)
08483       {
08484          rpt_mutex_lock(&myrpt->lock);
08485          myrpt->callmode = 0;
08486          rpt_mutex_unlock(&myrpt->lock);
08487          rpt_telemetry(myrpt,TERM,NULL);
08488          return;
08489       }
08490       rpt_mutex_lock(&myrpt->lock);
08491       myrpt->stopgen = 1;
08492       if (myrpt->cmdnode[0])
08493       {
08494          myrpt->cmdnode[0] = 0;
08495          myrpt->dtmfidx = -1;
08496          myrpt->dtmfbuf[0] = 0;
08497          rpt_mutex_unlock(&myrpt->lock);
08498          rpt_telemetry(myrpt,COMPLETE,NULL);
08499       } 
08500       else
08501                 {
08502                         rpt_mutex_unlock(&myrpt->lock);
08503                         if (myrpt->p.propagate_phonedtmf)
08504                                do_dtmf_phone(myrpt,NULL,c);
08505                 }
08506       return;
08507    }
08508    rpt_mutex_lock(&myrpt->lock);
08509    if (myrpt->cmdnode[0])
08510    {
08511       rpt_mutex_unlock(&myrpt->lock);
08512       send_link_dtmf(myrpt,c);
08513       return;
08514    }
08515    if (!myrpt->p.simple)
08516    {
08517       if (c == myrpt->p.funcchar)
08518       {
08519          myrpt->dtmfidx = 0;
08520          myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
08521          rpt_mutex_unlock(&myrpt->lock);
08522          time(&myrpt->dtmf_time);
08523          return;
08524       } 
08525       else if ((c != myrpt->p.endchar) && (myrpt->dtmfidx >= 0))
08526       {
08527          time(&myrpt->dtmf_time);
08528          
08529          if (myrpt->dtmfidx < MAXDTMF)
08530          {
08531             myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
08532             myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
08533             
08534             strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
08535             
08536             rpt_mutex_unlock(&myrpt->lock);
08537             res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL);
08538             rpt_mutex_lock(&myrpt->lock);
08539             switch(res){
08540                 case DC_INDETERMINATE:
08541                break;
08542                 case DC_REQ_FLUSH:
08543                myrpt->dtmfidx = 0;
08544                myrpt->dtmfbuf[0] = 0;
08545                break;
08546                 case DC_COMPLETE:
08547                 case DC_COMPLETEQUIET:
08548                myrpt->totalexecdcommands++;
08549                myrpt->dailyexecdcommands++;
08550                strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
08551                myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
08552                myrpt->dtmfbuf[0] = 0;
08553                myrpt->dtmfidx = -1;
08554                myrpt->dtmf_time = 0;
08555                break;
08556 
08557                 case DC_ERROR:
08558                 default:
08559                myrpt->dtmfbuf[0] = 0;
08560                myrpt->dtmfidx = -1;
08561                myrpt->dtmf_time = 0;
08562                break;
08563             }
08564             if(res != DC_INDETERMINATE) {
08565                rpt_mutex_unlock(&myrpt->lock);
08566                return;
08567             }
08568          } 
08569       }
08570    }
08571    else /* if simple */
08572    {
08573       if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
08574       {
08575          myrpt->callmode = 1;
08576          myrpt->patchnoct = 0;
08577          myrpt->patchquiet = 0;
08578          myrpt->patchfarenddisconnect = 0;
08579          myrpt->patchdialtime = 0;
08580          strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
08581          myrpt->cidx = 0;
08582          myrpt->exten[myrpt->cidx] = 0;
08583          rpt_mutex_unlock(&myrpt->lock);
08584               pthread_attr_init(&attr);
08585               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08586          ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
08587          return;
08588       }
08589    }
08590    if (myrpt->callmode == 1)
08591    {
08592       myrpt->exten[myrpt->cidx++] = c;
08593       myrpt->exten[myrpt->cidx] = 0;
08594       /* if this exists */
08595       if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
08596       {
08597          myrpt->callmode = 2;
08598          rpt_mutex_unlock(&myrpt->lock);
08599          if(!myrpt->patchquiet)
08600             rpt_telemetry(myrpt,PROC,NULL); 
08601          return;
08602       }
08603       /* if can continue, do so */
08604       if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
08605       {
08606          /* call has failed, inform user */
08607          myrpt->callmode = 4;
08608       }
08609       rpt_mutex_unlock(&myrpt->lock);
08610       return;
08611    }
08612    if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
08613    {
08614       myrpt->mydtmf = c;
08615    }
08616    rpt_mutex_unlock(&myrpt->lock);
08617    if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
08618       do_dtmf_phone(myrpt,NULL,c);
08619    return;
08620 }

static int matchkeyword ( char *  string,
char **  param,
char *  keywords[] 
) [static]

Definition at line 1476 of file app_rpt.c.

Referenced by function_autopatchup().

01477 {
01478 int   i,ls;
01479    for( i = 0 ; keywords[i] ; i++){
01480       ls = strlen(keywords[i]);
01481       if(!ls){
01482          *param = NULL;
01483          return 0;
01484       }
01485       if(!strncmp(string, keywords[i], ls)){
01486          if(param)
01487             *param = string + ls;
01488          return i + 1; 
01489       }
01490    }
01491    param = NULL;
01492    return 0;
01493 }

static void mdc1200_notify ( struct rpt myrpt,
char *  fromnode,
unsigned int  unit 
) [static]

Definition at line 1190 of file app_rpt.c.

References ast_verbose(), and rpt::name.

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

01191 {
01192    if (!fromnode)
01193    {
01194       ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
01195          unit,myrpt->name);
01196    }
01197    else
01198    {
01199       ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
01200          unit,fromnode,myrpt->name);
01201    }
01202 }

static int mem2vfo_ic706 ( struct rpt myrpt  )  [static]

Definition at line 7189 of file app_rpt.c.

References civ_cmd(), rpt::civaddr, and rpt::p.

Referenced by set_ic706().

07190 {
07191    unsigned char cmdstr[10];
07192    
07193    cmdstr[0] = cmdstr[1] = 0xfe;
07194    cmdstr[2] = myrpt->p.civaddr;
07195    cmdstr[3] = 0xe0;
07196    cmdstr[4] = 0x0a;
07197    cmdstr[5] = 0xfd;
07198 
07199    return(civ_cmd(myrpt,cmdstr,6));
07200 }

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

Definition at line 7552 of file app_rpt.c.

References multimode_bump_freq_ft897(), multimode_bump_freq_ic706(), and rpt::remote.

Referenced by function_remote(), and service_scan().

07553 {
07554    if(!strcmp(myrpt->remote, remote_rig_ft897))
07555       return multimode_bump_freq_ft897(myrpt, interval);
07556    else if(!strcmp(myrpt->remote, remote_rig_ic706))
07557       return multimode_bump_freq_ic706(myrpt, interval);
07558    else
07559       return -1;
07560 }

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

Definition at line 6741 of file app_rpt.c.

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

Referenced by multimode_bump_freq().

06742 {
06743    int m,d;
06744    char mhz[MAXREMSTR], decimals[MAXREMSTR];
06745 
06746    if(debug)
06747       printf("Before bump: %s\n", myrpt->freq);
06748 
06749    if(split_freq(mhz, decimals, myrpt->freq))
06750       return -1;
06751    
06752    m = atoi(mhz);
06753    d = atoi(decimals);
06754 
06755    d += (interval / 10); /* 10Hz resolution */
06756    if(d < 0){
06757       m--;
06758       d += 100000;
06759    }
06760    else if(d >= 100000){
06761       m++;
06762       d -= 100000;
06763    }
06764 
06765    if(check_freq_ft897(m, d, NULL)){
06766       if(debug)
06767          printf("Bump freq invalid\n");
06768       return -1;
06769    }
06770 
06771    snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
06772 
06773    if(debug)
06774       printf("After bump: %s\n", myrpt->freq);
06775 
06776    return set_freq_ft897(myrpt, myrpt->freq);   
06777 }

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

Definition at line 7285 of file app_rpt.c.

References check_freq_ic706(), rpt::civaddr, rpt::freq, MAXREMSTR, rpt::p, serial_remote_io(), and split_freq().

Referenced by multimode_bump_freq().

07286 {
07287    int m,d;
07288    char mhz[MAXREMSTR], decimals[MAXREMSTR];
07289    unsigned char cmdstr[20];
07290 
07291    if(debug)
07292       printf("Before bump: %s\n", myrpt->freq);
07293 
07294    if(split_freq(mhz, decimals, myrpt->freq))
07295       return -1;
07296    
07297    m = atoi(mhz);
07298    d = atoi(decimals);
07299 
07300    d += (interval / 10); /* 10Hz resolution */
07301    if(d < 0){
07302       m--;
07303       d += 100000;
07304    }
07305    else if(d >= 100000){
07306       m++;
07307       d -= 100000;
07308    }
07309 
07310    if(check_freq_ic706(m, d, NULL)){
07311       if(debug)
07312          printf("Bump freq invalid\n");
07313       return -1;
07314    }
07315 
07316    snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
07317 
07318    if(debug)
07319       printf("After bump: %s\n", myrpt->freq);
07320 
07321    /* The ic-706 likes packed BCD frequencies */
07322 
07323    cmdstr[0] = cmdstr[1] = 0xfe;
07324    cmdstr[2] = myrpt->p.civaddr;
07325    cmdstr[3] = 0xe0;
07326    cmdstr[4] = 0;
07327    cmdstr[5] = ((d % 10) << 4);
07328    cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
07329    cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
07330    cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
07331    cmdstr[9] = (m / 100);
07332    cmdstr[10] = 0xfd;
07333 
07334    return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
07335 }

static int multimode_capable ( struct rpt myrpt  )  [static]

Definition at line 878 of file app_rpt.c.

References rpt::remote.

Referenced by function_remote(), and rpt_tele_thread().

00879 {
00880    if(!strcmp(myrpt->remote, remote_rig_ft897))
00881       return 1;
00882    if(!strcmp(myrpt->remote, remote_rig_ic706))
00883       return 1;
00884    return 0;
00885 }  

static int myatoi ( char *  str  )  [static]

Definition at line 1518 of file app_rpt.c.

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

01519 {
01520 int   ret;
01521 
01522    if (str == NULL) return -1;
01523    /* leave this %i alone, non-base-10 input is useful here */
01524    if (sscanf(str,"%i",&ret) != 1) return -1;
01525    return ret;
01526 }

static int mycompar ( const void *  a,
const void *  b 
) [static]

Definition at line 1528 of file app_rpt.c.

Referenced by rpt_do_nodes(), and rpt_tele_thread().

01529 {
01530 char  **x = (char **) a;
01531 char  **y = (char **) b;
01532 int   xoff,yoff;
01533 
01534    if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
01535    if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
01536    return(strcmp((*x) + xoff,(*y) + yoff));
01537 }

static char* node_lookup ( struct rpt myrpt,
char *  digitbuf 
) [static]

Definition at line 1408 of file app_rpt.c.

References ast_config_destroy(), ast_config_load(), ast_mutex_lock(), ast_mutex_unlock(), ast_variable_browse(), ast_variable_retrieve(), rpt::cfg, rpt::extnodefile, rpt::extnodes, last, rpt::longestnode, ast_variable::name, ast_variable::next, nodelookuplock, rpt::nodes, rpt::p, and val.

Referenced by attempt_reconnect(), connect_link(), and function_ilink().

01409 {
01410 
01411 char *val;
01412 int longestnode,j;
01413 struct stat mystat;
01414 static time_t last = 0;
01415 static struct ast_config *ourcfg = NULL;
01416 struct ast_variable *vp;
01417 
01418    /* try to look it up locally first */
01419    val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
01420    if (val) return(val);
01421    ast_mutex_lock(&nodelookuplock);
01422    /* if file does not exist */
01423    if (stat(myrpt->p.extnodefile,&mystat) == -1)
01424    {
01425       if (ourcfg) ast_config_destroy(ourcfg);
01426       ourcfg = NULL;
01427       ast_mutex_unlock(&nodelookuplock);
01428       return(NULL);
01429    }
01430    /* if we need to reload */
01431    if (mystat.st_mtime > last)
01432    {
01433       if (ourcfg) ast_config_destroy(ourcfg);
01434       ourcfg = ast_config_load(myrpt->p.extnodefile);
01435       /* if file not there, just bail */
01436       if (!ourcfg)
01437       {
01438          ast_mutex_unlock(&nodelookuplock);
01439          return(NULL);
01440       }
01441       /* reset "last" time */
01442       last = mystat.st_mtime;
01443 
01444       /* determine longest node length again */    
01445       longestnode = 0;
01446       vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
01447       while(vp){
01448          j = strlen(vp->name);
01449          if (j > longestnode)
01450             longestnode = j;
01451          vp = vp->next;
01452       }
01453 
01454       vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
01455       while(vp){
01456          j = strlen(vp->name);
01457          if (j > longestnode)
01458             longestnode = j;
01459          vp = vp->next;
01460       }
01461 
01462       myrpt->longestnode = longestnode;
01463    }
01464    val = NULL;
01465    if (ourcfg)
01466       val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
01467    ast_mutex_unlock(&nodelookuplock);
01468    return(val);
01469 }

static int openserial ( char *  fname  )  [static]

Definition at line 1154 of file app_rpt.c.

References ast_log(), ECHO, errno, LOG_WARNING, and MAX.

01155 {
01156    struct termios mode;
01157    int fd;
01158 
01159    fd = open(fname,O_RDWR);
01160    if (fd == -1)
01161    {
01162       ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
01163       return -1;
01164    }
01165    memset(&mode, 0, sizeof(mode));
01166    if (tcgetattr(fd, &mode)) {
01167       ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
01168       return -1;
01169    }
01170 #ifndef SOLARIS
01171    cfmakeraw(&mode);
01172 #else
01173         mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
01174                         |INLCR|IGNCR|ICRNL|IXON);
01175         mode.c_oflag &= ~OPOST;
01176         mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
01177         mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
01178         mode.c_cflag |= CS8;
01179    mode.c_cc[TIME] = 3;
01180    mode.c_cc[MAX] = 1;
01181 #endif
01182 
01183    cfsetispeed(&mode, B9600);
01184    cfsetospeed(&mode, B9600);
01185    if (tcsetattr(fd, TCSANOW, &mode)) 
01186       ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
01187    return(fd); 
01188 }

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

Definition at line 2456 of file app_rpt.c.

References play_tone_pair().

Referenced by send_morse().

02457 {
02458    return play_tone_pair(chan, 0, 0, duration, 0);
02459 }

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

Definition at line 2451 of file app_rpt.c.

References play_tone_pair().

Referenced by rpt_tele_thread(), and send_morse().

02452 {
02453    return play_tone_pair(chan, freq, 0, duration, amplitude);
02454 }

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

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

02438 {
02439    int res;
02440 
02441         if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
02442                 return res;
02443                                                                                                                                             
02444         while(chan->generatordata) {
02445       if (ast_safe_sleep(chan,1)) return -1;
02446    }
02447 
02448         return 0;
02449 }

static void queue_id ( struct rpt myrpt  )  [static]

Definition at line 8625 of file app_rpt.c.

References ID, rpt::idtime, rpt::idtimer, rpt::lock, rpt::mustid, rpt::p, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), and rpt::tailid.

Referenced by rpt().

08626 {
08627    if(myrpt->p.idtime){ /* ID time must be non-zero */
08628       myrpt->mustid = myrpt->tailid = 0;
08629       myrpt->idtimer = myrpt->p.idtime; /* Reset our ID timer */
08630       rpt_mutex_unlock(&myrpt->lock);
08631       rpt_telemetry(myrpt,ID,NULL);
08632       rpt_mutex_lock(&myrpt->lock);
08633    }
08634 }

static int rbi_mhztoband ( char *  str  )  [static]

Definition at line 5689 of file app_rpt.c.

Referenced by setrbi(), and setrbi_check().

05690 {
05691 int   i;
05692 
05693    i = atoi(str) / 10; /* get the 10's of mhz */
05694    switch(i)
05695    {
05696        case 2:
05697       return 10;
05698        case 5:
05699       return 11;
05700        case 14:
05701       return 2;
05702        case 22:
05703       return 3;
05704        case 44:
05705       return 4;
05706        case 124:
05707       return 0;
05708        case 125:
05709       return 1;
05710        case 126:
05711       return 8;
05712        case 127:
05713       return 5;
05714        case 128:
05715       return 6;
05716        case 129:
05717       return 7;
05718        default:
05719       break;
05720    }
05721    return -1;
05722 }

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

Definition at line 5848 of file app_rpt.c.

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

Referenced by setrbi().

05849 {
05850 struct dahdi_radio_param r;
05851 
05852    memset(&r,0,sizeof(struct dahdi_radio_param));
05853    r.radpar = DAHDI_RADPAR_REMMODE;
05854    r.data = DAHDI_RADPAR_REM_RBI1;
05855    /* if setparam ioctl fails, its probably not a pciradio card */
05856    if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
05857    {
05858       rbi_out_parallel(myrpt,data);
05859       return;
05860    }
05861    r.radpar = DAHDI_RADPAR_REMCOMMAND;
05862    memcpy(&r.data,data,5);
05863    if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
05864    {
05865       ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->zaprxchannel->name);
05866       return;
05867    }
05868 }

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

Definition at line 5820 of file app_rpt.c.

References rpt::iobase, and rpt::p.

Referenced by rbi_out().

05821     {
05822 #ifdef __i386__
05823     int i,j;
05824     unsigned char od,d;
05825     static volatile long long delayvar;
05826 
05827     for(i = 0 ; i < 5 ; i++){
05828         od = *data++; 
05829         for(j = 0 ; j < 8 ; j++){
05830             d = od & 1;
05831             outb(d,myrpt->p.iobase);
05832        /* >= 15 us */
05833        for(delayvar = 1; delayvar < 15000; delayvar++); 
05834             od >>= 1;
05835             outb(d | 2,myrpt->p.iobase);
05836        /* >= 30 us */
05837        for(delayvar = 1; delayvar < 30000; delayvar++); 
05838             outb(d,myrpt->p.iobase);
05839        /* >= 10 us */
05840        for(delayvar = 1; delayvar < 10000; delayvar++); 
05841             }
05842         }
05843    /* >= 50 us */
05844         for(delayvar = 1; delayvar < 50000; delayvar++); 
05845 #endif
05846     }

static int rbi_pltocode ( char *  str  )  [static]

Definition at line 5725 of file app_rpt.c.

References s.

Referenced by setrbi(), and setrbi_check().

05726 {
05727 int i;
05728 char *s;
05729 
05730    s = strchr(str,'.');
05731    i = 0;
05732    if (s) i = atoi(s + 1);
05733    i += atoi(str) * 10;
05734    switch(i)
05735    {
05736        case 670:
05737       return 0;
05738        case 719:
05739       return 1;
05740        case 744:
05741       return 2;
05742        case 770:
05743       return 3;
05744        case 797:
05745       return 4;
05746        case 825:
05747       return 5;
05748        case 854:
05749       return 6;
05750        case 885:
05751       return 7;
05752        case 915:
05753       return 8;
05754        case 948:
05755       return 9;
05756        case 974:
05757       return 10;
05758        case 1000:
05759       return 11;
05760        case 1035:
05761       return 12;
05762        case 1072:
05763       return 13;
05764        case 1109:
05765       return 14;
05766        case 1148:
05767       return 15;
05768        case 1188:
05769       return 16;
05770        case 1230:
05771       return 17;
05772        case 1273:
05773       return 18;
05774        case 1318:
05775       return 19;
05776        case 1365:
05777       return 20;
05778        case 1413:
05779       return 21;
05780        case 1462:
05781       return 22;
05782        case 1514:
05783       return 23;
05784        case 1567:
05785       return 24;
05786        case 1622:
05787       return 25;
05788        case 1679:
05789       return 26;
05790        case 1738:
05791       return 27;
05792        case 1799:
05793       return 28;
05794        case 1862:
05795       return 29;
05796        case 1928:
05797       return 30;
05798        case 2035:
05799       return 31;
05800        case 2107:
05801       return 32;
05802        case 2181:
05803       return 33;
05804        case 2257:
05805       return 34;
05806        case 2336:
05807       return 35;
05808        case 2418:
05809       return 36;
05810        case 2503:
05811       return 37;
05812    }
05813    return -1;
05814 }

static int reload ( void   )  [static]

Definition at line 11912 of file app_rpt.c.

References reload(), and rpt_vars.

11914 {
11915 int   n;
11916 
11917    for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
11918    return(0);
11919 }

static int retreive_memory ( struct rpt myrpt,
char *  memory 
) [static]

Definition at line 7649 of file app_rpt.c.

References ast_variable_retrieve(), rpt::cfg, rpt::freq, rpt::memory, rpt::offset, rpt::p, 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::remmode, rpt::rxpl, rpt::rxplon, s, rpt::txpl, and rpt::txplon.

Referenced by function_remote(), and rpt_master().

07650 {
07651    char tmp[30], *s, *s1, *val;
07652 
07653    val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
07654    if (!val){
07655       return -1;
07656    }        
07657    strncpy(tmp,val,sizeof(tmp) - 1);
07658    tmp[sizeof(tmp)-1] = 0;
07659 
07660    s = strchr(tmp,',');
07661    if (!s)
07662       return 1; 
07663    *s++ = 0;
07664    s1 = strchr(s,',');
07665    if (!s1)
07666       return 1;
07667    *s1++ = 0;
07668    strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
07669    strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
07670    strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
07671    myrpt->remmode = REM_MODE_FM;
07672    myrpt->offset = REM_SIMPLEX;
07673    myrpt->powerlevel = REM_MEDPWR;
07674    myrpt->txplon = myrpt->rxplon = 0;
07675    while(*s1){
07676       switch(*s1++){
07677          case 'A':
07678          case 'a':
07679             strcpy(myrpt->rxpl, "100.0");
07680             strcpy(myrpt->txpl, "100.0");
07681             myrpt->remmode = REM_MODE_AM; 
07682             break;
07683          case 'B':
07684          case 'b':
07685             strcpy(myrpt->rxpl, "100.0");
07686             strcpy(myrpt->txpl, "100.0");
07687             myrpt->remmode = REM_MODE_LSB;
07688             break;
07689          case 'F':
07690             myrpt->remmode = REM_MODE_FM;
07691             break;
07692          case 'L':
07693          case 'l':
07694             myrpt->powerlevel = REM_LOWPWR;
07695             break;               
07696          case 'H':
07697          case 'h':
07698             myrpt->powerlevel = REM_HIPWR;
07699             break;
07700                
07701          case 'M':
07702          case 'm':
07703             myrpt->powerlevel = REM_MEDPWR;
07704             break;
07705                   
07706          case '-':
07707             myrpt->offset = REM_MINUS;
07708             break;
07709                   
07710          case '+':
07711             myrpt->offset = REM_PLUS;
07712             break;
07713                   
07714          case 'S':
07715          case 's':
07716             myrpt->offset = REM_SIMPLEX;
07717             break;
07718                   
07719          case 'T':
07720          case 't':
07721             myrpt->txplon = 1;
07722             break;
07723                   
07724          case 'R':
07725          case 'r':
07726             myrpt->rxplon = 1;
07727             break;
07728 
07729          case 'U':
07730          case 'u':
07731             strcpy(myrpt->rxpl, "100.0");
07732             strcpy(myrpt->txpl, "100.0");
07733             myrpt->remmode = REM_MODE_USB;
07734             break;
07735          default:
07736             return 1;
07737       }
07738    }
07739    return 0;
07740 }

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

Definition at line 1593 of file app_rpt.c.

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

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

01594 {
01595         char *var;
01596         int ret;
01597    char include_zero = 0;
01598 
01599    if(min < 0){ /* If min is negative, this means include 0 as a valid entry */
01600       min = -min;
01601       include_zero = 1;
01602    }           
01603                                                                      
01604         var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
01605         if(var){
01606                 ret = myatoi(var);
01607       if(include_zero && !ret)
01608          return 0;
01609                 if(ret < min)
01610                         ret = min;
01611                 if(ret > max)
01612                         ret = max;
01613         }
01614         else
01615                 ret = defl;
01616         return ret;
01617 }

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

Definition at line 8759 of file app_rpt.c.

References __kickshort(), __mklinklist(), ast_channel::_state, sysstate::alternatetail, rpt::althangtime, ast_channel::appl, rpt::archivedir, ast_call(), AST_CDR_FLAG_POST_DISABLED, ast_channel_setoption(), ast_check_hangup(), ast_closestream(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_FORMAT_SLINEAR, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_hangup(), ast_indicate(), ast_log(), AST_OPTION_RELAXDTMF, AST_OPTION_TONE_VERIFY, AST_PTHREADT_STOP, ast_read(), ast_request(), ast_set_flag, 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(), ast_writefile(), ast_writestream(), attempt_reconnect(), rpt::callmode, ast_channel::cdr, rpt::cfg, rpt_link::chan, rpt_tele::chan, rpt::cmdnode, rpt::conf, CONNECTED, rpt_link::connected, rpt_link::connecttime, CONNFAIL, rpt::dailyexecdcommands, rpt::dailykerchunks, rpt::dailykeyups, rpt::dailytxtime, ast_frame::data, ast_channel::data, ast_frame::datalen, DISC_TIME, rpt_link::disced, rpt_link::disctime, rpt::disgorgetime, diskavail(), do_dtmf_local(), do_scheduler(), donodelog(), rpt::dtmf_local_timer, rpt::dtmf_time, DTMF_TIMEOUT, rpt::dtmfbuf, rpt_link::dtmfed, rpt::dtmfidx, rpt::duplex, rpt_link::elaptime, rpt::exten, rpt::exttx, f, ast_channel::fds, free, func_xlat(), handle_link_data(), handle_link_phone_dtmf(), rpt::hangtime, rpt_link::hasconnected, ID, IDTALKOVER, rpt::idtime, rpt::idtimer, rpt::inxlat, rpt_link::isremote, rpt::keyed, rpt_link::killme, rpt::lastdtmfcommand, rpt_link::lastf1, rpt::lastf1, rpt_link::lastf2, rpt::lastf2, rpt::lastnodewhichkeyedusup, rpt_link::lastrx, rpt_link::lastrx1, rpt_link::lasttx, LINKLISTTIME, rpt_link::linklisttimer, rpt::links, rpt::linktolink, LINKUNKEY, load_rpt_vars(), local_dtmf_helper(), rpt::localtx, rpt::lock, LOG_NOTICE, LOG_WARNING, rpt::macrobuf, MACROPTIME, MACROTIME, rpt::macrotimer, rpt_link::max_retries, MAXCONNECTTIME, MAXLINKLIST, MAXMACRO, mdc1200_notify(), rpt_link::mode, rpt_tele::mode, rpt::monchannel, rpt::monminblocks, rpt::monstream, MSWAIT, rpt::mustid, rpt_link::name, ast_channel::name, rpt::name, rpt_link::next, rpt_tele::next, rpt::notelemtx, option_verbose, rpt_link::outbound, rpt::p, rpt_link::pchan, rpt::pchannel, rpt_link::phonemode, rpt::politeid, rpt_link::prev, queue_id(), rpt_link::reconnects, REDUNDANT_TX_TIME, rpt::reload, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, REMDISC, rpt_link::rerxtimer, rpt::rerxtimer, rpt_link::retries, RETRY_TIMER_MS, rpt_link::retrytimer, rpt_link::retxtimer, rpt::retxtimer, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), rpt::rpt_thread, rpt_vars, rpt::rxchanname, rpt::rxchannel, s, rpt::s, rpt::scram, rpt::skedtimer, START_DELAY, rpt::startupmacro, rpt::sysstate_cur, t, rpt::tailevent, rpt::tailid, rpt::tailmessages, rpt::tailmessagetime, TAILMSG, rpt::tailtimer, rpt::tele, rpt_link::thisconnected, TIMEOUT, rpt::timeouts, rpt::tmsgtimer, rpt::tonotify, rpt::totalexecdcommands, rpt::totalkerchunks, rpt::totalkeyups, rpt::totaltxtime, rpt::totime, rpt::totimer, rpt::tounkeyed, rpt::txchanname, rpt::txchannel, rpt::txconf, sysstate::txdisable, rpt::txpchannel, UNKEY, VERBOSE_PREFIX_3, ast_channel::whentohangup, rpt::zaprxchannel, and rpt::zaptxchannel.

08760 {
08761 struct   rpt *myrpt = (struct rpt *)this;
08762 char *tele,*idtalkover,c;
08763 int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
08764 int tailmessagequeued,ctqueued,dtmfed;
08765 struct ast_channel *who;
08766 struct dahdi_confinfo ci;  /* conference info */
08767 time_t   t;
08768 struct rpt_link *l,*m;
08769 struct rpt_tele *telem;
08770 char tmpstr[300],lstr[MAXLINKLIST];
08771 
08772 
08773    if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
08774    sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
08775    mkdir(tmpstr,0600);
08776    rpt_mutex_lock(&myrpt->lock);
08777 
08778    telem = myrpt->tele.next;
08779    while(telem != &myrpt->tele)
08780    {
08781       ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
08782       telem = telem->next;
08783    }
08784    rpt_mutex_unlock(&myrpt->lock);
08785    /* find our index, and load the vars initially */
08786    for(i = 0; i < nrpts; i++)
08787    {
08788       if (&rpt_vars[i] == myrpt)
08789       {
08790          load_rpt_vars(i,0);
08791          break;
08792       }
08793    }
08794    rpt_mutex_lock(&myrpt->lock);
08795    strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
08796    tele = strchr(tmpstr,'/');
08797    if (!tele)
08798    {
08799       fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
08800       rpt_mutex_unlock(&myrpt->lock);
08801       myrpt->rpt_thread = AST_PTHREADT_STOP;
08802       pthread_exit(NULL);
08803    }
08804    *tele++ = 0;
08805    myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
08806    myrpt->zaprxchannel = NULL;
08807    if (!strcasecmp(tmpstr,"Zap"))
08808       myrpt->zaprxchannel = myrpt->rxchannel;
08809    if (myrpt->rxchannel)
08810    {
08811       if (myrpt->rxchannel->_state == AST_STATE_BUSY)
08812       {
08813          fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
08814          rpt_mutex_unlock(&myrpt->lock);
08815          ast_hangup(myrpt->rxchannel);
08816          myrpt->rpt_thread = AST_PTHREADT_STOP;
08817          pthread_exit(NULL);
08818       }
08819       ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
08820       ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
08821 #ifdef   AST_CDR_FLAG_POST_DISABLED
08822       ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
08823 #endif
08824       myrpt->rxchannel->whentohangup = 0;
08825       myrpt->rxchannel->appl = "Apprpt";
08826       myrpt->rxchannel->data = "(Repeater Rx)";
08827       if (option_verbose > 2)
08828          ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
08829             tmpstr,tele,myrpt->rxchannel->name);
08830       ast_call(myrpt->rxchannel,tele,999);
08831       if (myrpt->rxchannel->_state != AST_STATE_UP)
08832       {
08833          rpt_mutex_unlock(&myrpt->lock);
08834          ast_hangup(myrpt->rxchannel);
08835          myrpt->rpt_thread = AST_PTHREADT_STOP;
08836          pthread_exit(NULL);
08837       }
08838    }
08839    else
08840    {
08841       fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
08842       rpt_mutex_unlock(&myrpt->lock);
08843       myrpt->rpt_thread = AST_PTHREADT_STOP;
08844       pthread_exit(NULL);
08845    }
08846    myrpt->zaptxchannel = NULL;
08847    if (myrpt->txchanname)
08848    {
08849       strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
08850       tele = strchr(tmpstr,'/');
08851       if (!tele)
08852       {
08853          fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
08854          rpt_mutex_unlock(&myrpt->lock);
08855          ast_hangup(myrpt->rxchannel);
08856          myrpt->rpt_thread = AST_PTHREADT_STOP;
08857          pthread_exit(NULL);
08858       }
08859       *tele++ = 0;
08860       myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
08861       if (!strcasecmp(tmpstr,"Zap"))
08862          myrpt->zaptxchannel = myrpt->txchannel;
08863       if (myrpt->txchannel)
08864       {
08865          if (myrpt->txchannel->_state == AST_STATE_BUSY)
08866          {
08867             fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
08868             rpt_mutex_unlock(&myrpt->lock);
08869             ast_hangup(myrpt->txchannel);
08870             ast_hangup(myrpt->rxchannel);
08871             myrpt->rpt_thread = AST_PTHREADT_STOP;
08872             pthread_exit(NULL);
08873          }        
08874          ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
08875          ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
08876 #ifdef   AST_CDR_FLAG_POST_DISABLED
08877          ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
08878 #endif
08879          myrpt->txchannel->whentohangup = 0;
08880          myrpt->txchannel->appl = "Apprpt";
08881          myrpt->txchannel->data = "(Repeater Tx)";
08882          if (option_verbose > 2)
08883             ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
08884                tmpstr,tele,myrpt->txchannel->name);
08885          ast_call(myrpt->txchannel,tele,999);
08886          if (myrpt->rxchannel->_state != AST_STATE_UP)
08887          {
08888             rpt_mutex_unlock(&myrpt->lock);
08889             ast_hangup(myrpt->rxchannel);
08890             ast_hangup(myrpt->txchannel);
08891             myrpt->rpt_thread = AST_PTHREADT_STOP;
08892             pthread_exit(NULL);
08893          }
08894       }
08895       else
08896       {
08897          fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
08898          rpt_mutex_unlock(&myrpt->lock);
08899          ast_hangup(myrpt->rxchannel);
08900          myrpt->rpt_thread = AST_PTHREADT_STOP;
08901          pthread_exit(NULL);
08902       }
08903    }
08904    else
08905    {
08906       myrpt->txchannel = myrpt->rxchannel;
08907    }
08908    ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
08909    ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
08910    /* allocate a pseudo-channel thru asterisk */
08911    myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
08912    if (!myrpt->pchannel)
08913    {
08914       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
08915       rpt_mutex_unlock(&myrpt->lock);
08916       if (myrpt->txchannel != myrpt->rxchannel) 
08917          ast_hangup(myrpt->txchannel);
08918       ast_hangup(myrpt->rxchannel);
08919       myrpt->rpt_thread = AST_PTHREADT_STOP;
08920       pthread_exit(NULL);
08921    }
08922 #ifdef   AST_CDR_FLAG_POST_DISABLED
08923    ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
08924 #endif
08925    if (!myrpt->zaprxchannel) myrpt->zaprxchannel = myrpt->pchannel;
08926    if (!myrpt->zaptxchannel)
08927    {
08928       /* allocate a pseudo-channel thru asterisk */
08929       myrpt->zaptxchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
08930       if (!myrpt->zaptxchannel)
08931       {
08932          fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
08933          rpt_mutex_unlock(&myrpt->lock);
08934          if (myrpt->txchannel != myrpt->rxchannel) 
08935             ast_hangup(myrpt->txchannel);
08936          ast_hangup(myrpt->rxchannel);
08937          myrpt->rpt_thread = AST_PTHREADT_STOP;
08938          pthread_exit(NULL);
08939       }
08940       ast_set_read_format(myrpt->zaptxchannel,AST_FORMAT_SLINEAR);
08941       ast_set_write_format(myrpt->zaptxchannel,AST_FORMAT_SLINEAR);
08942 #ifdef   AST_CDR_FLAG_POST_DISABLED
08943       ast_set_flag(myrpt->zaptxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
08944 #endif
08945    }
08946    /* allocate a pseudo-channel thru asterisk */
08947    myrpt->monchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
08948    if (!myrpt->monchannel)
08949    {
08950       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
08951       rpt_mutex_unlock(&myrpt->lock);
08952       if (myrpt->txchannel != myrpt->rxchannel) 
08953          ast_hangup(myrpt->txchannel);
08954       ast_hangup(myrpt->rxchannel);
08955       myrpt->rpt_thread = AST_PTHREADT_STOP;
08956       pthread_exit(NULL);
08957    }
08958    ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
08959    ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
08960 #ifdef   AST_CDR_FLAG_POST_DISABLED
08961    ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
08962 #endif
08963    /* make a conference for the tx */
08964    ci.chan = 0;
08965    ci.confno = -1; /* make a new conf */
08966    ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
08967    /* first put the channel on the conference in proper mode */
08968    if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
08969    {
08970       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
08971       rpt_mutex_unlock(&myrpt->lock);
08972       ast_hangup(myrpt->pchannel);
08973       ast_hangup(myrpt->monchannel);
08974       if (myrpt->txchannel != myrpt->rxchannel) 
08975          ast_hangup(myrpt->txchannel);
08976       ast_hangup(myrpt->rxchannel);
08977       myrpt->rpt_thread = AST_PTHREADT_STOP;
08978       pthread_exit(NULL);
08979    }
08980    /* save tx conference number */
08981    myrpt->txconf = ci.confno;
08982    /* make a conference for the pseudo */
08983    ci.chan = 0;
08984    ci.confno = -1; /* make a new conf */
08985    ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
08986       (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
08987    /* first put the channel on the conference in announce mode */
08988    if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
08989    {
08990       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
08991       rpt_mutex_unlock(&myrpt->lock);
08992       ast_hangup(myrpt->pchannel);
08993       ast_hangup(myrpt->monchannel);
08994       if (myrpt->txchannel != myrpt->rxchannel) 
08995          ast_hangup(myrpt->txchannel);
08996       ast_hangup(myrpt->rxchannel);
08997       myrpt->rpt_thread = AST_PTHREADT_STOP;
08998       pthread_exit(NULL);
08999    }
09000    /* save pseudo channel conference number */
09001    myrpt->conf = ci.confno;
09002    /* make a conference for the pseudo */
09003    ci.chan = 0;
09004    if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
09005       (myrpt->zaptxchannel == myrpt->txchannel))
09006    {
09007       /* get tx channel's port number */
09008       if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
09009       {
09010          ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
09011          rpt_mutex_unlock(&myrpt->lock);
09012          ast_hangup(myrpt->pchannel);
09013          ast_hangup(myrpt->monchannel);
09014          if (myrpt->txchannel != myrpt->rxchannel) 
09015             ast_hangup(myrpt->txchannel);
09016          ast_hangup(myrpt->rxchannel);
09017          myrpt->rpt_thread = AST_PTHREADT_STOP;
09018          pthread_exit(NULL);
09019       }
09020       ci.confmode = DAHDI_CONF_MONITORTX;
09021    }
09022    else
09023    {
09024       ci.confno = myrpt->txconf;
09025       ci.confmode = DAHDI_CONF_CONFANNMON;
09026    }
09027    /* first put the channel on the conference in announce mode */
09028    if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
09029    {
09030       ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
09031       rpt_mutex_unlock(&myrpt->lock);
09032       ast_hangup(myrpt->pchannel);
09033       ast_hangup(myrpt->monchannel);
09034       if (myrpt->txchannel != myrpt->rxchannel) 
09035          ast_hangup(myrpt->txchannel);
09036       ast_hangup(myrpt->rxchannel);
09037       myrpt->rpt_thread = AST_PTHREADT_STOP;
09038       pthread_exit(NULL);
09039    }
09040    /* allocate a pseudo-channel thru asterisk */
09041    myrpt->txpchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
09042    if (!myrpt->txpchannel)
09043    {
09044       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
09045       rpt_mutex_unlock(&myrpt->lock);
09046       ast_hangup(myrpt->pchannel);
09047       ast_hangup(myrpt->monchannel);
09048       if (myrpt->txchannel != myrpt->rxchannel) 
09049          ast_hangup(myrpt->txchannel);
09050       ast_hangup(myrpt->rxchannel);
09051       myrpt->rpt_thread = AST_PTHREADT_STOP;
09052       pthread_exit(NULL);
09053    }
09054 #ifdef   AST_CDR_FLAG_POST_DISABLED
09055    ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
09056 #endif
09057    /* make a conference for the tx */
09058    ci.chan = 0;
09059    ci.confno = myrpt->txconf;
09060    ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
09061    /* first put the channel on the conference in proper mode */
09062    if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
09063    {
09064       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
09065       rpt_mutex_unlock(&myrpt->lock);
09066       ast_hangup(myrpt->txpchannel);
09067       ast_hangup(myrpt->monchannel);
09068       if (myrpt->txchannel != myrpt->rxchannel) 
09069          ast_hangup(myrpt->txchannel);
09070       ast_hangup(myrpt->rxchannel);
09071       myrpt->rpt_thread = AST_PTHREADT_STOP;
09072       pthread_exit(NULL);
09073    }
09074    /* Now, the idea here is to copy from the physical rx channel buffer
09075       into the pseudo tx buffer, and from the pseudo rx buffer into the 
09076       tx channel buffer */
09077    myrpt->links.next = &myrpt->links;
09078    myrpt->links.prev = &myrpt->links;
09079    myrpt->tailtimer = 0;
09080    myrpt->totimer = 0;
09081    myrpt->tmsgtimer = myrpt->p.tailmessagetime;
09082    myrpt->idtimer = myrpt->p.politeid;
09083    myrpt->mustid = myrpt->tailid = 0;
09084    myrpt->callmode = 0;
09085    myrpt->tounkeyed = 0;
09086    myrpt->tonotify = 0;
09087    myrpt->retxtimer = 0;
09088    myrpt->rerxtimer = 0;
09089    myrpt->skedtimer = 0;
09090    myrpt->tailevent = 0;
09091    lasttx = 0;
09092    myrpt->keyed = 0;
09093    idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
09094    myrpt->dtmfidx = -1;
09095    myrpt->dtmfbuf[0] = 0;
09096    myrpt->rem_dtmfidx = -1;
09097    myrpt->rem_dtmfbuf[0] = 0;
09098    myrpt->dtmf_time = 0;
09099    myrpt->rem_dtmf_time = 0;
09100    myrpt->disgorgetime = 0;
09101    myrpt->lastnodewhichkeyedusup[0] = '\0';
09102    myrpt->dailytxtime = 0;
09103    myrpt->totaltxtime = 0;
09104    myrpt->dailykeyups = 0;
09105    myrpt->totalkeyups = 0;
09106    myrpt->dailykerchunks = 0;
09107    myrpt->totalkerchunks = 0;
09108    myrpt->dailyexecdcommands = 0;
09109    myrpt->totalexecdcommands = 0;
09110    myrpt->timeouts = 0;
09111    myrpt->exten[0] = '\0';
09112    myrpt->lastdtmfcommand[0] = '\0';
09113    if (myrpt->p.startupmacro)
09114    {
09115       snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
09116    }
09117    rpt_mutex_unlock(&myrpt->lock);
09118    val = 1;
09119    ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
09120    val = 1;
09121    ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
09122    if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
09123    dtmfed = 0;
09124    while (ms >= 0)
09125    {
09126       struct ast_frame *f,*f1,*f2;
09127       struct ast_channel *cs[300],*cs1[300];
09128       int totx=0,elap=0,n,x,toexit=0;
09129 
09130       /* DEBUG Dump */
09131       if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
09132          struct rpt_link *zl;
09133          struct rpt_tele *zt;
09134 
09135          myrpt->disgorgetime = 0;
09136          ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
09137          ast_log(LOG_NOTICE,"totx = %d\n",totx);
09138          ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
09139          ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
09140          ast_log(LOG_NOTICE,"elap = %d\n",elap);
09141          ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
09142 
09143          ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
09144          ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
09145          ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
09146          ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
09147          ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
09148          ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
09149          ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
09150          ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
09151          ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
09152          ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
09153 
09154          zl = myrpt->links.next;
09155                   while(zl != &myrpt->links){
09156             ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",zl->name);
09157             ast_log(LOG_NOTICE,"        link->lasttx %d\n",zl->lasttx);
09158             ast_log(LOG_NOTICE,"        link->lastrx %d\n",zl->lastrx);
09159             ast_log(LOG_NOTICE,"        link->connected %d\n",zl->connected);
09160             ast_log(LOG_NOTICE,"        link->hasconnected %d\n",zl->hasconnected);
09161             ast_log(LOG_NOTICE,"        link->outbound %d\n",zl->outbound);
09162             ast_log(LOG_NOTICE,"        link->disced %d\n",zl->disced);
09163             ast_log(LOG_NOTICE,"        link->killme %d\n",zl->killme);
09164             ast_log(LOG_NOTICE,"        link->disctime %ld\n",zl->disctime);
09165             ast_log(LOG_NOTICE,"        link->retrytimer %ld\n",zl->retrytimer);
09166             ast_log(LOG_NOTICE,"        link->retries = %d\n",zl->retries);
09167             ast_log(LOG_NOTICE,"        link->reconnects = %d\n",zl->reconnects);
09168                            zl = zl->next;
09169                   }
09170                                                                                                                                
09171          zt = myrpt->tele.next;
09172          if(zt != &myrpt->tele)
09173             ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
09174                   while(zt != &myrpt->tele){
09175             ast_log(LOG_NOTICE,"        Telemetry mode: %d\n",zt->mode);
09176                            zt = zt->next;
09177                   }
09178          ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
09179 
09180       }  
09181 
09182 
09183       if (myrpt->reload)
09184       {
09185          struct rpt_tele *telem;
09186 
09187          rpt_mutex_lock(&myrpt->lock);
09188          telem = myrpt->tele.next;
09189          while(telem != &myrpt->tele)
09190          {
09191             ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
09192             telem = telem->next;
09193          }
09194          myrpt->reload = 0;
09195          rpt_mutex_unlock(&myrpt->lock);
09196          usleep(10000);
09197          /* find our index, and load the vars */
09198          for(i = 0; i < nrpts; i++)
09199          {
09200             if (&rpt_vars[i] == myrpt)
09201             {
09202                load_rpt_vars(i,0);
09203                break;
09204             }
09205          }
09206       }
09207 
09208       rpt_mutex_lock(&myrpt->lock);
09209       if (ast_check_hangup(myrpt->rxchannel)) break;
09210       if (ast_check_hangup(myrpt->txchannel)) break;
09211       if (ast_check_hangup(myrpt->pchannel)) break;
09212       if (ast_check_hangup(myrpt->monchannel)) break;
09213       if (ast_check_hangup(myrpt->txpchannel)) break;
09214       if (myrpt->zaptxchannel && ast_check_hangup(myrpt->zaptxchannel)) break;
09215 
09216       /* Set local tx with keyed */
09217       myrpt->localtx = myrpt->keyed;
09218       /* If someone's connected, and they're transmitting from their end to us, set remrx true */
09219       l = myrpt->links.next;
09220       remrx = 0;
09221       while(l != &myrpt->links)
09222       {
09223          if (l->lastrx){
09224             remrx = 1;
09225             if(l->name[0] != '0') /* Ignore '0' nodes */
09226                strcpy(myrpt->lastnodewhichkeyedusup, l->name); /* Note the node which is doing the key up */
09227          }
09228          l = l->next;
09229       }
09230       /* Create a "must_id" flag for the cleanup ID */      
09231       if(myrpt->p.idtime) /* ID time must be non-zero */
09232          myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
09233       /* Build a fresh totx from myrpt->keyed and autopatch activated */
09234       totx = myrpt->callmode;
09235       /* If full duplex, add local tx to totx */
09236       if (myrpt->p.duplex > 1) 
09237       {
09238          totx = totx || myrpt->localtx;
09239       }
09240       /* Traverse the telemetry list to see what's queued */
09241       identqueued = 0;
09242       othertelemqueued = 0;
09243       tailmessagequeued = 0;
09244       ctqueued = 0;
09245       telem = myrpt->tele.next;
09246       while(telem != &myrpt->tele)
09247       {
09248          if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
09249             identqueued = 1; /* Identification telemetry */
09250          }
09251          else if(telem->mode == TAILMSG)
09252          {
09253             tailmessagequeued = 1; /* Tail message telemetry */
09254          }
09255          else
09256          {
09257             if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
09258                othertelemqueued = 1;  /* Other telemetry */
09259             else
09260                ctqueued = 1; /* Courtesy tone telemetry */
09261          }
09262          telem = telem->next;
09263       }
09264    
09265       /* Add in any "other" telemetry, unless specified otherwise */
09266       if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
09267       /* Update external (to links) transmitter PTT state with everything but ID, CT, and tailmessage telemetry */
09268       myrpt->exttx = totx;
09269       totx = totx || myrpt->dtmf_local_timer;
09270       /* If half or 3/4 duplex, add localtx to external link tx */
09271       if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
09272       /* Add in ID telemetry to local transmitter */
09273       totx = totx || remrx;
09274       /* If 3/4 or full duplex, add in ident and CT telemetry */
09275       if (myrpt->p.duplex > 0)
09276          totx = totx || identqueued || ctqueued;
09277       /* If full duplex, add local dtmf stuff active */
09278       if (myrpt->p.duplex > 1) 
09279       {
09280          totx = totx || (myrpt->dtmfidx > -1) ||
09281             myrpt->cmdnode[0];
09282       }
09283       /* Reset time out timer variables if there is no activity */
09284       if (!totx) 
09285       {
09286          myrpt->totimer = myrpt->p.totime;
09287          myrpt->tounkeyed = 0;
09288          myrpt->tonotify = 0;
09289       }
09290       else{
09291          myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
09292             myrpt->p.althangtime : /* Initialize tail timer */
09293             myrpt->p.hangtime;
09294       }
09295       /* Disable the local transmitter if we are timed out */
09296       totx = totx && myrpt->totimer;
09297       /* if timed-out and not said already, say it */
09298       if ((!myrpt->totimer) && (!myrpt->tonotify))
09299       {
09300          myrpt->tonotify = 1;
09301          myrpt->timeouts++;
09302          rpt_mutex_unlock(&myrpt->lock);
09303          rpt_telemetry(myrpt,TIMEOUT,NULL);
09304          rpt_mutex_lock(&myrpt->lock);
09305       }
09306 
09307       /* If unkey and re-key, reset time out timer */
09308       if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
09309       {
09310          myrpt->tounkeyed = 1;
09311       }
09312       if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
09313       {
09314          myrpt->totimer = myrpt->p.totime;
09315          myrpt->tounkeyed = 0;
09316          myrpt->tonotify = 0;
09317          rpt_mutex_unlock(&myrpt->lock);
09318          continue;
09319       }
09320       /* if timed-out and in circuit busy after call */
09321       if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
09322       {
09323          myrpt->callmode = 0;
09324       }
09325       /* get rid of tail if timed out */
09326       if (!myrpt->totimer) myrpt->tailtimer = 0;
09327       /* if not timed-out, add in tail */
09328       if (myrpt->totimer) totx = totx || myrpt->tailtimer;
09329       /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
09330       /* If tail message, kill the message if someone keys up over it */ 
09331       if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
09332          int hasid = 0,hastalkover = 0;
09333 
09334          telem = myrpt->tele.next;
09335          while(telem != &myrpt->tele){
09336             if(telem->mode == ID){
09337                if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
09338                hasid = 1;
09339             }
09340             if(telem->mode == TAILMSG){
09341                                         if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
09342                                 }
09343             if (telem->mode == IDTALKOVER) hastalkover = 1;
09344             telem = telem->next;
09345          }
09346          rpt_mutex_unlock(&myrpt->lock);
09347          if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL); /* Start Talkover ID */
09348          rpt_mutex_lock(&myrpt->lock);
09349       }
09350       /* Try to be polite */
09351       /* If the repeater has been inactive for longer than the ID time, do an initial ID in the tail*/
09352       /* If within 30 seconds of the time to ID, try do it in the tail */
09353       /* else if at ID time limit, do it right over the top of them */
09354       /* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */
09355       if(myrpt->mustid && (!myrpt->idtimer))
09356          queue_id(myrpt);
09357 
09358       if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
09359           (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer)) /* ID time must be non-zero */ 
09360          {
09361             myrpt->tailid = 1;
09362          }
09363 
09364       /* If tail timer expires, then check for tail messages */
09365 
09366       if(myrpt->tailevent){
09367          myrpt->tailevent = 0;
09368          if(myrpt->tailid){
09369             totx = 1;
09370             queue_id(myrpt);
09371          }
09372          else if ((myrpt->p.tailmessages[0]) &&
09373             (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
09374                totx = 1;
09375                myrpt->tmsgtimer = myrpt->p.tailmessagetime; 
09376                rpt_mutex_unlock(&myrpt->lock);
09377                rpt_telemetry(myrpt, TAILMSG, NULL);
09378                rpt_mutex_lock(&myrpt->lock);
09379          }  
09380       }
09381 
09382       /* Main TX control */
09383 
09384       /* let telemetry transmit anyway (regardless of timeout) */
09385       if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
09386       if (totx && (!lasttx))
09387       {
09388          char mydate[100],myfname[100];
09389          time_t myt;
09390 
09391          if (myrpt->monstream) ast_closestream(myrpt->monstream);
09392          if (myrpt->p.archivedir)
09393          {
09394             long blocksleft;
09395 
09396             time(&myt);
09397             strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
09398                localtime(&myt));
09399             sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
09400                myrpt->name,mydate);
09401             myrpt->monstream = ast_writefile(myfname,"wav49",
09402                "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
09403             if (myrpt->p.monminblocks)
09404             {
09405                blocksleft = diskavail(myrpt);
09406                if (blocksleft >= myrpt->p.monminblocks)
09407                   donodelog(myrpt,"TXKEY,MAIN");
09408             } else donodelog(myrpt,"TXKEY,MAIN");
09409          }
09410          lasttx = 1;
09411          myrpt->dailykeyups++;
09412          myrpt->totalkeyups++;
09413          rpt_mutex_unlock(&myrpt->lock);
09414          ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
09415          rpt_mutex_lock(&myrpt->lock);
09416       }
09417       totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
09418       if ((!totx) && lasttx)
09419       {
09420          if (myrpt->monstream) ast_closestream(myrpt->monstream);
09421          myrpt->monstream = NULL;
09422 
09423          lasttx = 0;
09424          rpt_mutex_unlock(&myrpt->lock);
09425          ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
09426          rpt_mutex_lock(&myrpt->lock);
09427          donodelog(myrpt,"TXUNKEY,MAIN");
09428       }
09429       time(&t);
09430       /* if DTMF timeout */
09431       if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
09432       {
09433          myrpt->dtmfidx = -1;
09434          myrpt->dtmfbuf[0] = 0;
09435       }        
09436       /* if remote DTMF timeout */
09437       if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
09438       {
09439          myrpt->rem_dtmfidx = -1;
09440          myrpt->rem_dtmfbuf[0] = 0;
09441       }  
09442 
09443       /* Reconnect */
09444    
09445       l = myrpt->links.next;
09446       while(l != &myrpt->links)
09447       {
09448          if (l->killme)
09449          {
09450             /* remove from queue */
09451             remque((struct qelem *) l);
09452             if (!strcmp(myrpt->cmdnode,l->name))
09453                myrpt->cmdnode[0] = 0;
09454             rpt_mutex_unlock(&myrpt->lock);
09455             /* hang-up on call to device */
09456             if (l->chan) ast_hangup(l->chan);
09457             ast_hangup(l->pchan);
09458             free(l);
09459             rpt_mutex_lock(&myrpt->lock);
09460             /* re-start link traversal */
09461             l = myrpt->links.next;
09462             continue;
09463          }
09464          l = l->next;
09465       }
09466       n = 0;
09467       cs[n++] = myrpt->rxchannel;
09468       cs[n++] = myrpt->pchannel;
09469       cs[n++] = myrpt->monchannel;
09470       cs[n++] = myrpt->txpchannel;
09471       if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
09472       if (myrpt->zaptxchannel != myrpt->txchannel)
09473          cs[n++] = myrpt->zaptxchannel;
09474       l = myrpt->links.next;
09475       while(l != &myrpt->links)
09476       {
09477          if ((!l->killme) && (!l->disctime) && l->chan)
09478          {
09479             cs[n++] = l->chan;
09480             cs[n++] = l->pchan;
09481          }
09482          l = l->next;
09483       }
09484       rpt_mutex_unlock(&myrpt->lock);
09485       ms = MSWAIT;
09486       for(x = 0; x < n; x++)
09487       {
09488          int s = -(-x - myrpt->scram - 1) % n;
09489          cs1[x] = cs[s];
09490       }
09491       myrpt->scram++;
09492       who = ast_waitfor_n(cs1,n,&ms);
09493       if (who == NULL) ms = 0;
09494       elap = MSWAIT - ms;
09495       rpt_mutex_lock(&myrpt->lock);
09496       l = myrpt->links.next;
09497       while(l != &myrpt->links)
09498       {
09499          if (l->linklisttimer)
09500          {
09501             l->linklisttimer -= elap;
09502             if (l->linklisttimer < 0) l->linklisttimer = 0;
09503          }
09504          if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
09505          {
09506             struct   ast_frame lf;
09507 
09508             memset(&lf,0,sizeof(lf));
09509             lf.frametype = AST_FRAME_TEXT;
09510             lf.subclass = 0;
09511             lf.offset = 0;
09512             lf.mallocd = 0;
09513             lf.samples = 0;
09514             l->linklisttimer = LINKLISTTIME;
09515             strcpy(lstr,"L ");
09516             __mklinklist(myrpt,l,lstr + 2);
09517             if (l->chan)
09518             {
09519                lf.datalen = strlen(lstr) + 1;
09520                lf.data = lstr;
09521                ast_write(l->chan,&lf);
09522                if (debug > 6) ast_log(LOG_NOTICE,
09523                   "@@@@ node %s sent node string %s to node %s\n",
09524                      myrpt->name,lstr,l->name);
09525             }
09526          }
09527 #ifndef  OLDKEY
09528          if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
09529          {
09530             l->retxtimer = 0;
09531             if (l->chan && l->phonemode == 0) 
09532             {
09533                if (l->lasttx)
09534                   ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
09535                else
09536                   ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
09537             }
09538          }
09539          if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
09540          {
09541             if (debug == 7) printf("@@@@ rx un-key\n");
09542             l->lastrx = 0;
09543             l->rerxtimer = 0;
09544             if(myrpt->p.duplex) 
09545                rpt_telemetry(myrpt,LINKUNKEY,l);
09546             if (myrpt->p.archivedir)
09547             {
09548                char str[100];
09549 
09550                l->lastrx1 = 0;
09551                sprintf(str,"RXUNKEY(T),%s",l->name);
09552                donodelog(myrpt,str);
09553             }
09554          }
09555 #endif
09556          if (l->disctime) /* Disconnect timer active on a channel ? */
09557          {
09558             l->disctime -= elap;
09559             if (l->disctime <= 0) /* Disconnect timer expired on inbound channel ? */
09560                l->disctime = 0; /* Yep */
09561          }
09562 
09563          if (l->retrytimer)
09564          {
09565             l->retrytimer -= elap;
09566             if (l->retrytimer < 0) l->retrytimer = 0;
09567          }
09568 
09569          /* Tally connect time */
09570          l->connecttime += elap;
09571 
09572          /* ignore non-timing channels */
09573          if (l->elaptime < 0)
09574          {
09575             l = l->next;
09576             continue;
09577          }
09578          l->elaptime += elap;
09579          /* if connection has taken too long */
09580          if ((l->elaptime > MAXCONNECTTIME) && 
09581             ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
09582          {
09583             l->elaptime = 0;
09584             rpt_mutex_unlock(&myrpt->lock);
09585             if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
09586             rpt_mutex_lock(&myrpt->lock);
09587             break;
09588          }
09589          if ((!l->chan) && (!l->retrytimer) && l->outbound && 
09590             (l->retries++ < l->max_retries) && (l->hasconnected))
09591          {
09592             if (l->chan) ast_hangup(l->chan);
09593             l->chan = 0;
09594             rpt_mutex_unlock(&myrpt->lock);
09595             if ((l->name[0] != '0') && (!l->isremote))
09596             {
09597                if (attempt_reconnect(myrpt,l) == -1)
09598                {
09599                   l->retrytimer = RETRY_TIMER_MS;
09600                } 
09601             }
09602             else 
09603             {
09604                l->retrytimer = l->max_retries + 1;
09605             }
09606 
09607             rpt_mutex_lock(&myrpt->lock);
09608             break;
09609          }
09610          if ((!l->chan) && (!l->retrytimer) && l->outbound &&
09611             (l->retries >= l->max_retries))
09612          {
09613             /* remove from queue */
09614             remque((struct qelem *) l);
09615             if (!strcmp(myrpt->cmdnode,l->name))
09616                myrpt->cmdnode[0] = 0;
09617             rpt_mutex_unlock(&myrpt->lock);
09618             if (l->name[0] != '0')
09619             {
09620                if (!l->hasconnected)
09621                   rpt_telemetry(myrpt,CONNFAIL,l);
09622                else rpt_telemetry(myrpt,REMDISC,l);
09623             }
09624             if (myrpt->p.archivedir)
09625             {
09626                char str[100];
09627 
09628                if (!l->hasconnected)
09629                   sprintf(str,"LINKFAIL,%s",l->name);
09630                else
09631                   sprintf(str,"LINKDISC,%s",l->name);
09632                donodelog(myrpt,str);
09633             }
09634             /* hang-up on call to device */
09635             ast_hangup(l->pchan);
09636             free(l);
09637                                 rpt_mutex_lock(&myrpt->lock);
09638             break;
09639          }
09640                         if ((!l->chan) && (!l->disctime) && (!l->outbound))
09641                         {
09642                                 /* remove from queue */
09643                                 remque((struct qelem *) l);
09644                                 if (!strcmp(myrpt->cmdnode,l->name))
09645                                         myrpt->cmdnode[0] = 0;
09646                                 rpt_mutex_unlock(&myrpt->lock);
09647             if (l->name[0] != '0') 
09648             {
09649                                    rpt_telemetry(myrpt,REMDISC,l);
09650             }
09651             if (myrpt->p.archivedir)
09652             {
09653                char str[100];
09654 
09655                sprintf(str,"LINKDISC,%s",l->name);
09656                donodelog(myrpt,str);
09657             }
09658                                 /* hang-up on call to device */
09659                                 ast_hangup(l->pchan);
09660                                 free(l);
09661                                 rpt_mutex_lock(&myrpt->lock);
09662                                 break;
09663                         }
09664          l = l->next;
09665       }
09666       if(totx){
09667          myrpt->dailytxtime += elap;
09668          myrpt->totaltxtime += elap;
09669       }
09670       i = myrpt->tailtimer;
09671       if (myrpt->tailtimer) myrpt->tailtimer -= elap;
09672       if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
09673       if((i) && (myrpt->tailtimer == 0))
09674          myrpt->tailevent = 1;
09675       if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
09676       if (myrpt->totimer < 0) myrpt->totimer = 0;
09677       if (myrpt->idtimer) myrpt->idtimer -= elap;
09678       if (myrpt->idtimer < 0) myrpt->idtimer = 0;
09679       if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
09680       if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
09681       /* do macro timers */
09682       if (myrpt->macrotimer) myrpt->macrotimer -= elap;
09683       if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
09684       /* do local dtmf timer */
09685       if (myrpt->dtmf_local_timer)
09686       {
09687          if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
09688          if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
09689       }
09690       do_dtmf_local(myrpt,0);
09691       /* Execute scheduler appx. every 2 tenths of a second */
09692       if (myrpt->skedtimer <= 0){
09693          myrpt->skedtimer = 200;
09694          do_scheduler(myrpt);
09695       }
09696       else
09697          myrpt->skedtimer -=elap;
09698       if (!ms) 
09699       {
09700          rpt_mutex_unlock(&myrpt->lock);
09701          continue;
09702       }
09703       c = myrpt->macrobuf[0];
09704       time(&t);
09705       if (c && (!myrpt->macrotimer) && 
09706          starttime && (t > (starttime + START_DELAY)))
09707       {
09708          myrpt->macrotimer = MACROTIME;
09709          memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
09710          if ((c == 'p') || (c == 'P'))
09711             myrpt->macrotimer = MACROPTIME;
09712          rpt_mutex_unlock(&myrpt->lock);
09713          if (myrpt->p.archivedir)
09714          {
09715             char str[100];
09716 
09717             sprintf(str,"DTMF(M),MAIN,%c",c);
09718             donodelog(myrpt,str);
09719          }
09720          local_dtmf_helper(myrpt,c);
09721       } else rpt_mutex_unlock(&myrpt->lock);
09722       if (who == myrpt->rxchannel) /* if it was a read from rx */
09723       {
09724          int ismuted;
09725 
09726          f = ast_read(myrpt->rxchannel);
09727          if (!f)
09728          {
09729             if (debug) printf("@@@@ rpt:Hung Up\n");
09730             break;
09731          }
09732          if (f->frametype == AST_FRAME_VOICE)
09733          {
09734 #ifdef   _MDC_DECODE_H_
09735             unsigned char ubuf[2560];
09736             short *sp;
09737             int n;
09738 #endif
09739 
09740             if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
09741                memset(f->data,0,f->datalen);
09742             }
09743 
09744 #ifdef   _MDC_DECODE_H_
09745             sp = (short *) f->data;
09746             /* convert block to unsigned char */
09747             for(n = 0; n < f->datalen / 2; n++)
09748             {
09749                ubuf[n] = (*sp++ >> 8) + 128;
09750             }
09751             n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
09752             if (n == 1)
09753             {
09754                   unsigned char op,arg;
09755                   unsigned short unitID;
09756 
09757                   mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
09758                   if (debug > 2)
09759                   {
09760                      ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
09761                      ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
09762                         op & 255,arg & 255,unitID);
09763                   }
09764                   if ((op == 1) && (arg == 0))
09765                   {
09766                      myrpt->lastunit = unitID;
09767                      mdc1200_notify(myrpt,NULL,myrpt->lastunit);
09768                      mdc1200_send(myrpt,myrpt->lastunit);
09769                   }
09770             }
09771             if ((debug > 2) && (i == 2))
09772             {
09773                unsigned char op,arg,ex1,ex2,ex3,ex4;
09774                unsigned short unitID;
09775 
09776                mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
09777                   &ex1,&ex2,&ex3,&ex4);
09778                ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
09779                ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
09780                   op & 255,arg & 255,unitID);
09781                ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
09782                   ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
09783             }
09784 #endif
09785 #ifdef   __RPT_NOTCH
09786             /* apply inbound filters, if any */
09787             rpt_filter(myrpt,f->data,f->datalen / 2);
09788 #endif
09789             if (ioctl(myrpt->zaprxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
09790             {
09791                ismuted = 0;
09792             }
09793             if (dtmfed) ismuted = 1;
09794             dtmfed = 0;
09795             if (ismuted)
09796             {
09797                memset(f->data,0,f->datalen);
09798                if (myrpt->lastf1)
09799                   memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09800                if (myrpt->lastf2)
09801                   memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09802             } 
09803             if (f) f2 = ast_frdup(f);
09804             else f2 = NULL;
09805             f1 = myrpt->lastf2;
09806             myrpt->lastf2 = myrpt->lastf1;
09807             myrpt->lastf1 = f2;
09808             if (ismuted)
09809             {
09810                if (myrpt->lastf1)
09811                   memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09812                if (myrpt->lastf2)
09813                   memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09814             }
09815             if (f1)
09816             {
09817                ast_write(myrpt->pchannel,f1);
09818                ast_frfree(f1);
09819             }
09820          }
09821 #ifndef  OLD_ASTERISK
09822          else if (f->frametype == AST_FRAME_DTMF_BEGIN)
09823          {
09824             if (myrpt->lastf1)
09825                memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09826             if (myrpt->lastf2)
09827                memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09828             dtmfed = 1;
09829          }
09830 #endif
09831          else if (f->frametype == AST_FRAME_DTMF)
09832          {
09833             c = (char) f->subclass; /* get DTMF char */
09834             ast_frfree(f);
09835             if (myrpt->lastf1)
09836                memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
09837             if (myrpt->lastf2)
09838                memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
09839             dtmfed = 1;
09840             if (!myrpt->keyed) continue;
09841             c = func_xlat(myrpt,c,&myrpt->p.inxlat);
09842             if (c) local_dtmf_helper(myrpt,c);
09843             continue;
09844          }                 
09845          else if (f->frametype == AST_FRAME_CONTROL)
09846          {
09847             if (f->subclass == AST_CONTROL_HANGUP)
09848             {
09849                if (debug) printf("@@@@ rpt:Hung Up\n");
09850                ast_frfree(f);
09851                break;
09852             }
09853             /* if RX key */
09854             if (f->subclass == AST_CONTROL_RADIO_KEY)
09855             {
09856                if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink)) 
09857                {
09858                   if (debug == 7) printf("@@@@ rx key\n");
09859                   myrpt->keyed = 1;
09860                }
09861                if (myrpt->p.archivedir)
09862                {
09863                   donodelog(myrpt,"RXKEY,MAIN");
09864                }
09865             }
09866             /* if RX un-key */
09867             if (f->subclass == AST_CONTROL_RADIO_UNKEY)
09868             {
09869                if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
09870                {
09871                   if (debug == 7) printf("@@@@ rx un-key\n");
09872                   if(myrpt->p.duplex && myrpt->keyed) {
09873                      rpt_telemetry(myrpt,UNKEY,NULL);
09874                   }
09875                }
09876                myrpt->keyed = 0;
09877                if (myrpt->p.archivedir)
09878                {
09879                   donodelog(myrpt,"RXUNKEY,MAIN");
09880                }
09881             }
09882          }
09883          ast_frfree(f);
09884          continue;
09885       }
09886       if (who == myrpt->pchannel) /* if it was a read from pseudo */
09887       {
09888          f = ast_read(myrpt->pchannel);
09889          if (!f)
09890          {
09891             if (debug) printf("@@@@ rpt:Hung Up\n");
09892             break;
09893          }
09894          if (f->frametype == AST_FRAME_VOICE)
09895          {
09896             ast_write(myrpt->txpchannel,f);
09897          }
09898          if (f->frametype == AST_FRAME_CONTROL)
09899          {
09900             if (f->subclass == AST_CONTROL_HANGUP)
09901             {
09902                if (debug) printf("@@@@ rpt:Hung Up\n");
09903                ast_frfree(f);
09904                break;
09905             }
09906          }
09907          ast_frfree(f);
09908          continue;
09909       }
09910       if (who == myrpt->txchannel) /* if it was a read from tx */
09911       {
09912          f = ast_read(myrpt->txchannel);
09913          if (!f)
09914          {
09915             if (debug) printf("@@@@ rpt:Hung Up\n");
09916             break;
09917          }
09918          if (f->frametype == AST_FRAME_CONTROL)
09919          {
09920             if (f->subclass == AST_CONTROL_HANGUP)
09921             {
09922                if (debug) printf("@@@@ rpt:Hung Up\n");
09923                ast_frfree(f);
09924                break;
09925             }
09926          }
09927          ast_frfree(f);
09928          continue;
09929       }
09930       if (who == myrpt->zaptxchannel) /* if it was a read from pseudo-tx */
09931       {
09932          f = ast_read(myrpt->zaptxchannel);
09933          if (!f)
09934          {
09935             if (debug) printf("@@@@ rpt:Hung Up\n");
09936             break;
09937          }
09938          if (f->frametype == AST_FRAME_VOICE)
09939          {
09940             ast_write(myrpt->txchannel,f);
09941          }
09942          if (f->frametype == AST_FRAME_CONTROL)
09943          {
09944             if (f->subclass == AST_CONTROL_HANGUP)
09945             {
09946                if (debug) printf("@@@@ rpt:Hung Up\n");
09947                ast_frfree(f);
09948                break;
09949             }
09950          }
09951          ast_frfree(f);
09952          continue;
09953       }
09954       toexit = 0;
09955       rpt_mutex_lock(&myrpt->lock);
09956       l = myrpt->links.next;
09957       while(l != &myrpt->links)
09958       {
09959          if (l->disctime)
09960          {
09961             l = l->next;
09962             continue;
09963          }
09964          if (who == l->chan) /* if it was a read from rx */
09965          {
09966             int remnomute;
09967 
09968             remrx = 0;
09969             /* see if any other links are receiving */
09970             m = myrpt->links.next;
09971             while(m != &myrpt->links)
09972             {
09973                /* if not us, count it */
09974                if ((m != l) && (m->lastrx)) remrx = 1;
09975                m = m->next;
09976             }
09977             rpt_mutex_unlock(&myrpt->lock);
09978             remnomute = myrpt->localtx && 
09979                 (!(myrpt->cmdnode[0] || 
09980                (myrpt->dtmfidx > -1)));
09981             totx = (((l->isremote) ? (remnomute) : 
09982                myrpt->exttx) || remrx) && l->mode;
09983             if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
09984             {
09985                if (totx)
09986                {
09987                   ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
09988                }
09989                else
09990                {
09991                   ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
09992                }
09993                if (myrpt->p.archivedir)
09994                {
09995                   char str[100];
09996 
09997                   if (totx)
09998                      sprintf(str,"TXKEY,%s",l->name);
09999                   else
10000                      sprintf(str,"TXUNKEY,%s",l->name);
10001                   donodelog(myrpt,str);
10002                }
10003             }
10004             l->lasttx = totx;
10005             f = ast_read(l->chan);
10006             if (!f)
10007             {
10008                rpt_mutex_lock(&myrpt->lock);
10009                __kickshort(myrpt);
10010                rpt_mutex_unlock(&myrpt->lock);
10011                if ((!l->disced) && (!l->outbound))
10012                {
10013                   if ((l->name[0] == '0') || l->isremote)
10014                      l->disctime = 1;
10015                   else
10016                      l->disctime = DISC_TIME;
10017                   rpt_mutex_lock(&myrpt->lock);
10018                   ast_hangup(l->chan);
10019                   l->chan = 0;
10020                   break;
10021                }
10022 
10023                if (l->retrytimer) 
10024                {
10025                   ast_hangup(l->chan);
10026                   l->chan = 0;
10027                   rpt_mutex_lock(&myrpt->lock);
10028                   break; 
10029                }
10030                if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
10031                {
10032                   rpt_mutex_lock(&myrpt->lock);
10033                   if (l->chan) ast_hangup(l->chan);
10034                   l->chan = 0;
10035                   l->hasconnected = 1;
10036                   l->retrytimer = RETRY_TIMER_MS;
10037                   l->elaptime = 0;
10038                   l->connecttime = 0;
10039                   l->thisconnected = 0;
10040                   break;
10041                }
10042                rpt_mutex_lock(&myrpt->lock);
10043                /* remove from queue */
10044                remque((struct qelem *) l);
10045                if (!strcmp(myrpt->cmdnode,l->name))
10046                   myrpt->cmdnode[0] = 0;
10047                __kickshort(myrpt);
10048                rpt_mutex_unlock(&myrpt->lock);
10049                if (!l->hasconnected)
10050                   rpt_telemetry(myrpt,CONNFAIL,l);
10051                else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
10052                if (myrpt->p.archivedir)
10053                {
10054                   char str[100];
10055 
10056                   if (!l->hasconnected)
10057                      sprintf(str,"LINKFAIL,%s",l->name);
10058                   else
10059                      sprintf(str,"LINKDISC,%s",l->name);
10060                   donodelog(myrpt,str);
10061                }
10062                if (l->lastf1) ast_frfree(l->lastf1);
10063                l->lastf1 = NULL;
10064                if (l->lastf2) ast_frfree(l->lastf2);
10065                l->lastf2 = NULL;
10066                /* hang-up on call to device */
10067                ast_hangup(l->chan);
10068                ast_hangup(l->pchan);
10069                free(l);
10070                rpt_mutex_lock(&myrpt->lock);
10071                break;
10072             }
10073             if (f->frametype == AST_FRAME_VOICE)
10074             {
10075                int ismuted;
10076 
10077                if (l->phonemode)
10078                {
10079                   if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
10080                   {
10081                      ismuted = 0;
10082                   }
10083                   /* if not receiving, zero-out audio */
10084                   ismuted |= (!l->lastrx);
10085                   if (l->dtmfed && l->phonemode) ismuted = 1;
10086                   l->dtmfed = 0;
10087                   if (ismuted)
10088                   {
10089                      memset(f->data,0,f->datalen);
10090                      if (l->lastf1)
10091                         memset(l->lastf1->data,0,l->lastf1->datalen);
10092                      if (l->lastf2)
10093                         memset(l->lastf2->data,0,l->lastf2->datalen);
10094                   } 
10095                   if (f) f2 = ast_frdup(f);
10096                   else f2 = NULL;
10097                   f1 = l->lastf2;
10098                   l->lastf2 = l->lastf1;
10099                   l->lastf1 = f2;
10100                   if (ismuted)
10101                   {
10102                      if (l->lastf1)
10103                         memset(l->lastf1->data,0,l->lastf1->datalen);
10104                      if (l->lastf2)
10105                         memset(l->lastf2->data,0,l->lastf2->datalen);
10106                   }
10107                   if (f1)
10108                   {
10109                      ast_write(l->pchan,f1);
10110                      ast_frfree(f1);
10111                   }
10112                }
10113                else
10114                {
10115                   if (!l->lastrx)
10116                      memset(f->data,0,f->datalen);
10117                   ast_write(l->pchan,f);
10118                }
10119             }
10120 #ifndef  OLD_ASTERISK
10121             else if (f->frametype == AST_FRAME_DTMF_BEGIN)
10122             {
10123                if (l->lastf1)
10124                   memset(l->lastf1->data,0,l->lastf1->datalen);
10125                if (l->lastf2)
10126                   memset(l->lastf2->data,0,l->lastf2->datalen);
10127                l->dtmfed = 1;
10128             }
10129 #endif
10130 
10131             if (f->frametype == AST_FRAME_TEXT)
10132             {
10133                handle_link_data(myrpt,l,f->data);
10134             }
10135             if (f->frametype == AST_FRAME_DTMF)
10136             {
10137                if (l->lastf1)
10138                   memset(l->lastf1->data,0,l->lastf1->datalen);
10139                if (l->lastf2)
10140                   memset(l->lastf2->data,0,l->lastf2->datalen);
10141                l->dtmfed = 1;
10142                handle_link_phone_dtmf(myrpt,l,f->subclass);
10143             }
10144             if (f->frametype == AST_FRAME_CONTROL)
10145             {
10146                if (f->subclass == AST_CONTROL_ANSWER)
10147                {
10148                   char lconnected = l->connected;
10149 
10150                   __kickshort(myrpt);
10151                   l->connected = 1;
10152                   l->hasconnected = 1;
10153                   l->thisconnected = 1;
10154                   l->elaptime = -1;
10155                   if (!l->isremote) l->retries = 0;
10156                   if (!lconnected) 
10157                   {
10158                      rpt_telemetry(myrpt,CONNECTED,l);
10159                      if (myrpt->p.archivedir)
10160                      {
10161                         char str[100];
10162 
10163                         if (l->mode)
10164                            sprintf(str,"LINKTRX,%s",l->name);
10165                         else
10166                            sprintf(str,"LINKMONITOR,%s",l->name);
10167                         donodelog(myrpt,str);
10168                      }
10169                   }     
10170                   else
10171                      l->reconnects++;
10172                }
10173                /* if RX key */
10174                if (f->subclass == AST_CONTROL_RADIO_KEY)
10175                {
10176                   if (debug == 7 ) printf("@@@@ rx key\n");
10177                   l->lastrx = 1;
10178                   l->rerxtimer = 0;
10179                   if (myrpt->p.archivedir && (!l->lastrx1))
10180                   {
10181                      char str[100];
10182 
10183                      l->lastrx1 = 1;
10184                      sprintf(str,"RXKEY,%s",l->name);
10185                      donodelog(myrpt,str);
10186                   }
10187                }
10188                /* if RX un-key */
10189                if (f->subclass == AST_CONTROL_RADIO_UNKEY)
10190                {
10191                   if (debug == 7) printf("@@@@ rx un-key\n");
10192                   l->lastrx = 0;
10193                   l->rerxtimer = 0;
10194                   if(myrpt->p.duplex) 
10195                      rpt_telemetry(myrpt,LINKUNKEY,l);
10196                   if (myrpt->p.archivedir && (l->lastrx1))
10197                   {
10198                      char str[100];
10199 
10200                      l->lastrx1 = 0;
10201                      sprintf(str,"RXUNKEY,%s",l->name);
10202                      donodelog(myrpt,str);
10203                   }
10204                }
10205                if (f->subclass == AST_CONTROL_HANGUP)
10206                {
10207                   ast_frfree(f);
10208                   rpt_mutex_lock(&myrpt->lock);
10209                   __kickshort(myrpt);
10210                   rpt_mutex_unlock(&myrpt->lock);
10211                   if ((!l->outbound) && (!l->disced))
10212                   {
10213                      if ((l->name[0] == '0') || l->isremote)
10214                         l->disctime = 1;
10215                      else
10216                         l->disctime = DISC_TIME;
10217                      rpt_mutex_lock(&myrpt->lock);
10218                      ast_hangup(l->chan);
10219                      l->chan = 0;
10220                      break;
10221                   }
10222                   if (l->retrytimer) 
10223                   {
10224                      if (l->chan) ast_hangup(l->chan);
10225                      l->chan = 0;
10226                      rpt_mutex_lock(&myrpt->lock);
10227                      break;
10228                   }
10229                   if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
10230                   {
10231                      rpt_mutex_lock(&myrpt->lock);
10232                      if (l->chan) ast_hangup(l->chan);
10233                      l->chan = 0;
10234                      l->hasconnected = 1;
10235                      l->elaptime = 0;
10236                      l->retrytimer = RETRY_TIMER_MS;
10237                      l->connecttime = 0;
10238                      l->thisconnected = 0;
10239                      break;
10240                   }
10241                   rpt_mutex_lock(&myrpt->lock);
10242                   /* remove from queue */
10243                   remque((struct qelem *) l);
10244                   if (!strcmp(myrpt->cmdnode,l->name))
10245                      myrpt->cmdnode[0] = 0;
10246                   __kickshort(myrpt);
10247                   rpt_mutex_unlock(&myrpt->lock);
10248                   if (!l->hasconnected)
10249                      rpt_telemetry(myrpt,CONNFAIL,l);
10250                   else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
10251                   if (myrpt->p.archivedir)
10252                   {
10253                      char str[100];
10254 
10255                      if (!l->hasconnected)
10256                         sprintf(str,"LINKFAIL,%s",l->name);
10257                      else
10258                         sprintf(str,"LINKDISC,%s",l->name);
10259                      donodelog(myrpt,str);
10260                   }
10261                   if (l->lastf1) ast_frfree(l->lastf1);
10262                   l->lastf1 = NULL;
10263                   if (l->lastf2) ast_frfree(l->lastf2);
10264                   l->lastf2 = NULL;
10265                   /* hang-up on call to device */
10266                   ast_hangup(l->chan);
10267                   ast_hangup(l->pchan);
10268                   free(l);
10269                   rpt_mutex_lock(&myrpt->lock);
10270                   break;
10271                }
10272             }
10273             ast_frfree(f);
10274             rpt_mutex_lock(&myrpt->lock);
10275             break;
10276          }
10277          if (who == l->pchan) 
10278          {
10279             rpt_mutex_unlock(&myrpt->lock);
10280             f = ast_read(l->pchan);
10281             if (!f)
10282             {
10283                if (debug) printf("@@@@ rpt:Hung Up\n");
10284                toexit = 1;
10285                rpt_mutex_lock(&myrpt->lock);
10286                break;
10287             }
10288             if (f->frametype == AST_FRAME_VOICE)
10289             {
10290                if (l->chan) ast_write(l->chan,f);
10291             }
10292             if (f->frametype == AST_FRAME_CONTROL)
10293             {
10294                if (f->subclass == AST_CONTROL_HANGUP)
10295                {
10296                   if (debug) printf("@@@@ rpt:Hung Up\n");
10297                   ast_frfree(f);
10298                   toexit = 1;
10299                   rpt_mutex_lock(&myrpt->lock);
10300                   break;
10301                }
10302             }
10303             ast_frfree(f);
10304             rpt_mutex_lock(&myrpt->lock);
10305             break;
10306          }
10307          l = l->next;
10308       }
10309       rpt_mutex_unlock(&myrpt->lock);
10310       if (toexit) break;
10311       if (who == myrpt->monchannel) 
10312       {
10313          f = ast_read(myrpt->monchannel);
10314          if (!f)
10315          {
10316             if (debug) printf("@@@@ rpt:Hung Up\n");
10317             break;
10318          }
10319          if (f->frametype == AST_FRAME_VOICE)
10320          {
10321             if (myrpt->monstream) 
10322                ast_writestream(myrpt->monstream,f);
10323          }
10324          if (f->frametype == AST_FRAME_CONTROL)
10325          {
10326             if (f->subclass == AST_CONTROL_HANGUP)
10327             {
10328                if (debug) printf("@@@@ rpt:Hung Up\n");
10329                ast_frfree(f);
10330                break;
10331             }
10332          }
10333          ast_frfree(f);
10334          continue;
10335       }
10336       if (who == myrpt->txpchannel) /* if it was a read from remote tx */
10337       {
10338          f = ast_read(myrpt->txpchannel);
10339          if (!f)
10340          {
10341             if (debug) printf("@@@@ rpt:Hung Up\n");
10342             break;
10343          }
10344          if (f->frametype == AST_FRAME_CONTROL)
10345          {
10346             if (f->subclass == AST_CONTROL_HANGUP)
10347             {
10348                if (debug) printf("@@@@ rpt:Hung Up\n");
10349                ast_frfree(f);
10350                break;
10351             }
10352          }
10353          ast_frfree(f);
10354          continue;
10355       }
10356    }
10357    usleep(100000);
10358    ast_hangup(myrpt->pchannel);
10359    ast_hangup(myrpt->monchannel);
10360    ast_hangup(myrpt->txpchannel);
10361    if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
10362    if (myrpt->zaptxchannel != myrpt->txchannel) ast_hangup(myrpt->zaptxchannel);
10363    if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
10364    myrpt->lastf1 = NULL;
10365    if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
10366    myrpt->lastf2 = NULL;
10367    ast_hangup(myrpt->rxchannel);
10368    rpt_mutex_lock(&myrpt->lock);
10369    l = myrpt->links.next;
10370    while(l != &myrpt->links)
10371    {
10372       struct rpt_link *ll = l;
10373       /* remove from queue */
10374       remque((struct qelem *) l);
10375       /* hang-up on call to device */
10376       if (l->chan) ast_hangup(l->chan);
10377       ast_hangup(l->pchan);
10378       l = l->next;
10379       free(ll);
10380    }
10381    rpt_mutex_unlock(&myrpt->lock);
10382    if (debug) printf("@@@@ rpt:Hung up channel\n");
10383    myrpt->rpt_thread = AST_PTHREADT_STOP;
10384    pthread_exit(NULL); 
10385    return NULL;
10386 }

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

Definition at line 4162 of file app_rpt.c.

References rpt::acctcode, ast_callerid_parse(), AST_CDR_FLAG_POST_DISABLED, ast_cdr_setaccount(), ast_channel_undefer_dtmf(), ast_copy_string(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, ast_hangup(), ast_log(), ast_pbx_start(), ast_queue_frame(), ast_request(), ast_safe_sleep(), ast_senddigit(), ast_set_flag, ast_softhangup(), AST_SOFTHANGUP_DEV, rpt::callmode, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, rpt::cidx, rpt::conf, ast_channel::context, rpt::duplex, rpt::exten, ast_channel::exten, ast_channel::fds, free, rpt::lock, LOG_WARNING, MSWAIT, rpt::mydtmf, name, rpt::ourcallerid, rpt::p, rpt::patchcontext, rpt::patchdialtime, rpt::patchfarenddisconnect, rpt::patchquiet, ast_channel::pbx, rpt::pchannel, ast_channel::priority, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), strdup, ast_frame::subclass, TERM, and rpt::tonezone.

Referenced by function_autopatchup(), and local_dtmf_helper().

04163 {
04164 struct dahdi_confinfo ci;  /* conference info */
04165 struct   rpt *myrpt = (struct rpt *)this;
04166 int   res;
04167 int stopped,congstarted,dialtimer,lastcidx,aborted;
04168 struct ast_channel *mychannel,*genchannel;
04169 
04170 
04171    myrpt->mydtmf = 0;
04172    /* allocate a pseudo-channel thru asterisk */
04173    mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04174    if (!mychannel)
04175    {
04176       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04177       pthread_exit(NULL);
04178    }
04179 #ifdef   AST_CDR_FLAG_POST_DISABLED
04180    ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04181 #endif
04182    ci.chan = 0;
04183    ci.confno = myrpt->conf; /* use the pseudo conference */
04184    ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
04185       | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 
04186    /* first put the channel on the conference */
04187    if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04188    {
04189       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04190       ast_hangup(mychannel);
04191       myrpt->callmode = 0;
04192       pthread_exit(NULL);
04193    }
04194    /* allocate a pseudo-channel thru asterisk */
04195    genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04196    if (!genchannel)
04197    {
04198       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04199       ast_hangup(mychannel);
04200       pthread_exit(NULL);
04201    }
04202 #ifdef   AST_CDR_FLAG_POST_DISABLED
04203    ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
04204 #endif
04205    ci.chan = 0;
04206    ci.confno = myrpt->conf;
04207    ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
04208       | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 
04209    /* first put the channel on the conference */
04210    if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04211    {
04212       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04213       ast_hangup(mychannel);
04214       ast_hangup(genchannel);
04215       myrpt->callmode = 0;
04216       pthread_exit(NULL);
04217    }
04218    if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
04219    {
04220       ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
04221       ast_hangup(mychannel);
04222       ast_hangup(genchannel);
04223       myrpt->callmode = 0;
04224       pthread_exit(NULL);
04225    }
04226    if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
04227    {
04228       ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
04229       ast_hangup(mychannel);
04230       ast_hangup(genchannel);
04231       myrpt->callmode = 0;
04232       pthread_exit(NULL);
04233    }
04234    /* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */
04235    if ((!myrpt->patchquiet) && (tone_zone_play_tone(mychannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
04236    {
04237       ast_log(LOG_WARNING, "Cannot start dialtone\n");
04238       ast_hangup(mychannel);
04239       ast_hangup(genchannel);
04240       myrpt->callmode = 0;
04241       pthread_exit(NULL);
04242    }
04243    stopped = 0;
04244    congstarted = 0;
04245    dialtimer = 0;
04246    lastcidx = 0;
04247    aborted = 0;
04248 
04249 
04250    while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
04251    {
04252 
04253       if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
04254          dialtimer = 0;
04255          lastcidx = myrpt->cidx;
04256       }     
04257 
04258       if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){ 
04259          rpt_mutex_lock(&myrpt->lock);
04260          aborted = 1;
04261          myrpt->callmode = 0;
04262          rpt_mutex_unlock(&myrpt->lock);
04263          break;
04264       }
04265    
04266       if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
04267       {
04268          stopped = 1;
04269          /* stop dial tone */
04270          tone_zone_play_tone(mychannel->fds[0],-1);
04271       }
04272       if (myrpt->callmode == 4)
04273       {
04274          if(!congstarted){
04275             congstarted = 1;
04276             /* start congestion tone */
04277             tone_zone_play_tone(mychannel->fds[0],DAHDI_TONE_CONGESTION);
04278          }
04279       }
04280       res = ast_safe_sleep(mychannel, MSWAIT);
04281       if (res < 0)
04282       {
04283          ast_hangup(mychannel);
04284          ast_hangup(genchannel);
04285          rpt_mutex_lock(&myrpt->lock);
04286          myrpt->callmode = 0;
04287          rpt_mutex_unlock(&myrpt->lock);
04288          pthread_exit(NULL);
04289       }
04290       dialtimer += MSWAIT;
04291    }
04292    /* stop any tone generation */
04293    tone_zone_play_tone(mychannel->fds[0],-1);
04294    /* end if done */
04295    if (!myrpt->callmode)
04296    {
04297       ast_hangup(mychannel);
04298       ast_hangup(genchannel);
04299       rpt_mutex_lock(&myrpt->lock);
04300       myrpt->callmode = 0;
04301       rpt_mutex_unlock(&myrpt->lock);
04302       if((!myrpt->patchquiet) && aborted)
04303          rpt_telemetry(myrpt, TERM, NULL);
04304       pthread_exit(NULL);        
04305    }
04306 
04307    if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
04308       char *name, *loc, *instr;
04309       instr = strdup(myrpt->p.ourcallerid);
04310       if(instr){
04311          ast_callerid_parse(instr, &name, &loc);
04312          if(loc){
04313             if(mychannel->cid.cid_num)
04314                free(mychannel->cid.cid_num);
04315             mychannel->cid.cid_num = strdup(loc);
04316          }
04317          if(name){
04318             if(mychannel->cid.cid_name)
04319                free(mychannel->cid.cid_name);
04320             mychannel->cid.cid_name = strdup(name);
04321          }
04322          free(instr);
04323       }
04324    }
04325 
04326    ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
04327    ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
04328    
04329    if (myrpt->p.acctcode)
04330       ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
04331    mychannel->priority = 1;
04332    ast_channel_undefer_dtmf(mychannel);
04333    if (ast_pbx_start(mychannel) < 0)
04334    {
04335       ast_log(LOG_WARNING, "Unable to start PBX!!\n");
04336       ast_hangup(mychannel);
04337       ast_hangup(genchannel);
04338       rpt_mutex_lock(&myrpt->lock);
04339       myrpt->callmode = 0;
04340       rpt_mutex_unlock(&myrpt->lock);
04341       pthread_exit(NULL);
04342    }
04343    usleep(10000);
04344    rpt_mutex_lock(&myrpt->lock);
04345    myrpt->callmode = 3;
04346    /* set appropriate conference for the pseudo */
04347    ci.chan = 0;
04348    ci.confno = myrpt->conf;
04349    ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
04350       (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
04351    /* first put the channel on the conference in announce mode */
04352    if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04353    {
04354       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04355       ast_hangup(mychannel);
04356       ast_hangup(genchannel);
04357       myrpt->callmode = 0;
04358       pthread_exit(NULL);
04359    }
04360    while(myrpt->callmode)
04361    {
04362       if ((!mychannel->pbx) && (myrpt->callmode != 4))
04363       {
04364          if(myrpt->patchfarenddisconnect){ /* If patch is setup for far end disconnect */
04365             myrpt->callmode = 0;
04366             if(!myrpt->patchquiet){
04367                rpt_mutex_unlock(&myrpt->lock);
04368                rpt_telemetry(myrpt, TERM, NULL);
04369                rpt_mutex_lock(&myrpt->lock);
04370             }
04371          }
04372          else{ /* Send congestion until patch is downed by command */
04373             myrpt->callmode = 4;
04374             rpt_mutex_unlock(&myrpt->lock);
04375             /* start congestion tone */
04376             tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
04377             rpt_mutex_lock(&myrpt->lock);
04378          }
04379       }
04380       if (myrpt->mydtmf)
04381       {
04382          struct ast_frame wf = {AST_FRAME_DTMF, } ;
04383          wf.subclass = myrpt->mydtmf;
04384          rpt_mutex_unlock(&myrpt->lock);
04385          ast_queue_frame(mychannel,&wf);
04386          ast_senddigit(genchannel,myrpt->mydtmf);
04387          rpt_mutex_lock(&myrpt->lock);
04388          myrpt->mydtmf = 0;
04389       }
04390       rpt_mutex_unlock(&myrpt->lock);
04391       usleep(MSWAIT * 1000);
04392       rpt_mutex_lock(&myrpt->lock);
04393    }
04394    rpt_mutex_unlock(&myrpt->lock);
04395    tone_zone_play_tone(genchannel->fds[0],-1);
04396    if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
04397    ast_hangup(genchannel);
04398    rpt_mutex_lock(&myrpt->lock);
04399    myrpt->callmode = 0;
04400    rpt_mutex_unlock(&myrpt->lock);
04401    /* set appropriate conference for the pseudo */
04402    ci.chan = 0;
04403    ci.confno = myrpt->conf;
04404    ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
04405       (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
04406    /* first put the channel on the conference in announce mode */
04407    if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
04408    {
04409       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
04410    }
04411    pthread_exit(NULL);
04412 }

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

Definition at line 1966 of file app_rpt.c.

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

01967 {
01968    int newlevel;
01969 
01970         if (argc != 4)
01971                 return RESULT_SHOWUSAGE;
01972         newlevel = myatoi(argv[3]);
01973         if((newlevel < 0) || (newlevel > 7))
01974                 return RESULT_SHOWUSAGE;
01975         if(newlevel)
01976                 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
01977         else
01978                 ast_cli(fd, "app_rpt Debugging disabled\n");
01979 
01980         debug = newlevel;                                                                                                                          
01981         return RESULT_SUCCESS;
01982 }

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

Definition at line 1988 of file app_rpt.c.

References ast_cli(), name, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rpt_vars.

01989 {
01990    int i;
01991 
01992         if (argc != 3)
01993                 return RESULT_SHOWUSAGE;
01994 
01995    for(i = 0; i < nrpts; i++)
01996    {
01997       if (!strcmp(argv[2],rpt_vars[i].name))
01998       {
01999          rpt_vars[i].disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
02000               ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
02001               return RESULT_SUCCESS;
02002       }
02003    }
02004    return RESULT_FAILURE;
02005 }

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

Definition at line 2408 of file app_rpt.c.

References ast_cli(), busy, rpt::lock, rpt::macrobuf, MACROTIME, rpt::macrotimer, MAXMACRO, name, RESULT_FAILURE, RESULT_SHOWUSAGE, rpt_mutex_lock, rpt_mutex_unlock, and rpt_vars.

02409 {
02410    int   i,busy=0;
02411 
02412         if (argc != 4) return RESULT_SHOWUSAGE;
02413 
02414    for(i = 0; i < nrpts; i++){
02415       if(!strcmp(argv[2], rpt_vars[i].name)){
02416          struct rpt *myrpt = &rpt_vars[i];
02417          rpt_mutex_lock(&myrpt->lock);
02418          if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
02419             rpt_mutex_unlock(&myrpt->lock);
02420             busy=1;
02421          }
02422          if(!busy){
02423             myrpt->macrotimer = MACROTIME;
02424             strncat(myrpt->macrobuf, argv[3], MAXMACRO - strlen(myrpt->macrobuf) - 1);
02425          }
02426          rpt_mutex_unlock(&myrpt->lock);
02427       }
02428    }
02429    if(busy){
02430       ast_cli(fd, "Function decoder busy");
02431    }
02432    return RESULT_FAILURE;
02433 }

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

Definition at line 2236 of file app_rpt.c.

References ast_cli(), ast_log(), rpt_link::chan, rpt_link::chan_stat, rpt_lstat::connecttime, rpt_link::connecttime, free, rpt::links, rpt::lock, LOG_ERROR, malloc, MAXPEERSTR, MAXREMSTR, rpt_link::mode, rpt_link::name, name, rpt_link::next, rpt_lstat::next, NRPTSTAT, rpt_link::outbound, pbx_substitute_variables_helper(), rpt_lstat::prev, rpt_link::reconnects, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, rpt_mutex_lock, rpt_mutex_unlock, rpt_vars, s, t, and rpt_link::thisconnected.

02237 {
02238    int i,j;
02239    char *connstate;
02240    struct rpt *myrpt;
02241    struct rpt_link *l;
02242    struct rpt_lstat *s,*t;
02243    struct rpt_lstat s_head;
02244    if(argc != 3)
02245       return RESULT_SHOWUSAGE;
02246 
02247    s = NULL;
02248    s_head.next = &s_head;
02249    s_head.prev = &s_head;
02250 
02251    for(i = 0; i < nrpts; i++)
02252    {
02253       if (!strcmp(argv[2],rpt_vars[i].name)){
02254          /* Make a copy of all stat variables while locked */
02255          myrpt = &rpt_vars[i];
02256          rpt_mutex_lock(&myrpt->lock); /* LOCK */
02257          /* Traverse the list of connected nodes */
02258          j = 0;
02259          l = myrpt->links.next;
02260          while(l && (l != &myrpt->links)){
02261             if (l->name[0] == '0'){ /* Skip '0' nodes */
02262                l = l->next;
02263                continue;
02264             }
02265             if((s = (struct rpt_lstat *) malloc(sizeof(struct rpt_lstat))) == NULL){
02266                ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
02267                rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
02268                return RESULT_FAILURE;
02269             }
02270             memset(s, 0, sizeof(struct rpt_lstat));
02271             strncpy(s->name, l->name, MAXREMSTR - 1);
02272             if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
02273             else strcpy(s->peer,"(none)");
02274             s->mode = l->mode;
02275             s->outbound = l->outbound;
02276             s->reconnects = l->reconnects;
02277             s->connecttime = l->connecttime;
02278             s->thisconnected = l->thisconnected;
02279             memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
02280             insque((struct qelem *) s, (struct qelem *) s_head.next);
02281             memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
02282             l = l->next;
02283          }
02284          rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
02285          ast_cli(fd, "NODE      PEER                RECONNECTS  DIRECTION  CONNECT TIME        CONNECT STATE\n");
02286          ast_cli(fd, "----      ----                ----------  ---------  ------------        -------------\n");
02287 
02288          for(s = s_head.next; s != &s_head; s = s->next){
02289             int hours, minutes, seconds;
02290             long long connecttime = s->connecttime;
02291             char conntime[21];
02292             hours = (int) connecttime/3600000;
02293             connecttime %= 3600000;
02294             minutes = (int) connecttime/60000;
02295             connecttime %= 60000;
02296             seconds = (int)  connecttime/1000;
02297             connecttime %= 1000;
02298             snprintf(conntime, 20, "%02d:%02d:%02d.%d",
02299                hours, minutes, seconds, (int) connecttime);
02300             conntime[20] = 0;
02301             if(s->thisconnected)
02302                connstate  = "ESTABLISHED";
02303             else
02304                connstate = "CONNECTING";
02305             ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
02306                s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
02307          }  
02308          /* destroy our local link queue */
02309          s = s_head.next;
02310          while(s != &s_head){
02311             t = s;
02312             s = s->next;
02313             remque((struct qelem *)t);
02314             free(t);
02315          }        
02316          return RESULT_SUCCESS;
02317       }
02318    }
02319    return RESULT_FAILURE;
02320 }

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

Definition at line 2326 of file app_rpt.c.

References __mklinklist(), ast_cli(), finddelim(), rpt::lock, MAXLINKLIST, mycompar(), name, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, rpt_mutex_lock, rpt_mutex_unlock, and rpt_vars.

02327 {
02328    int i,j;
02329    char ns;
02330    char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
02331    struct rpt *myrpt;
02332    if(argc != 3)
02333       return RESULT_SHOWUSAGE;
02334 
02335    for(i = 0; i < nrpts; i++)
02336    {
02337       if (!strcmp(argv[2],rpt_vars[i].name)){
02338          /* Make a copy of all stat variables while locked */
02339          myrpt = &rpt_vars[i];
02340          rpt_mutex_lock(&myrpt->lock); /* LOCK */
02341          __mklinklist(myrpt,NULL,lbuf);
02342          rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
02343          /* parse em */
02344          ns = finddelim(lbuf,strs,MAXLINKLIST);
02345          /* sort em */
02346          if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
02347          ast_cli(fd,"\n");
02348          ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
02349          for(j = 0 ;; j++){
02350             if(!strs[j]){
02351                if(!j){
02352                   ast_cli(fd,"<NONE>");
02353                }
02354                break;
02355             }
02356             ast_cli(fd, "%s", strs[j]);
02357             if(j % 8 == 7){
02358                ast_cli(fd, "\n");
02359             }
02360             else{
02361                if(strs[j + 1])
02362                   ast_cli(fd, ", ");
02363             }
02364          }
02365          ast_cli(fd,"\n\n");
02366          return RESULT_SUCCESS;
02367       }
02368    }
02369    return RESULT_FAILURE;
02370 }

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

Definition at line 2376 of file app_rpt.c.

References reload(), RESULT_FAILURE, RESULT_SHOWUSAGE, and rpt_vars.

02377 {
02378 int   n;
02379 
02380         if (argc > 2) return RESULT_SHOWUSAGE;
02381 
02382    for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
02383 
02384    return RESULT_FAILURE;
02385 }

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

Definition at line 2391 of file app_rpt.c.

References ast_softhangup(), AST_SOFTHANGUP_DEV, RESULT_FAILURE, RESULT_SHOWUSAGE, rpt_vars, and rpt::rxchannel.

02392 {
02393 int   i;
02394 
02395         if (argc > 2) return RESULT_SHOWUSAGE;
02396    for(i = 0; i < nrpts; i++)
02397    {
02398       if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
02399    }
02400    return RESULT_FAILURE;
02401 }

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

Definition at line 2011 of file app_rpt.c.

References ast_cli(), ast_strdupa, rpt::callmode, rpt::dailyexecdcommands, rpt::dailykerchunks, rpt::dailykeyups, rpt::dailytxtime, rpt::exten, rpt::keyed, rpt::lastdtmfcommand, rpt::lastnodewhichkeyedusup, rpt::links, rpt::lock, MAX_STAT_LINKS, rpt::mustid, rpt::name, rpt_link::name, name, rpt_link::next, rpt::p, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, rpt_mutex_lock, rpt_mutex_unlock, rpt_vars, rpt::s, rpt::sysstate_cur, rpt::tailid, rpt::timeouts, rpt::totalexecdcommands, rpt::totalkerchunks, rpt::totalkeyups, rpt::totaltxtime, rpt::totime, and rpt::totimer.

02012 {
02013    int i,j;
02014    int dailytxtime, dailykerchunks;
02015    int totalkerchunks, dailykeyups, totalkeyups, timeouts;
02016    int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
02017    long long totaltxtime;
02018    struct   rpt_link *l;
02019    char *listoflinks[MAX_STAT_LINKS];  
02020    char *lastnodewhichkeyedusup, *lastdtmfcommand;
02021    char *tot_state, *ider_state, *patch_state;
02022    char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
02023    char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
02024    struct rpt *myrpt;
02025 
02026    static char *not_applicable = "N/A";
02027 
02028    if(argc != 3)
02029       return RESULT_SHOWUSAGE;
02030 
02031    for(i = 0 ; i < MAX_STAT_LINKS; i++)
02032       listoflinks[i] = NULL;
02033 
02034    tot_state = ider_state = 
02035    patch_state = reverse_patch_state = 
02036    input_signal = called_number = 
02037    lastdtmfcommand = not_applicable;
02038 
02039    for(i = 0; i < nrpts; i++)
02040    {
02041       if (!strcmp(argv[2],rpt_vars[i].name)){
02042          /* Make a copy of all stat variables while locked */
02043          myrpt = &rpt_vars[i];
02044          rpt_mutex_lock(&myrpt->lock); /* LOCK */
02045 
02046          dailytxtime = myrpt->dailytxtime;
02047          totaltxtime = myrpt->totaltxtime;
02048          dailykeyups = myrpt->dailykeyups;
02049          totalkeyups = myrpt->totalkeyups;
02050          dailykerchunks = myrpt->dailykerchunks;
02051          totalkerchunks = myrpt->totalkerchunks;
02052          dailyexecdcommands = myrpt->dailyexecdcommands;
02053          totalexecdcommands = myrpt->totalexecdcommands;
02054          timeouts = myrpt->timeouts;
02055 
02056          /* Traverse the list of connected nodes */
02057          reverse_patch_state = "DOWN";
02058          j = 0;
02059          l = myrpt->links.next;
02060          while(l && (l != &myrpt->links)){
02061             if (l->name[0] == '0'){ /* Skip '0' nodes */
02062                reverse_patch_state = "UP";
02063                l = l->next;
02064                continue;
02065             }
02066             listoflinks[j] = ast_strdupa(l->name);
02067             if(listoflinks[j])
02068                j++;
02069             l = l->next;
02070          }
02071 
02072          lastnodewhichkeyedusup = ast_strdupa(myrpt->lastnodewhichkeyedusup);       
02073          if((!lastnodewhichkeyedusup) || (!strlen(lastnodewhichkeyedusup)))
02074             lastnodewhichkeyedusup = not_applicable;
02075 
02076          if(myrpt->keyed)
02077             input_signal = "YES";
02078          else
02079             input_signal = "NO";
02080 
02081          if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
02082             sys_ena = "DISABLED";
02083          else
02084             sys_ena = "ENABLED";
02085 
02086          if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
02087             tot_ena = "DISABLED";
02088          else
02089             tot_ena = "ENABLED";
02090 
02091          if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
02092             link_ena = "DISABLED";
02093          else
02094             link_ena = "ENABLED";
02095 
02096          if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
02097             patch_ena = "DISABLED";
02098          else
02099             patch_ena = "ENABLED";
02100 
02101          if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
02102             sch_ena = "DISABLED";
02103          else
02104             sch_ena = "ENABLED";
02105 
02106          if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
02107             user_funs = "DISABLED";
02108          else
02109             user_funs = "ENABLED";
02110 
02111          if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
02112             tail_type = "ALTERNATE";
02113          else
02114             tail_type = "STANDARD";
02115 
02116          if(!myrpt->totimer)
02117             tot_state = "TIMED OUT!";
02118          else if(myrpt->totimer != myrpt->p.totime)
02119             tot_state = "ARMED";
02120          else
02121             tot_state = "RESET";
02122 
02123          if(myrpt->tailid)
02124             ider_state = "QUEUED IN TAIL";
02125          else if(myrpt->mustid)
02126             ider_state = "QUEUED FOR CLEANUP";
02127          else
02128             ider_state = "CLEAN";
02129 
02130          switch(myrpt->callmode){
02131             case 1:
02132                patch_state = "DIALING";
02133                break;
02134             case 2:
02135                patch_state = "CONNECTING";
02136                break;
02137             case 3:
02138                patch_state = "UP";
02139                break;
02140 
02141             case 4:
02142                patch_state = "CALL FAILED";
02143                break;
02144 
02145             default:
02146                patch_state = "DOWN";
02147          }
02148 
02149          if(strlen(myrpt->exten)){
02150             called_number = ast_strdupa(myrpt->exten);
02151             if(!called_number)
02152                called_number = not_applicable;
02153          }
02154 
02155          if(strlen(myrpt->lastdtmfcommand)){
02156             lastdtmfcommand = ast_strdupa(myrpt->lastdtmfcommand);
02157             if(!lastdtmfcommand)
02158                lastdtmfcommand = not_applicable;
02159          }
02160 
02161          rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
02162 
02163          ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
02164          ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
02165          ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
02166          ast_cli(fd, "System...........................................: %s\n", sys_ena);
02167          ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
02168          ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
02169          ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
02170          ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
02171          ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
02172          ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
02173          ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
02174          ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
02175          ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
02176          ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
02177          ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
02178          ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
02179          ast_cli(fd, "Last DTMF command executed.......................: %s\n", lastdtmfcommand);
02180          hours = dailytxtime/3600000;
02181          dailytxtime %= 3600000;
02182          minutes = dailytxtime/60000;
02183          dailytxtime %= 60000;
02184          seconds = dailytxtime/1000;
02185          dailytxtime %= 1000;
02186 
02187          ast_cli(fd, "TX time today ...................................: %02d:%02d:%02d.%d\n",
02188             hours, minutes, seconds, dailytxtime);
02189 
02190          hours = (int) totaltxtime/3600000;
02191          totaltxtime %= 3600000;
02192          minutes = (int) totaltxtime/60000;
02193          totaltxtime %= 60000;
02194          seconds = (int)  totaltxtime/1000;
02195          totaltxtime %= 1000;
02196 
02197          ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
02198              hours, minutes, seconds, (int) totaltxtime);
02199          ast_cli(fd, "Nodes currently connected to us..................: ");
02200          for(j = 0 ;; j++){
02201             if(!listoflinks[j]){
02202                if(!j){
02203                   ast_cli(fd,"<NONE>");
02204                }
02205                break;
02206             }
02207             ast_cli(fd, "%s", listoflinks[j]);
02208             if(j % 4 == 3){
02209                ast_cli(fd, "\n");
02210                ast_cli(fd, "                                                 : ");
02211             }
02212             else{
02213                if(listoflinks[j + 1])
02214                   ast_cli(fd, ", ");
02215             }
02216          }
02217          ast_cli(fd,"\n");
02218 
02219          ast_cli(fd, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup);
02220          ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
02221          ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
02222          ast_cli(fd, "Autopatch called number..........................: %s\n", called_number);
02223          ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
02224          ast_cli(fd, "User linking commands............................: %s\n", link_ena);
02225          ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
02226               return RESULT_SUCCESS;
02227       }
02228    }
02229    return RESULT_FAILURE;
02230 }

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

Definition at line 10556 of file app_rpt.c.

References ast_log(), ast_safe_sleep(), ast_strlen_zero(), rpt_tele::chan, f, LOG_NOTICE, LOG_WARNING, rpt::name, name, rpt::p, rpt_vars, rpt::s, START_DELAY, rpt::sysstate_cur, and t.

Referenced by load_module().

10557 {
10558    int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
10559    int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
10560    int ismuted,dtmfed;
10561 #ifdef   OLD_ASTERISK
10562    struct localuser *u;
10563 #endif
10564    char tmp[256], keyed = 0,keyed1 = 0;
10565    char *options,*stringp,*tele,c;
10566    struct   rpt *myrpt;
10567    struct ast_frame *f,*f1,*f2;
10568    struct ast_channel *who;
10569    struct ast_channel *cs[20];
10570    struct   rpt_link *l;
10571    struct dahdi_confinfo ci;  /* conference info */
10572    struct dahdi_params par;
10573    int ms,elap,nullfd;
10574    time_t t,last_timeout_warning;
10575    struct   dahdi_radio_param z;
10576    struct rpt_tele *telem;
10577 
10578    nullfd = open("/dev/null",O_RDWR);
10579    if (ast_strlen_zero(data)) {
10580       ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
10581       return -1;
10582    }
10583 
10584    strncpy(tmp, (char *)data, sizeof(tmp)-1);
10585    time(&t);
10586    /* if time has externally shifted negative, screw it */
10587    if (t < starttime) t = starttime + START_DELAY;
10588    if ((!starttime) || (t < (starttime + START_DELAY)))
10589    {
10590       ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
10591       ast_safe_sleep(chan,3000);
10592       return -1;
10593    }
10594    stringp=tmp;
10595    strsep(&stringp, "|");
10596    options = stringp;
10597    myrpt = NULL;
10598    /* see if we can find our specified one */
10599    for(i = 0; i < nrpts; i++)
10600    {
10601       /* if name matches, assign it and exit loop */
10602       if (!strcmp(tmp,rpt_vars[i].name))
10603       {
10604          myrpt = &rpt_vars[i];
10605          break;
10606       }
10607    }
10608    if (myrpt == NULL)
10609    {
10610       ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
10611       return -1;
10612    }
10613    
10614    if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){ /* Do not allow incoming connections if disabled */
10615       ast_log(LOG_NOTICE, "Connect attempt to node %s  with tx disabled", myrpt->name);
10616       return -1;
10617    }
10618 
10619    /* if not phone access, must be an IAX connection */
10620    if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R')))
10621    {
10622       int val;
10623 
10624       phone_mode = 1;
10625       if (*options == 'D') phone_mode = 2;
10626       ast_set_callerid(chan,"0","app_rpt user","0");
10627       val = 1;
10628       ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
10629    }
10630    else
10631    {
10632 #ifdef ALLOW_LOCAL_CHANNELS
10633            /* Check to insure the connection is IAX2 or Local*/
10634            if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
10635                ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
10636                return -1;
10637            }
10638 #else
10639       if (strncmp(chan->name,"IAX2",4))
10640       {
10641          ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
10642          return -1;
10643       }
10644 #endif
10645    }
10646    if (options && (*options == 'R'))
10647    {
10648 
10649       /* Parts of this section taken from app_parkandannounce */
10650       char *return_context;
10651       int l, m, lot, timeout = 0;
10652       char tmp[256],*template;
10653       char *working, *context, *exten, *priority;
10654       char *s,*orig_s;
10655 
10656 
10657       rpt_mutex_lock(&myrpt->lock);
10658       m = myrpt->callmode;
10659       rpt_mutex_unlock(&myrpt->lock);
10660 
10661       if ((!myrpt->p.nobusyout) && m)
10662       {
10663          if (chan->_state != AST_STATE_UP)
10664          {
10665             ast_indicate(chan,AST_CONTROL_BUSY);
10666          }
10667          while(ast_safe_sleep(chan,10000) != -1);
10668          return -1;
10669       }
10670 
10671       if (chan->_state != AST_STATE_UP)
10672       {
10673          ast_answer(chan);
10674       }
10675 
10676       l=strlen(options)+2;
10677       orig_s=malloc(l);
10678       if(!orig_s) {
10679          ast_log(LOG_WARNING, "Out of memory\n");
10680          return -1;
10681       }
10682       s=orig_s;
10683       strncpy(s,options,l);
10684 
10685       template=strsep(&s,"|");
10686       if(!template) {
10687          ast_log(LOG_WARNING, "An announce template must be defined\n");
10688          free(orig_s);
10689          return -1;
10690       } 
10691   
10692       if(s) {
10693          timeout = atoi(strsep(&s, "|"));
10694          timeout *= 1000;
10695       }
10696    
10697       return_context = s;
10698   
10699       if(return_context != NULL) {
10700          /* set the return context. Code borrowed from the Goto builtin */
10701     
10702          working = return_context;
10703          context = strsep(&working, "|");
10704          exten = strsep(&working, "|");
10705          if(!exten) {
10706             /* Only a priority in this one */
10707             priority = context;
10708             exten = NULL;
10709             context = NULL;
10710          } else {
10711             priority = strsep(&working, "|");
10712             if(!priority) {
10713                /* Only an extension and priority in this one */
10714                priority = exten;
10715                exten = context;
10716                context = NULL;
10717          }
10718       }
10719       if(atoi(priority) < 0) {
10720          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
10721          free(orig_s);
10722          return -1;
10723       }
10724       /* At this point we have a priority and maybe an extension and a context */
10725       chan->priority = atoi(priority);
10726 #ifdef OLD_ASTERISK
10727       if(exten && strcasecmp(exten, "BYEXTENSION"))
10728 #else
10729       if(exten)
10730 #endif
10731          strncpy(chan->exten, exten, sizeof(chan->exten)-1);
10732       if(context)
10733          strncpy(chan->context, context, sizeof(chan->context)-1);
10734       } else {  /* increment the priority by default*/
10735          chan->priority++;
10736       }
10737 
10738       if(option_verbose > 2) {
10739          ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
10740          if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
10741             ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
10742          }
10743       }
10744   
10745       /* we are using masq_park here to protect * from touching the channel once we park it.  If the channel comes out of timeout
10746       before we are done announcing and the channel is messed with, Kablooeee.  So we use Masq to prevent this.  */
10747 
10748       ast_masq_park_call(chan, NULL, timeout, &lot);
10749 
10750       if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
10751 
10752       snprintf(tmp,sizeof(tmp) - 1,"%d,%s",lot,template + 1);
10753 
10754       rpt_telemetry(myrpt,REV_PATCH,tmp);
10755 
10756       free(orig_s);
10757 
10758       return 0;
10759 
10760    }
10761 
10762    if (!options)
10763    {
10764                 struct ast_hostent ahp;
10765                 struct hostent *hp;
10766       struct in_addr ia;
10767       char hisip[100],nodeip[100],*val, *s, *s1, *s2, *b,*b1;
10768 
10769       /* look at callerid to see what node this comes from */
10770       if (!chan->cid.cid_num) /* if doesn't have caller id */
10771       {
10772          ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
10773          return -1;
10774       }
10775 
10776       /* get his IP from IAX2 module */
10777       memset(hisip,0,sizeof(hisip));
10778 #ifdef ALLOW_LOCAL_CHANNELS
10779            /* set IP address if this is a local connection*/
10780            if (strncmp(chan->name,"Local",5)==0) {
10781                strcpy(hisip,"127.0.0.1");
10782            } else {
10783          pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
10784       }
10785 #else
10786       pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
10787 #endif
10788 
10789       if (!hisip[0])
10790       {
10791          ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
10792          return -1;
10793       }
10794       
10795       ast_callerid_parse(chan->cid.cid_num,&b,&b1);
10796       ast_shrink_phone_number(b1);
10797       if (!strcmp(myrpt->name,b1))
10798       {
10799          ast_log(LOG_WARNING, "Trying to link to self!!\n");
10800          return -1;
10801       }
10802 
10803       if (*b1 < '1')
10804       {
10805          ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
10806          return -1;
10807       }
10808 
10809 
10810       /* look for his reported node string */
10811       val = node_lookup(myrpt,b1);
10812       if (!val)
10813       {
10814          ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
10815          return -1;
10816       }
10817       strncpy(tmp,val,sizeof(tmp) - 1);
10818       s = tmp;
10819       s1 = strsep(&s,",");
10820       s2 = strsep(&s,",");
10821       if (!s2)
10822       {
10823          ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
10824          return -1;
10825       }
10826                 if (strcmp(s2,"NONE")) {
10827          hp = ast_gethostbyname(s2, &ahp);
10828          if (!hp)
10829          {
10830             ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
10831             return -1;
10832          }
10833          memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
10834 #ifdef   OLD_ASTERISK
10835          ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
10836 #else
10837          strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
10838 #endif
10839          if (strcmp(hisip,nodeip))
10840          {
10841             char *s3 = strchr(s1,'@');
10842             if (s3) s1 = s3 + 1;
10843             s3 = strchr(s1,'/');
10844             if (s3) *s3 = 0;
10845             hp = ast_gethostbyname(s1, &ahp);
10846             if (!hp)
10847             {
10848                ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
10849                return -1;
10850             }
10851             memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
10852 #ifdef   OLD_ASTERISK
10853             ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
10854 #else
10855             strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
10856 #endif
10857             if (strcmp(hisip,nodeip))
10858             {
10859                ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
10860                return -1;
10861             }
10862          }
10863       }
10864    }
10865 
10866    /* if is not a remote */
10867    if (!myrpt->remote)
10868    {
10869 
10870       char *b,*b1;
10871       int reconnects = 0;
10872 
10873       /* look at callerid to see what node this comes from */
10874       if (!chan->cid.cid_num) /* if doesn't have caller id */
10875       {
10876          ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
10877          return -1;
10878       }
10879 
10880       ast_callerid_parse(chan->cid.cid_num,&b,&b1);
10881       ast_shrink_phone_number(b1);
10882       if (!strcmp(myrpt->name,b1))
10883       {
10884          ast_log(LOG_WARNING, "Trying to link to self!!\n");
10885          return -1;
10886       }
10887       rpt_mutex_lock(&myrpt->lock);
10888       l = myrpt->links.next;
10889       /* try to find this one in queue */
10890       while(l != &myrpt->links)
10891       {
10892          if (l->name[0] == '0') 
10893          {
10894             l = l->next;
10895             continue;
10896          }
10897          /* if found matching string */
10898          if (!strcmp(l->name,b1)) break;
10899          l = l->next;
10900       }
10901       /* if found */
10902       if (l != &myrpt->links) 
10903       {
10904          l->killme = 1;
10905          l->retries = l->max_retries + 1;
10906          l->disced = 2;
10907          reconnects = l->reconnects;
10908          reconnects++;
10909                         rpt_mutex_unlock(&myrpt->lock);
10910          usleep(500000);   
10911       } else 
10912          rpt_mutex_unlock(&myrpt->lock);
10913       /* establish call in tranceive mode */
10914       l = malloc(sizeof(struct rpt_link));
10915       if (!l)
10916       {
10917          ast_log(LOG_WARNING, "Unable to malloc\n");
10918          pthread_exit(NULL);
10919       }
10920       /* zero the silly thing */
10921       memset((char *)l,0,sizeof(struct rpt_link));
10922       l->mode = 1;
10923       strncpy(l->name,b1,MAXNODESTR - 1);
10924       l->isremote = 0;
10925       l->chan = chan;
10926       l->connected = 1;
10927       l->thisconnected = 1;
10928       l->hasconnected = 1;
10929       l->reconnects = reconnects;
10930       l->phonemode = phone_mode;
10931       l->lastf1 = NULL;
10932       l->lastf2 = NULL;
10933       l->dtmfed = 0;
10934       ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
10935       ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
10936       /* allocate a pseudo-channel thru asterisk */
10937       l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
10938       if (!l->pchan)
10939       {
10940          fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
10941          pthread_exit(NULL);
10942       }
10943       ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
10944       ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
10945 #ifdef   AST_CDR_FLAG_POST_DISABLED
10946       ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
10947 #endif
10948       /* make a conference for the tx */
10949       ci.chan = 0;
10950       ci.confno = myrpt->conf;
10951       ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
10952       /* first put the channel on the conference in proper mode */
10953       if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
10954       {
10955          ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
10956          pthread_exit(NULL);
10957       }
10958       rpt_mutex_lock(&myrpt->lock);
10959       if (phone_mode > 1) l->lastrx = 1;
10960       l->max_retries = MAX_RETRIES;
10961       /* insert at end of queue */
10962       insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
10963       __kickshort(myrpt);
10964       rpt_mutex_unlock(&myrpt->lock);
10965       if (chan->_state != AST_STATE_UP) {
10966          ast_answer(chan);
10967       }
10968       if (myrpt->p.archivedir)
10969       {
10970          char str[100];
10971 
10972          if (l->phonemode)
10973             sprintf(str,"LINK(P),%s",l->name);
10974          else
10975             sprintf(str,"LINK,%s",l->name);
10976          donodelog(myrpt,str);
10977       }
10978       return AST_PBX_KEEPALIVE;
10979    }
10980    /* well, then it is a remote */
10981    rpt_mutex_lock(&myrpt->lock);
10982    /* if remote, error if anyone else already linked */
10983    if (myrpt->remoteon)
10984    {
10985       rpt_mutex_unlock(&myrpt->lock);
10986       usleep(500000);
10987       if (myrpt->remoteon)
10988       {
10989          ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
10990          return -1;
10991       }     
10992       rpt_mutex_lock(&myrpt->lock);
10993    }
10994 #ifdef HAVE_IOPERM
10995    if ((!strcmp(myrpt->remote, remote_rig_rbi)) &&
10996      (ioperm(myrpt->p.iobase,1,1) == -1))
10997    {
10998       rpt_mutex_unlock(&myrpt->lock);
10999       ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
11000       return -1;
11001    }
11002 #endif
11003    myrpt->remoteon = 1;
11004 #ifdef   OLD_ASTERISK
11005    LOCAL_USER_ADD(u);
11006 #endif
11007    rpt_mutex_unlock(&myrpt->lock);
11008    /* find our index, and load the vars initially */
11009    for(i = 0; i < nrpts; i++)
11010    {
11011       if (&rpt_vars[i] == myrpt)
11012       {
11013          load_rpt_vars(i,0);
11014          break;
11015       }
11016    }
11017    rpt_mutex_lock(&myrpt->lock);
11018    tele = strchr(myrpt->rxchanname,'/');
11019    if (!tele)
11020    {
11021       fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
11022       rpt_mutex_unlock(&myrpt->lock);
11023       pthread_exit(NULL);
11024    }
11025    *tele++ = 0;
11026    myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
11027    myrpt->zaprxchannel = NULL;
11028    if (!strcasecmp(myrpt->rxchanname,"Zap"))
11029       myrpt->zaprxchannel = myrpt->rxchannel;
11030    if (myrpt->rxchannel)
11031    {
11032       ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
11033       ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
11034 #ifdef   AST_CDR_FLAG_POST_DISABLED
11035       ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11036 #endif
11037       myrpt->rxchannel->whentohangup = 0;
11038       myrpt->rxchannel->appl = "Apprpt";
11039       myrpt->rxchannel->data = "(Link Rx)";
11040       if (option_verbose > 2)
11041          ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
11042             myrpt->rxchanname,tele,myrpt->rxchannel->name);
11043       rpt_mutex_unlock(&myrpt->lock);
11044       ast_call(myrpt->rxchannel,tele,999);
11045       rpt_mutex_lock(&myrpt->lock);
11046    }
11047    else
11048    {
11049       fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
11050       rpt_mutex_unlock(&myrpt->lock);
11051       pthread_exit(NULL);
11052    }
11053    *--tele = '/';
11054    myrpt->zaptxchannel = NULL;
11055    if (myrpt->txchanname)
11056    {
11057       tele = strchr(myrpt->txchanname,'/');
11058       if (!tele)
11059       {
11060          fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
11061          rpt_mutex_unlock(&myrpt->lock);
11062          ast_hangup(myrpt->rxchannel);
11063          pthread_exit(NULL);
11064       }
11065       *tele++ = 0;
11066       myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
11067       if (!strcasecmp(myrpt->txchanname,"Zap"))
11068          myrpt->zaptxchannel = myrpt->txchannel;
11069       if (myrpt->txchannel)
11070       {
11071          ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
11072          ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
11073 #ifdef   AST_CDR_FLAG_POST_DISABLED
11074          ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11075 #endif
11076          myrpt->txchannel->whentohangup = 0;
11077          myrpt->txchannel->appl = "Apprpt";
11078          myrpt->txchannel->data = "(Link Tx)";
11079          if (option_verbose > 2)
11080             ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
11081                myrpt->txchanname,tele,myrpt->txchannel->name);
11082          rpt_mutex_unlock(&myrpt->lock);
11083          ast_call(myrpt->txchannel,tele,999);
11084          rpt_mutex_lock(&myrpt->lock);
11085       }
11086       else
11087       {
11088          fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
11089          rpt_mutex_unlock(&myrpt->lock);
11090          ast_hangup(myrpt->rxchannel);
11091          pthread_exit(NULL);
11092       }
11093       *--tele = '/';
11094    }
11095    else
11096    {
11097       myrpt->txchannel = myrpt->rxchannel;
11098    }
11099    /* allocate a pseudo-channel thru asterisk */
11100    myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
11101    if (!myrpt->pchannel)
11102    {
11103       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
11104       rpt_mutex_unlock(&myrpt->lock);
11105       if (myrpt->txchannel != myrpt->rxchannel) 
11106          ast_hangup(myrpt->txchannel);
11107       ast_hangup(myrpt->rxchannel);
11108       pthread_exit(NULL);
11109    }
11110    ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
11111    ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
11112 #ifdef   AST_CDR_FLAG_POST_DISABLED
11113    ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
11114 #endif
11115    if (!myrpt->zaprxchannel) myrpt->zaprxchannel = myrpt->pchannel;
11116    if (!myrpt->zaptxchannel) myrpt->zaptxchannel = myrpt->pchannel;
11117    /* make a conference for the pseudo */
11118    ci.chan = 0;
11119    ci.confno = -1; /* make a new conf */
11120    ci.confmode = DAHDI_CONF_CONFANNMON ;
11121    /* first put the channel on the conference in announce/monitor mode */
11122    if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
11123    {
11124       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
11125       rpt_mutex_unlock(&myrpt->lock);
11126       ast_hangup(myrpt->pchannel);
11127       if (myrpt->txchannel != myrpt->rxchannel) 
11128          ast_hangup(myrpt->txchannel);
11129       ast_hangup(myrpt->rxchannel);
11130       pthread_exit(NULL);
11131    }
11132    /* save pseudo channel conference number */
11133    myrpt->conf = myrpt->txconf = ci.confno;
11134    /* if serial io port, open it */
11135    myrpt->iofd = -1;
11136    if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt->p.ioport)) == -1))
11137    {
11138       rpt_mutex_unlock(&myrpt->lock);
11139       ast_hangup(myrpt->pchannel);
11140       if (myrpt->txchannel != myrpt->rxchannel) 
11141          ast_hangup(myrpt->txchannel);
11142       ast_hangup(myrpt->rxchannel);
11143       pthread_exit(NULL);
11144    }
11145    iskenwood_pci4 = 0;
11146    memset(&z,0,sizeof(z));
11147    if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->zaptxchannel))
11148    {
11149       z.radpar = DAHDI_RADPAR_REMMODE;
11150       z.data = DAHDI_RADPAR_REM_NONE;
11151       res = ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
11152       /* if PCIRADIO and kenwood selected */
11153       if ((!res) && (!strcmp(myrpt->remote,remote_rig_kenwood)))
11154       {
11155          z.radpar = DAHDI_RADPAR_UIOMODE;
11156          z.data = 1;
11157          if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11158          {
11159             ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
11160             return -1;
11161          }
11162          z.radpar = DAHDI_RADPAR_UIODATA;
11163          z.data = 3;
11164          if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11165          {
11166             ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11167             return -1;
11168          }
11169          i = DAHDI_OFFHOOK;
11170          if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_HOOK,&i) == -1)
11171          {
11172             ast_log(LOG_ERROR,"Cannot set hook\n");
11173             return -1;
11174          }
11175          iskenwood_pci4 = 1;
11176       }
11177    }
11178    if (myrpt->txchannel == myrpt->zaptxchannel)
11179    {
11180       i = DAHDI_ONHOOK;
11181       ioctl(myrpt->zaptxchannel->fds[0],DAHDI_HOOK,&i);
11182       /* if PCIRADIO and Yaesu ft897/ICOM IC-706 selected */
11183       if ((myrpt->iofd < 1) && (!res) &&
11184          (!strcmp(myrpt->remote,remote_rig_ft897) ||
11185             (!strcmp(myrpt->remote,remote_rig_ic706))))
11186       {
11187          z.radpar = DAHDI_RADPAR_UIOMODE;
11188          z.data = 1;
11189          if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11190          {
11191             ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
11192             return -1;
11193          }
11194          z.radpar = DAHDI_RADPAR_UIODATA;
11195          z.data = 3;
11196          if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11197          {
11198             ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11199             return -1;
11200          }
11201       }
11202    }
11203    myrpt->remoterx = 0;
11204    myrpt->remotetx = 0;
11205    myrpt->retxtimer = 0;
11206    myrpt->rerxtimer = 0;
11207    myrpt->remoteon = 1;
11208    myrpt->dtmfidx = -1;
11209    myrpt->dtmfbuf[0] = 0;
11210    myrpt->dtmf_time_rem = 0;
11211    myrpt->hfscanmode = 0;
11212    myrpt->hfscanstatus = 0;
11213    if (myrpt->p.startupmacro)
11214    {
11215       snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
11216    }
11217    time(&myrpt->start_time);
11218    myrpt->last_activity_time = myrpt->start_time;
11219    last_timeout_warning = 0;
11220    myrpt->reload = 0;
11221    myrpt->tele.next = &myrpt->tele;
11222    myrpt->tele.prev = &myrpt->tele;
11223    rpt_mutex_unlock(&myrpt->lock);
11224    ast_set_write_format(chan, AST_FORMAT_SLINEAR);
11225    ast_set_read_format(chan, AST_FORMAT_SLINEAR);
11226    rem_rx = 0;
11227    remkeyed = 0;
11228    /* if we are on 2w loop and are a remote, turn EC on */
11229    if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
11230    {
11231       i = 128;
11232       ioctl(myrpt->zaprxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
11233    }
11234    if (chan->_state != AST_STATE_UP) {
11235       ast_answer(chan);
11236    }
11237 
11238    if (myrpt->rxchannel == myrpt->zaprxchannel)
11239    {
11240       if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
11241       {
11242          if (par.rxisoffhook)
11243          {
11244             ast_indicate(chan,AST_CONTROL_RADIO_KEY);
11245             myrpt->remoterx = 1;
11246             remkeyed = 1;
11247          }
11248       }
11249    }
11250    if (myrpt->p.archivedir)
11251    {
11252       char mycmd[100],mydate[100],*b,*b1;
11253       time_t myt;
11254       long blocksleft;
11255 
11256 
11257       mkdir(myrpt->p.archivedir,0600);
11258       sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
11259       mkdir(mycmd,0600);
11260       time(&myt);
11261       strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
11262          localtime(&myt));
11263       sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
11264          myrpt->p.archivedir,myrpt->name,mydate);
11265       if (myrpt->p.monminblocks)
11266       {
11267          blocksleft = diskavail(myrpt);
11268          if (myrpt->p.remotetimeout)
11269          {
11270             blocksleft -= (myrpt->p.remotetimeout *
11271                MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
11272          }
11273          if (blocksleft >= myrpt->p.monminblocks)
11274             ast_cli_command(nullfd,mycmd);
11275       } else ast_cli_command(nullfd,mycmd);
11276       /* look at callerid to see what node this comes from */
11277       if (!chan->cid.cid_num) /* if doesn't have caller id */
11278       {
11279          b1 = "0";
11280       } else {
11281          ast_callerid_parse(chan->cid.cid_num,&b,&b1);
11282          ast_shrink_phone_number(b1);
11283       }
11284       sprintf(mycmd,"CONNECT,%s",b1);
11285       donodelog(myrpt,mycmd);
11286    }
11287    myrpt->loginuser[0] = 0;
11288    myrpt->loginlevel[0] = 0;
11289    myrpt->authtelltimer = 0;
11290    myrpt->authtimer = 0;
11291    authtold = 0;
11292    authreq = 0;
11293    if (myrpt->p.authlevel > 1) authreq = 1;
11294    setrem(myrpt); 
11295    n = 0;
11296    dtmfed = 0;
11297    cs[n++] = chan;
11298    cs[n++] = myrpt->rxchannel;
11299    cs[n++] = myrpt->pchannel;
11300    if (myrpt->rxchannel != myrpt->txchannel)
11301       cs[n++] = myrpt->txchannel;
11302    /* start un-locked */
11303    for(;;) 
11304    {
11305       if (ast_check_hangup(chan)) break;
11306       if (ast_check_hangup(myrpt->rxchannel)) break;
11307       notremming = 0;
11308       setting = 0;
11309       reming = 0;
11310       telem = myrpt->tele.next;
11311       while(telem != &myrpt->tele)
11312       {
11313          if (telem->mode == SETREMOTE) setting = 1;
11314          if ((telem->mode == SETREMOTE) ||
11315              (telem->mode == SCAN) ||
11316             (telem->mode == TUNE))  reming = 1;
11317          else notremming = 1;
11318          telem = telem->next;
11319       }
11320       if (myrpt->reload)
11321       {
11322          myrpt->reload = 0;
11323          /* find our index, and load the vars */
11324          for(i = 0; i < nrpts; i++)
11325          {
11326             if (&rpt_vars[i] == myrpt)
11327             {
11328                load_rpt_vars(i,0);
11329                break;
11330             }
11331          }
11332       }
11333       time(&t);
11334       if (myrpt->p.remotetimeout)
11335       { 
11336          time_t r;
11337 
11338          r = (t - myrpt->start_time);
11339          if (r >= myrpt->p.remotetimeout)
11340          {
11341             sayfile(chan,"rpt/node");
11342             ast_say_character_str(chan,myrpt->name,NULL,chan->language);
11343             sayfile(chan,"rpt/timeout");
11344             ast_safe_sleep(chan,1000);
11345             break;
11346          }
11347          if ((myrpt->p.remotetimeoutwarning) && 
11348              (r >= (myrpt->p.remotetimeout -
11349             myrpt->p.remotetimeoutwarning)) &&
11350                 (r <= (myrpt->p.remotetimeout - 
11351                   myrpt->p.remotetimeoutwarningfreq)))
11352          {
11353             if (myrpt->p.remotetimeoutwarningfreq)
11354             {
11355                 if ((t - last_timeout_warning) >=
11356                myrpt->p.remotetimeoutwarningfreq)
11357                 {
11358                time(&last_timeout_warning);
11359                rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
11360                 }
11361             }
11362             else
11363             {
11364                 if (!last_timeout_warning)
11365                 {
11366                time(&last_timeout_warning);
11367                rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
11368                 }
11369             }
11370          }
11371       }
11372       if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
11373       { 
11374          time_t r;
11375 
11376          r = (t - myrpt->last_activity_time);
11377          if (r >= myrpt->p.remoteinacttimeout)
11378          {
11379             sayfile(chan,"rpt/node");
11380             ast_say_character_str(chan,myrpt->name,NULL,chan->language);
11381             sayfile(chan,"rpt/timeout");
11382             ast_safe_sleep(chan,1000);
11383             break;
11384          }
11385          if ((myrpt->p.remotetimeoutwarning) && 
11386              (r >= (myrpt->p.remoteinacttimeout -
11387             myrpt->p.remotetimeoutwarning)) &&
11388                 (r <= (myrpt->p.remoteinacttimeout - 
11389                   myrpt->p.remotetimeoutwarningfreq)))
11390          {
11391             if (myrpt->p.remotetimeoutwarningfreq)
11392             {
11393                 if ((t - last_timeout_warning) >=
11394                myrpt->p.remotetimeoutwarningfreq)
11395                 {
11396                time(&last_timeout_warning);
11397                rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
11398                 }
11399             }
11400             else
11401             {
11402                 if (!last_timeout_warning)
11403                 {
11404                time(&last_timeout_warning);
11405                rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
11406                 }
11407             }
11408          }
11409       }
11410       ms = MSWAIT;
11411       who = ast_waitfor_n(cs,n,&ms);
11412       if (who == NULL) ms = 0;
11413       elap = MSWAIT - ms;
11414       if (myrpt->macrotimer) myrpt->macrotimer -= elap;
11415       if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
11416       if (!ms) continue;
11417       /* do local dtmf timer */
11418       if (myrpt->dtmf_local_timer)
11419       {
11420          if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
11421          if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
11422       }
11423       rpt_mutex_lock(&myrpt->lock);
11424       do_dtmf_local(myrpt,0);
11425       rpt_mutex_unlock(&myrpt->lock);
11426       rem_totx =  myrpt->dtmf_local_timer && (!phone_mode);
11427       rem_totx |= keyed && (!myrpt->tunerequest);
11428       rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
11429       if(!strcmp(myrpt->remote, remote_rig_ic706))
11430          rem_totx |= myrpt->tunerequest;
11431       if (keyed && (!keyed1))
11432       {
11433          keyed1 = 1;
11434       }
11435 
11436       if (!keyed && (keyed1))
11437       {
11438          time_t myt;
11439 
11440          keyed1 = 0;
11441          time(&myt);
11442          /* if login necessary, and not too soon */
11443          if ((myrpt->p.authlevel) && 
11444              (!myrpt->loginlevel[0]) &&
11445             (myt > (t + 3)))
11446          {
11447             authreq = 1;
11448             authtold = 0;
11449             myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
11450          }
11451       }
11452 
11453 
11454       if (rem_rx && (!myrpt->remoterx))
11455       {
11456          myrpt->remoterx = 1;
11457          ast_indicate(chan,AST_CONTROL_RADIO_KEY);
11458       }
11459       if ((!rem_rx) && (myrpt->remoterx))
11460       {
11461          myrpt->remoterx = 0;
11462          ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
11463       }
11464       /* if auth requested, and not authed yet */
11465       if (authreq && (!myrpt->loginlevel[0]))
11466       {
11467          if ((!authtold) && ((myrpt->authtelltimer += elap)
11468              >= AUTHTELLTIME))
11469          {
11470             authtold = 1;
11471             rpt_telemetry(myrpt,LOGINREQ,NULL);
11472          }
11473          if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
11474          {
11475             break; /* if not logged in, hang up after a time */
11476          }
11477       }
11478 #ifndef  OLDKEY
11479       if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
11480       {
11481          myrpt->retxtimer = 0;
11482          if ((myrpt->remoterx) && (!myrpt->remotetx))
11483             ast_indicate(chan,AST_CONTROL_RADIO_KEY);
11484          else
11485             ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
11486       }
11487 
11488       if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
11489       {
11490          keyed = 0;
11491          myrpt->rerxtimer = 0;
11492       }
11493 #endif
11494       if (rem_totx && (!myrpt->remotetx))
11495       {
11496          /* if not authed, and needed, dont transmit */
11497          if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
11498          {
11499             myrpt->remotetx = 1;
11500             if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
11501             {
11502                time(&myrpt->last_activity_time);
11503                if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
11504                {
11505                   z.radpar = DAHDI_RADPAR_UIODATA;
11506                   z.data = 1;
11507                   if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11508                   {
11509                      ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11510                      return -1;
11511                   }
11512                }
11513                else
11514                {
11515                   ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
11516                }
11517                if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
11518             }
11519          }
11520       }
11521       if ((!rem_totx) && myrpt->remotetx) /* Remote base radio TX unkey */
11522       {
11523          myrpt->remotetx = 0;
11524          if(!myrpt->remtxfreqok){
11525             rpt_telemetry(myrpt,UNAUTHTX,NULL);
11526          }
11527          if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
11528          {
11529             z.radpar = DAHDI_RADPAR_UIODATA;
11530             z.data = 3;
11531             if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11532             {
11533                ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11534                return -1;
11535             }
11536          }
11537          else
11538          {
11539             ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
11540          }
11541          if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
11542       }
11543       if (myrpt->hfscanmode){
11544          myrpt->scantimer -= elap;
11545          if(myrpt->scantimer <= 0){
11546             if (!reming)
11547             {
11548                myrpt->scantimer = REM_SCANTIME;
11549                rpt_telemetry(myrpt,SCAN,0);
11550             } else myrpt->scantimer = 1;
11551          }
11552       }
11553       rpt_mutex_lock(&myrpt->lock);
11554       c = myrpt->macrobuf[0];
11555       if (c && (!myrpt->macrotimer))
11556       {
11557          myrpt->macrotimer = MACROTIME;
11558          memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
11559          if ((c == 'p') || (c == 'P'))
11560             myrpt->macrotimer = MACROPTIME;
11561          rpt_mutex_unlock(&myrpt->lock);
11562          if (myrpt->p.archivedir)
11563          {
11564             char str[100];
11565                sprintf(str,"DTMF(M),%c",c);
11566             donodelog(myrpt,str);
11567          }
11568          if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
11569          continue;
11570       } else rpt_mutex_unlock(&myrpt->lock);
11571       if (who == chan) /* if it was a read from incomming */
11572       {
11573          f = ast_read(chan);
11574          if (!f)
11575          {
11576             if (debug) printf("@@@@ link:Hung Up\n");
11577             break;
11578          }
11579          if (f->frametype == AST_FRAME_VOICE)
11580          {
11581             if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
11582             {
11583                ismuted = 0;
11584             }
11585             /* if not transmitting, zero-out audio */
11586             ismuted |= (!myrpt->remotetx);
11587             if (dtmfed && phone_mode) ismuted = 1;
11588             dtmfed = 0;
11589             if (ismuted)
11590             {
11591                memset(f->data,0,f->datalen);
11592                if (myrpt->lastf1)
11593                   memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11594                if (myrpt->lastf2)
11595                   memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11596             } 
11597             if (f) f2 = ast_frdup(f);
11598             else f2 = NULL;
11599             f1 = myrpt->lastf2;
11600             myrpt->lastf2 = myrpt->lastf1;
11601             myrpt->lastf1 = f2;
11602             if (ismuted)
11603             {
11604                if (myrpt->lastf1)
11605                   memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11606                if (myrpt->lastf2)
11607                   memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11608             }
11609             if (f1)
11610             {
11611                if (phone_mode)
11612                   ast_write(myrpt->txchannel,f1);
11613                else
11614                   ast_write(myrpt->txchannel,f);
11615                ast_frfree(f1);
11616             }
11617          }
11618 #ifndef  OLD_ASTERISK
11619          else if (f->frametype == AST_FRAME_DTMF_BEGIN)
11620          {
11621             if (myrpt->lastf1)
11622                memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11623             if (myrpt->lastf2)
11624                memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11625             dtmfed = 1;
11626          }
11627 #endif
11628          if (f->frametype == AST_FRAME_DTMF)
11629          {
11630             if (myrpt->lastf1)
11631                memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
11632             if (myrpt->lastf2)
11633                memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
11634             dtmfed = 1;
11635             if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1)
11636             {
11637                if (debug) printf("@@@@ rpt:Hung Up\n");
11638                ast_frfree(f);
11639                break;
11640             }
11641          }
11642          if (f->frametype == AST_FRAME_TEXT)
11643          {
11644             if (handle_remote_data(myrpt,f->data) == -1)
11645             {
11646                if (debug) printf("@@@@ rpt:Hung Up\n");
11647                ast_frfree(f);
11648                break;
11649             }
11650          }
11651          if (f->frametype == AST_FRAME_CONTROL)
11652          {
11653             if (f->subclass == AST_CONTROL_HANGUP)
11654             {
11655                if (debug) printf("@@@@ rpt:Hung Up\n");
11656                ast_frfree(f);
11657                break;
11658             }
11659             /* if RX key */
11660             if (f->subclass == AST_CONTROL_RADIO_KEY)
11661             {
11662                if (debug == 7) printf("@@@@ rx key\n");
11663                keyed = 1;
11664                myrpt->rerxtimer = 0;
11665             }
11666             /* if RX un-key */
11667             if (f->subclass == AST_CONTROL_RADIO_UNKEY)
11668             {
11669                myrpt->rerxtimer = 0;
11670                if (debug == 7) printf("@@@@ rx un-key\n");
11671                keyed = 0;
11672             }
11673          }
11674          ast_frfree(f);
11675          continue;
11676       }
11677       if (who == myrpt->rxchannel) /* if it was a read from radio */
11678       {
11679          f = ast_read(myrpt->rxchannel);
11680          if (!f)
11681          {
11682             if (debug) printf("@@@@ link:Hung Up\n");
11683             break;
11684          }
11685          if (f->frametype == AST_FRAME_VOICE)
11686          {
11687             int myreming = 0;
11688 
11689             if(!strcmp(myrpt->remote, remote_rig_kenwood))
11690                myreming = reming;
11691 
11692             if (myreming || (!remkeyed) ||
11693             ((myrpt->remote) && (myrpt->remotetx)) ||
11694               ((myrpt->remmode != REM_MODE_FM) &&
11695                 notremming))
11696                memset(f->data,0,f->datalen); 
11697              ast_write(myrpt->pchannel,f);
11698          }
11699          else if (f->frametype == AST_FRAME_CONTROL)
11700          {
11701             if (f->subclass == AST_CONTROL_HANGUP)
11702             {
11703                if (debug) printf("@@@@ rpt:Hung Up\n");
11704                ast_frfree(f);
11705                break;
11706             }
11707             /* if RX key */
11708             if (f->subclass == AST_CONTROL_RADIO_KEY)
11709             {
11710                if (debug == 7) printf("@@@@ remote rx key\n");
11711                if (!myrpt->remotetx)
11712                {
11713                   remkeyed = 1;
11714                }
11715             }
11716             /* if RX un-key */
11717             if (f->subclass == AST_CONTROL_RADIO_UNKEY)
11718             {
11719                if (debug == 7) printf("@@@@ remote rx un-key\n");
11720                if (!myrpt->remotetx) 
11721                {
11722                   remkeyed = 0;
11723                }
11724             }
11725          }
11726          ast_frfree(f);
11727          continue;
11728       }
11729       if (who == myrpt->pchannel) /* if is remote mix output */
11730       {
11731          f = ast_read(myrpt->pchannel);
11732          if (!f)
11733          {
11734             if (debug) printf("@@@@ link:Hung Up\n");
11735             break;
11736          }
11737          if (f->frametype == AST_FRAME_VOICE)
11738          {
11739             ast_write(chan,f);
11740          }
11741          if (f->frametype == AST_FRAME_CONTROL)
11742          {
11743             if (f->subclass == AST_CONTROL_HANGUP)
11744             {
11745                if (debug) printf("@@@@ rpt:Hung Up\n");
11746                ast_frfree(f);
11747                break;
11748             }
11749          }
11750          ast_frfree(f);
11751          continue;
11752       }
11753       if ((myrpt->rxchannel != myrpt->txchannel) && 
11754          (who == myrpt->txchannel)) /* do this cuz you have to */
11755       {
11756          f = ast_read(myrpt->txchannel);
11757          if (!f)
11758          {
11759             if (debug) printf("@@@@ link:Hung Up\n");
11760             break;
11761          }
11762          if (f->frametype == AST_FRAME_CONTROL)
11763          {
11764             if (f->subclass == AST_CONTROL_HANGUP)
11765             {
11766                if (debug) printf("@@@@ rpt:Hung Up\n");
11767                ast_frfree(f);
11768                break;
11769             }
11770          }
11771          ast_frfree(f);
11772          continue;
11773       }
11774    }
11775    if (myrpt->p.archivedir)
11776    {
11777       char mycmd[100],*b,*b1;
11778 
11779       /* look at callerid to see what node this comes from */
11780       if (!chan->cid.cid_num) /* if doesn't have caller id */
11781       {
11782          b1 = "0";
11783       } else {
11784          ast_callerid_parse(chan->cid.cid_num,&b,&b1);
11785          ast_shrink_phone_number(b1);
11786       }
11787       sprintf(mycmd,"DISCONNECT,%s",b1);
11788       donodelog(myrpt,mycmd);
11789    }
11790    /* wait for telem to be done */
11791    while(myrpt->tele.next != &myrpt->tele) usleep(100000);
11792    sprintf(tmp,"mixmonitor stop %s",chan->name);
11793    ast_cli_command(nullfd,tmp);
11794    close(nullfd);
11795    rpt_mutex_lock(&myrpt->lock);
11796    myrpt->hfscanmode = 0;
11797    myrpt->hfscanstatus = 0;
11798    myrpt->remoteon = 0;
11799    rpt_mutex_unlock(&myrpt->lock);
11800    if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
11801    myrpt->lastf1 = NULL;
11802    if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
11803    myrpt->lastf2 = NULL;
11804    if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
11805    {
11806       z.radpar = DAHDI_RADPAR_UIOMODE;
11807       z.data = 3;
11808       if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11809       {
11810          ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
11811          return -1;
11812       }
11813       z.radpar = DAHDI_RADPAR_UIODATA;
11814       z.data = 3;
11815       if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
11816       {
11817          ast_log(LOG_ERROR,"Cannot set UIODATA\n");
11818          return -1;
11819       }
11820       i = DAHDI_OFFHOOK;
11821       if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_HOOK,&i) == -1)
11822       {
11823          ast_log(LOG_ERROR,"Cannot set hook\n");
11824          return -1;
11825       }
11826    }
11827    if (myrpt->iofd) close(myrpt->iofd);
11828    myrpt->iofd = -1;
11829    ast_hangup(myrpt->pchannel);
11830    if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
11831    ast_hangup(myrpt->rxchannel);
11832    closerem(myrpt);
11833 #ifdef   OLD_ASTERISK
11834    LOCAL_USER_REMOVE(u);
11835 #endif
11836    return res;
11837 }

static void rpt_localtime ( time_t *  t,
struct tm *  lt 
) [static]

Definition at line 1582 of file app_rpt.c.

References ast_localtime(), and localtime_r.

Referenced by do_scheduler(), and rpt_tele_thread().

01583 {
01584 #ifdef OLD_ASTERISK
01585    localtime_r(t, lt);
01586 #else
01587    ast_localtime(t, lt, NULL);
01588 #endif
01589 }

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

Definition at line 10389 of file app_rpt.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, ast_pthread_create, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_test_flag, ast_variable_retrieve(), rpt::cfg, free, rpt::ident, rpt::lastthreadrestarttime, load_rpt_vars(), lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, name, rpt::name, rpt_tele::next, nodeloglock, rpt::offset, rpt::powerlevel, rpt_tele::prev, REM_MEDPWR, REM_MODE_FM, REM_SIMPLEX, rpt::remmode, rpt::remote, retreive_memory(), rpt::rpt_thread, rpt_vars, rpt::rxchanname, strdup, rpt::tailmessagen, rpt::tele, rpt::threadrestarts, and rpt::txchanname.

Referenced by load_module().

10390 {
10391 int   i,n;
10392 pthread_attr_t attr;
10393 struct ast_config *cfg;
10394 char *this,*val;
10395 
10396    /* init nodelog queue */
10397    nodelog.next = nodelog.prev = &nodelog;
10398    /* go thru all the specified repeaters */
10399    this = NULL;
10400    n = 0;
10401    /* wait until asterisk starts */
10402         while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
10403                 usleep(250000);
10404    rpt_vars[n].cfg = ast_config_load("rpt.conf");
10405    cfg = rpt_vars[n].cfg;
10406    if (!cfg) {
10407       ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf.  Radio Repeater disabled.\n");
10408       pthread_exit(NULL);
10409    }
10410    while((this = ast_category_browse(cfg,this)) != NULL)
10411    {
10412       for(i = 0 ; i < strlen(this) ; i++){
10413          if((this[i] < '0') || (this[i] > '9'))
10414             break;
10415       }
10416       if(i != strlen(this)) continue; /* Not a node defn */
10417       memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
10418       rpt_vars[n].name = strdup(this);
10419       val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
10420       if (val) rpt_vars[n].rxchanname = strdup(val);
10421       val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
10422       if (val) rpt_vars[n].txchanname = strdup(val);
10423       val = (char *) ast_variable_retrieve(cfg,this,"remote");
10424       if (val) rpt_vars[n].remote = strdup(val);
10425       ast_mutex_init(&rpt_vars[n].lock);
10426       ast_mutex_init(&rpt_vars[n].remlock);
10427       rpt_vars[n].tele.next = &rpt_vars[n].tele;
10428       rpt_vars[n].tele.prev = &rpt_vars[n].tele;
10429       rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
10430       rpt_vars[n].tailmessagen = 0;
10431 #ifdef   _MDC_DECODE_H_
10432       rpt_vars[n].mdc = mdc_decoder_new(8000);
10433 #endif
10434       n++;
10435    }
10436    nrpts = n;
10437    ast_config_destroy(cfg);
10438 
10439    /* start em all */
10440    for(i = 0; i < n; i++)
10441    {
10442       load_rpt_vars(i,1);
10443 
10444       /* if is a remote, dont start one for it */
10445       if (rpt_vars[i].remote)
10446       {
10447          if(retreive_memory(&rpt_vars[i],"init")){ /* Try to retreive initial memory channel */
10448             strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
10449             strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
10450 
10451             strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
10452             rpt_vars[i].remmode = REM_MODE_FM;
10453             rpt_vars[i].offset = REM_SIMPLEX;
10454             rpt_vars[i].powerlevel = REM_MEDPWR;
10455          }
10456          continue;
10457       }
10458       if (!rpt_vars[i].p.ident)
10459       {
10460          ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
10461          ast_config_destroy(cfg);
10462          pthread_exit(NULL);
10463       }
10464            pthread_attr_init(&attr);
10465            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10466       ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
10467    }
10468    usleep(500000);
10469    time(&starttime);
10470    for(;;)
10471    {
10472       /* Now monitor each thread, and restart it if necessary */
10473       for(i = 0; i < n; i++)
10474       { 
10475          int rv;
10476          if (rpt_vars[i].remote) continue;
10477          if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP) 
10478             rv = -1;
10479          else
10480             rv = pthread_kill(rpt_vars[i].rpt_thread,0);
10481          if (rv)
10482          {
10483             if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
10484             {
10485                if(rpt_vars[i].threadrestarts >= 5)
10486                {
10487                   ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
10488                   exit(1); /* Stuck in a restart loop, kill Asterisk and start over */
10489                }
10490                else
10491                {
10492                   ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
10493                   rpt_vars[i].threadrestarts++;
10494                }
10495             }
10496             else
10497                rpt_vars[i].threadrestarts = 0;
10498 
10499             rpt_vars[i].lastthreadrestarttime = time(NULL);
10500                  pthread_attr_init(&attr);
10501                  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10502             ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
10503             ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
10504          }
10505 
10506       }
10507       for(;;)
10508       {
10509          struct nodelog *nodep;
10510          char *space,datestr[100],fname[300];
10511          int fd;
10512 
10513          ast_mutex_lock(&nodeloglock);
10514          nodep = nodelog.next;
10515          if(nodep == &nodelog) /* if nothing in queue */
10516          {
10517             ast_mutex_unlock(&nodeloglock);
10518             break;
10519          }
10520          remque((struct qelem *)nodep);
10521          ast_mutex_unlock(&nodeloglock);
10522          space = strchr(nodep->str,' ');
10523          if (!space) 
10524          {
10525             free(nodep);
10526             continue;
10527          }
10528          *space = 0;
10529          strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
10530             localtime(&nodep->timestamp));
10531          sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
10532             nodep->str,datestr);
10533          fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
10534          if (fd == -1)
10535          {
10536             ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
10537             free(nodep);
10538             continue;
10539          }
10540          if (write(fd,space + 1,strlen(space + 1)) !=
10541             strlen(space + 1))
10542          {
10543             ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
10544             free(nodep);
10545             continue;
10546          }
10547          close(fd);
10548          free(nodep);
10549       }
10550       sleep(2);
10551    }
10552    ast_config_destroy(cfg);
10553    pthread_exit(NULL);
10554 }

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

Definition at line 2904 of file app_rpt.c.

References __mklinklist(), ACT_TIMEOUT_WARNING, ARB_ALPHA, AST_CDR_FLAG_POST_DISABLED, AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_safe_sleep(), ast_say_character_str(), ast_say_digits(), ast_say_number(), ast_say_time, ast_set_flag, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_tonepair_start(), ast_variable_retrieve(), ast_waitstream(), ast_channel::cdr, rpt_tele::chan, COMPLETE, CONNECTED, CONNFAIL, DLY_CALLTERM, DLY_COMP, DLY_ID, DLY_LINKUNKEY, DLY_TELEM, DLY_UNKEY, ast_channel::fds, finddelim(), free, FULLSTATUS, get_wait_interval(), rpt_link::hasconnected, ID, ID1, IDTALKOVER, INVFREQ, rpt_link::isremote, ast_channel::language, LASTNODEKEY, LINKUNKEY, rpt_link::linkunkeytocttimer, LOG_ERROR, LOG_NOTICE, LOG_WARNING, LOGINREQ, MACRO_BUSY, MACRO_NOTFOUND, malloc, MAXLINKLIST, MAXREMSTR, MEMNOTFOUND, rpt_link::mode, rpt_tele::mode, multimode_capable(), mycompar(), rpt_tele::mylink, rpt_link::name, ast_channel::name, rpt_link::next, rpt_tele::next, rpt_tele::param, play_tone(), rpt_link::prev, PROC, REM_HIPWR, REM_LOWPWR, REM_MEDPWR, REM_MINUS, REM_MODE_AM, REM_MODE_FM, REM_MODE_LSB, REM_MODE_USB, REM_PLUS, REM_SIMPLEX, REMALREADY, REMDISC, REMGO, REMLOGIN, REMLONGSTATUS, REMMODE, REMNOTFOUND, REMSHORTSTATUS, REMXXX, REV_PATCH, rpt_tele::rpt, rpt_localtime(), rpt_mutex_lock, rpt_mutex_unlock, s, saycharstr(), sayfile(), saynum(), SCAN, SCANSTAT, service_scan(), set_ft897(), set_ic706(), set_mode_ft897(), set_mode_ic706(), setkenwood(), setrbi(), SETREMOTE, simple_command_ft897(), split_freq(), STATS_TIME, STATS_VERSION, STATUS, rpt_tele::submode, t, TAILMSG, telem_any(), telem_lookup(), TERM, TEST_TONE, rpt_link::thisconnected, TIMEOUT, TIMEOUT_WARNING, TUNE, UNAUTHTX, UNKEY, and wait_interval().

Referenced by rpt_telemetry().

02905 {
02906 struct dahdi_confinfo ci;  /* conference info */
02907 int   res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
02908 struct   rpt_tele *mytele = (struct rpt_tele *)this;
02909 struct  rpt_tele *tlist;
02910 struct   rpt *myrpt;
02911 struct   rpt_link *l,*l1,linkbase;
02912 struct   ast_channel *mychannel;
02913 int vmajor, vminor, m;
02914 char *p,*ct,*ct_copy,*ident, *nodename,*cp;
02915 time_t t;
02916 struct tm localtm;
02917 char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
02918 int   i,ns,rbimode;
02919 char mhz[MAXREMSTR];
02920 char decimals[MAXREMSTR];
02921 struct dahdi_params par;
02922 
02923 
02924    /* get a pointer to myrpt */
02925    myrpt = mytele->rpt;
02926 
02927    /* Snag copies of a few key myrpt variables */
02928    rpt_mutex_lock(&myrpt->lock);
02929    nodename = ast_strdupa(myrpt->name);
02930    if (myrpt->p.ident) ident = ast_strdupa(myrpt->p.ident);
02931    else ident = "";
02932    rpt_mutex_unlock(&myrpt->lock);
02933    
02934    /* allocate a pseudo-channel thru asterisk */
02935    mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
02936    if (!mychannel)
02937    {
02938       fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
02939       rpt_mutex_lock(&myrpt->lock);
02940       remque((struct qelem *)mytele);
02941       ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
02942       rpt_mutex_unlock(&myrpt->lock);
02943       free(mytele);     
02944       pthread_exit(NULL);
02945    }
02946 #ifdef   AST_CDR_FLAG_POST_DISABLED
02947    ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
02948 #endif
02949    rpt_mutex_lock(&myrpt->lock);
02950    mytele->chan = mychannel;
02951    rpt_mutex_unlock(&myrpt->lock);
02952    /* make a conference for the tx */
02953    ci.chan = 0;
02954    /* If there's an ID queued, or tail message queued, */
02955    /* only connect the ID audio to the local tx conference so */
02956    /* linked systems can't hear it */
02957    ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) || 
02958       (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY)) || (mytele->mode == TIMEOUT) ?
02959          myrpt->txconf : myrpt->conf);
02960    ci.confmode = DAHDI_CONF_CONFANN;
02961    /* first put the channel on the conference in announce mode */
02962    if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
02963    {
02964       ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
02965       rpt_mutex_lock(&myrpt->lock);
02966       remque((struct qelem *)mytele);
02967       rpt_mutex_unlock(&myrpt->lock);
02968       ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
02969       free(mytele);     
02970       ast_hangup(mychannel);
02971       pthread_exit(NULL);
02972    }
02973    ast_stopstream(mychannel);
02974    switch(mytele->mode)
02975    {
02976        case ID:
02977        case ID1:
02978       /* wait a bit */
02979       wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
02980       res = telem_any(myrpt,mychannel, ident); 
02981       imdone=1;   
02982       break;
02983       
02984        case TAILMSG:
02985       res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language); 
02986       break;
02987       
02988        case IDTALKOVER:
02989          p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
02990          if(p)
02991          res = telem_any(myrpt,mychannel, p); 
02992       imdone=1;   
02993          break;
02994             
02995        case PROC:
02996       /* wait a little bit longer */
02997       wait_interval(myrpt, DLY_TELEM, mychannel);
02998       res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
02999       if(res < 0){ /* Then default message */
03000          res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
03001       }
03002       break;
03003        case TERM:
03004       /* wait a little bit longer */
03005       wait_interval(myrpt, DLY_CALLTERM, mychannel);
03006       res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
03007       if(res < 0){ /* Then default message */
03008          res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
03009       }
03010       break;
03011        case COMPLETE:
03012       /* wait a little bit */
03013       wait_interval(myrpt, DLY_TELEM, mychannel);
03014       res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03015       break;
03016        case MACRO_NOTFOUND:
03017       /* wait a little bit */
03018       wait_interval(myrpt, DLY_TELEM, mychannel);
03019       res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
03020       break;
03021        case MACRO_BUSY:
03022       /* wait a little bit */
03023       wait_interval(myrpt, DLY_TELEM, mychannel);
03024       res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
03025       break;
03026        case UNKEY:
03027       if(myrpt->patchnoct && myrpt->callmode){ /* If no CT during patch configured, then don't send one */
03028          imdone = 1;
03029          break;
03030       }
03031          
03032       /*
03033       * Reset the Unkey to CT timer
03034       */
03035 
03036       x = get_wait_interval(myrpt, DLY_UNKEY);
03037       rpt_mutex_lock(&myrpt->lock);
03038       myrpt->unkeytocttimer = x; /* Must be protected as it is changed below */
03039       rpt_mutex_unlock(&myrpt->lock);
03040 
03041       /*
03042       * If there's one already queued, don't do another
03043       */
03044 
03045       tlist = myrpt->tele.next;
03046       unkeys_queued = 0;
03047                 if (tlist != &myrpt->tele)
03048                 {
03049                         rpt_mutex_lock(&myrpt->lock);
03050                         while(tlist != &myrpt->tele){
03051                                 if (tlist->mode == UNKEY) unkeys_queued++;
03052                                 tlist = tlist->next;
03053                         }
03054                         rpt_mutex_unlock(&myrpt->lock);
03055       }
03056       if( unkeys_queued > 1){
03057          imdone = 1;
03058          break;
03059       }
03060 
03061       /* Wait for the telemetry timer to expire */
03062       /* Periodically check the timer since it can be re-initialized above */
03063       while(myrpt->unkeytocttimer)
03064       {
03065          int ctint;
03066          if(myrpt->unkeytocttimer > 100)
03067             ctint = 100;
03068          else
03069             ctint = myrpt->unkeytocttimer;
03070          ast_safe_sleep(mychannel, ctint);
03071          rpt_mutex_lock(&myrpt->lock);
03072          if(myrpt->unkeytocttimer < ctint)
03073             myrpt->unkeytocttimer = 0;
03074          else
03075             myrpt->unkeytocttimer -= ctint;
03076          rpt_mutex_unlock(&myrpt->lock);
03077       }
03078    
03079       /*
03080       * Now, the carrier on the rptr rx should be gone. 
03081       * If it re-appeared, then forget about sending the CT
03082       */
03083       if(myrpt->keyed){
03084          imdone = 1;
03085          break;
03086       }
03087       
03088       rpt_mutex_lock(&myrpt->lock); /* Update the kerchunk counters */
03089       myrpt->dailykerchunks++;
03090       myrpt->totalkerchunks++;
03091       rpt_mutex_unlock(&myrpt->lock);
03092    
03093       haslink = 0;
03094       hastx = 0;
03095       hasremote = 0;    
03096       l = myrpt->links.next;
03097       if (l != &myrpt->links)
03098       {
03099          rpt_mutex_lock(&myrpt->lock);
03100          while(l != &myrpt->links)
03101          {
03102             if (l->name[0] == '0')
03103             {
03104                l = l->next;
03105                continue;
03106             }
03107             haslink = 1;
03108             if (l->mode) {
03109                hastx++;
03110                if (l->isremote) hasremote++;
03111             }
03112             l = l->next;
03113          }
03114          rpt_mutex_unlock(&myrpt->lock);
03115       }
03116       if (haslink)
03117       {
03118 
03119          res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
03120          if(res)
03121             ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
03122          
03123       
03124          /* if in remote cmd mode, indicate it */
03125          if (myrpt->cmdnode[0])
03126          {
03127             ast_safe_sleep(mychannel,200);
03128             res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
03129             if(res)
03130                ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
03131             ast_stopstream(mychannel);
03132          }
03133       }
03134       else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */
03135          ct_copy = ast_strdupa(ct);
03136          res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
03137          if(res)
03138             ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);     
03139       }  
03140       if (hasremote && (!myrpt->cmdnode[0]))
03141       {
03142          /* set for all to hear */
03143          ci.chan = 0;
03144          ci.confno = myrpt->conf;
03145          ci.confmode = DAHDI_CONF_CONFANN;
03146          /* first put the channel on the conference in announce mode */
03147          if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
03148          {
03149             ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
03150             rpt_mutex_lock(&myrpt->lock);
03151             remque((struct qelem *)mytele);
03152             rpt_mutex_unlock(&myrpt->lock);
03153             ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
03154             free(mytele);     
03155             ast_hangup(mychannel);
03156             pthread_exit(NULL);
03157          }
03158          if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){ /* Unlinked Courtesy Tone */
03159             ast_safe_sleep(mychannel,200);
03160             ct_copy = ast_strdupa(ct);
03161             res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
03162             if(res)
03163                ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);     
03164          }  
03165       }
03166 #if   defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
03167       if (myrpt->lastunit)
03168       {
03169          char mystr[10];
03170 
03171          ast_safe_sleep(mychannel,200);
03172          /* set for all to hear */
03173          ci.chan = 0;
03174          ci.confno = myrpt->txconf;
03175          ci.confmode = DAHDI_CONF_CONFANN;
03176          /* first put the channel on the conference in announce mode */
03177          if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
03178          {
03179             ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
03180             rpt_mutex_lock(&myrpt->lock);
03181             remque((struct qelem *)mytele);
03182             rpt_mutex_unlock(&myrpt->lock);
03183             ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
03184             free(mytele);     
03185             ast_hangup(mychannel);
03186             pthread_exit(NULL);
03187          }
03188          sprintf(mystr,"%04x",myrpt->lastunit);
03189          myrpt->lastunit = 0;
03190          ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
03191          break;
03192       }
03193 #endif
03194       imdone = 1;
03195       break;
03196        case LINKUNKEY:
03197       if(myrpt->patchnoct && myrpt->callmode){ /* If no CT during patch configured, then don't send one */
03198          imdone = 1;
03199          break;
03200       }
03201          
03202       /*
03203       * Reset the Unkey to CT timer
03204       */
03205 
03206       x = get_wait_interval(myrpt, DLY_LINKUNKEY);
03207       mytele->mylink.linkunkeytocttimer = x; /* Must be protected as it is changed below */
03208 
03209       /*
03210       * If there's one already queued, don't do another
03211       */
03212 
03213       tlist = myrpt->tele.next;
03214       unkeys_queued = 0;
03215                 if (tlist != &myrpt->tele)
03216                 {
03217                         rpt_mutex_lock(&myrpt->lock);
03218                         while(tlist != &myrpt->tele){
03219                                 if (tlist->mode == LINKUNKEY) unkeys_queued++;
03220                                 tlist = tlist->next;
03221                         }
03222                         rpt_mutex_unlock(&myrpt->lock);
03223       }
03224       if( unkeys_queued > 1){
03225          imdone = 1;
03226          break;
03227       }
03228 
03229       /* Wait for the telemetry timer to expire */
03230       /* Periodically check the timer since it can be re-initialized above */
03231       while(mytele->mylink.linkunkeytocttimer)
03232       {
03233          int ctint;
03234          if(mytele->mylink.linkunkeytocttimer > 100)
03235             ctint = 100;
03236          else
03237             ctint = mytele->mylink.linkunkeytocttimer;
03238          ast_safe_sleep(mychannel, ctint);
03239          rpt_mutex_lock(&myrpt->lock);
03240          if(mytele->mylink.linkunkeytocttimer < ctint)
03241             mytele->mylink.linkunkeytocttimer = 0;
03242          else
03243             mytele->mylink.linkunkeytocttimer -= ctint;
03244          rpt_mutex_unlock(&myrpt->lock);
03245       }
03246    
03247       if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){ /* Unlinked Courtesy Tone */
03248          ct_copy = ast_strdupa(ct);
03249          res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
03250          if(res)
03251             ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);     
03252       }  
03253       imdone = 1;
03254       break;
03255        case REMDISC:
03256       /* wait a little bit */
03257       wait_interval(myrpt, DLY_TELEM, mychannel);
03258       l = myrpt->links.next;
03259       haslink = 0;
03260       /* dont report if a link for this one still on system */
03261       if (l != &myrpt->links)
03262       {
03263          rpt_mutex_lock(&myrpt->lock);
03264          while(l != &myrpt->links)
03265          {
03266             if (l->name[0] == '0')
03267             {
03268                l = l->next;
03269                continue;
03270             }
03271             if (!strcmp(l->name,mytele->mylink.name))
03272             {
03273                haslink = 1;
03274                break;
03275             }
03276             l = l->next;
03277          }
03278          rpt_mutex_unlock(&myrpt->lock);
03279       }
03280       if (haslink)
03281       {
03282          imdone = 1;
03283          break;
03284       }
03285       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03286       if (!res) 
03287          res = ast_waitstream(mychannel, "");
03288       else
03289           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03290       ast_stopstream(mychannel);
03291       ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
03292       res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ? 
03293          "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
03294       break;
03295        case REMALREADY:
03296       /* wait a little bit */
03297       wait_interval(myrpt, DLY_TELEM, mychannel);
03298       res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
03299       break;
03300        case REMNOTFOUND:
03301       /* wait a little bit */
03302       wait_interval(myrpt, DLY_TELEM, mychannel);
03303       res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
03304       break;
03305        case REMGO:
03306       /* wait a little bit */
03307       wait_interval(myrpt, DLY_TELEM, mychannel);
03308       res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
03309       break;
03310        case CONNECTED:
03311       /* wait a little bit */
03312       wait_interval(myrpt, DLY_TELEM,  mychannel);
03313       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03314       if (!res) 
03315          res = ast_waitstream(mychannel, "");
03316       else
03317           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03318       ast_stopstream(mychannel);
03319       ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
03320       res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
03321       if (!res) 
03322          res = ast_waitstream(mychannel, "");
03323       else
03324           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03325       ast_stopstream(mychannel);
03326       res = ast_streamfile(mychannel, "digits/2", mychannel->language);
03327       if (!res) 
03328          res = ast_waitstream(mychannel, "");
03329       else
03330           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03331       ast_stopstream(mychannel);
03332       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03333       if (!res) 
03334          res = ast_waitstream(mychannel, "");
03335       else
03336           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03337       ast_stopstream(mychannel);
03338       ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03339       imdone = 1;
03340       break;
03341        case CONNFAIL:
03342       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03343       if (!res) 
03344          res = ast_waitstream(mychannel, "");
03345       else
03346           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03347       ast_stopstream(mychannel);
03348       ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
03349       res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
03350       break;
03351        case MEMNOTFOUND:
03352       /* wait a little bit */
03353       wait_interval(myrpt, DLY_TELEM, mychannel);
03354       res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
03355       break;
03356        case SETREMOTE:
03357       ast_mutex_lock(&myrpt->remlock);
03358       res = 0;
03359       if(!strcmp(myrpt->remote, remote_rig_ft897))
03360       {
03361          res = set_ft897(myrpt);
03362       }
03363       if(!strcmp(myrpt->remote, remote_rig_ic706))
03364       {
03365          res = set_ic706(myrpt);
03366       }
03367 #ifdef HAVE_IOPERM
03368       else if(!strcmp(myrpt->remote, remote_rig_rbi))
03369       {
03370          if (ioperm(myrpt->p.iobase,1,1) == -1)
03371          {
03372             rpt_mutex_unlock(&myrpt->lock);
03373             ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
03374             res = -1;
03375          }
03376          else res = setrbi(myrpt);
03377       }
03378 #endif
03379       else if(!strcmp(myrpt->remote, remote_rig_kenwood))
03380       {
03381          res = setkenwood(myrpt);
03382          if (ast_safe_sleep(mychannel,200) == -1)
03383          {
03384             ast_mutex_unlock(&myrpt->remlock);
03385             res = -1;
03386             break;
03387          }
03388          i = DAHDI_FLUSH_EVENT;
03389          if (ioctl(myrpt->zaptxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
03390          {
03391             ast_mutex_unlock(&myrpt->remlock);
03392             ast_log(LOG_ERROR,"Cant flush events");
03393             res = -1;
03394             break;
03395          }
03396          if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
03397          {
03398             ast_mutex_unlock(&myrpt->remlock);
03399             ast_log(LOG_ERROR,"Cant get params");
03400             res = -1;
03401             break;
03402          }
03403          myrpt->remoterx = 
03404             (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
03405       }
03406       ast_mutex_unlock(&myrpt->remlock);
03407       if (!res)
03408       {
03409          imdone = 1;
03410          break;
03411       }
03412       /* fall thru to invalid freq */
03413        case INVFREQ:
03414       /* wait a little bit */
03415       wait_interval(myrpt, DLY_TELEM, mychannel);
03416       res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
03417       break;
03418        case REMMODE:
03419       cp = 0;
03420       wait_interval(myrpt, DLY_TELEM, mychannel);
03421       switch(myrpt->remmode)
03422       {
03423           case REM_MODE_FM:
03424          saycharstr(mychannel,"FM");
03425          break;
03426           case REM_MODE_USB:
03427          saycharstr(mychannel,"USB");
03428          break;
03429           case REM_MODE_LSB:
03430          saycharstr(mychannel,"LSB");
03431          break;
03432           case REM_MODE_AM:
03433          saycharstr(mychannel,"AM");
03434          break;
03435       }
03436       wait_interval(myrpt, DLY_COMP, mychannel);
03437       if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03438       break;
03439        case LOGINREQ:
03440       wait_interval(myrpt, DLY_TELEM, mychannel);
03441       sayfile(mychannel,"rpt/login");
03442       saycharstr(mychannel,myrpt->name);
03443       break;
03444        case REMLOGIN:
03445       wait_interval(myrpt, DLY_TELEM, mychannel);
03446       saycharstr(mychannel,myrpt->loginuser);
03447       sayfile(mychannel,"rpt/node");
03448       saycharstr(mychannel,myrpt->name);
03449       wait_interval(myrpt, DLY_COMP, mychannel);
03450       if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03451       break;
03452        case REMXXX:
03453       wait_interval(myrpt, DLY_TELEM, mychannel);
03454       res = 0;
03455       switch(mytele->submode)
03456       {
03457           case 100: /* RX PL Off */
03458          sayfile(mychannel, "rpt/rxpl");
03459          sayfile(mychannel, "rpt/off");
03460          break;
03461           case 101: /* RX PL On */
03462          sayfile(mychannel, "rpt/rxpl");
03463          sayfile(mychannel, "rpt/on");
03464          break;
03465           case 102: /* TX PL Off */
03466          sayfile(mychannel, "rpt/txpl");
03467          sayfile(mychannel, "rpt/off");
03468          break;
03469           case 103: /* TX PL On */
03470          sayfile(mychannel, "rpt/txpl");
03471          sayfile(mychannel, "rpt/on");
03472          break;
03473           case 104: /* Low Power */
03474          sayfile(mychannel, "rpt/lopwr");
03475          break;
03476           case 105: /* Medium Power */
03477          sayfile(mychannel, "rpt/medpwr");
03478          break;
03479           case 106: /* Hi Power */
03480          sayfile(mychannel, "rpt/hipwr");
03481          break;
03482           case 113: /* Scan down slow */
03483          sayfile(mychannel,"rpt/down");
03484          sayfile(mychannel, "rpt/slow");
03485          break;
03486           case 114: /* Scan down quick */
03487          sayfile(mychannel,"rpt/down");
03488          sayfile(mychannel, "rpt/quick");
03489          break;
03490           case 115: /* Scan down fast */
03491          sayfile(mychannel,"rpt/down");
03492          sayfile(mychannel, "rpt/fast");
03493          break;
03494           case 116: /* Scan up slow */
03495          sayfile(mychannel,"rpt/up");
03496          sayfile(mychannel, "rpt/slow");
03497          break;
03498           case 117: /* Scan up quick */
03499          sayfile(mychannel,"rpt/up");
03500          sayfile(mychannel, "rpt/quick");
03501          break;
03502           case 118: /* Scan up fast */
03503          sayfile(mychannel,"rpt/up");
03504          sayfile(mychannel, "rpt/fast");
03505          break;
03506           default:
03507          res = -1;
03508       }
03509       wait_interval(myrpt, DLY_COMP, mychannel);
03510       if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03511       break;
03512        case SCAN:
03513       ast_mutex_lock(&myrpt->remlock);
03514       if (myrpt->hfscanstop)
03515       {
03516          myrpt->hfscanstatus = 0;
03517          myrpt->hfscanmode = 0;
03518          myrpt->hfscanstop = 0;
03519          mytele->mode = SCANSTAT;
03520          ast_mutex_unlock(&myrpt->remlock);
03521          if (ast_safe_sleep(mychannel,1000) == -1) break;
03522          sayfile(mychannel, "rpt/stop"); 
03523          imdone = 1;
03524          break;
03525       }
03526       if (myrpt->hfscanstatus > -2) service_scan(myrpt);
03527       i = myrpt->hfscanstatus;
03528       myrpt->hfscanstatus = 0;
03529       if (i) mytele->mode = SCANSTAT;
03530       ast_mutex_unlock(&myrpt->remlock);
03531       if (i < 0) sayfile(mychannel, "rpt/stop"); 
03532       else if (i > 0) saynum(mychannel,i);
03533       imdone = 1;
03534       break;
03535        case TUNE:
03536       ast_mutex_lock(&myrpt->remlock);
03537       if (!strcmp(myrpt->remote,remote_rig_ic706))
03538       {
03539          set_mode_ic706(myrpt, REM_MODE_AM);
03540          if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
03541          ast_safe_sleep(mychannel,500);
03542          set_mode_ic706(myrpt, myrpt->remmode);
03543          myrpt->tunerequest = 0;
03544          ast_mutex_unlock(&myrpt->remlock);
03545          imdone = 1;
03546          break;
03547       }
03548       set_mode_ft897(myrpt, REM_MODE_AM);
03549       simple_command_ft897(myrpt, 8);
03550       if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
03551       simple_command_ft897(myrpt, 0x88);
03552       ast_safe_sleep(mychannel,500);
03553       set_mode_ft897(myrpt, myrpt->remmode);
03554       myrpt->tunerequest = 0;
03555       ast_mutex_unlock(&myrpt->remlock);
03556       imdone = 1;
03557       break;
03558        case REMSHORTSTATUS:
03559        case REMLONGSTATUS: 
03560       wait_interval(myrpt, DLY_TELEM, mychannel);
03561       res = sayfile(mychannel,"rpt/node");
03562       if(!res)
03563          res = saycharstr(mychannel, myrpt->name);
03564       if(!res)
03565          res = sayfile(mychannel,"rpt/frequency");
03566       if(!res)
03567          res = split_freq(mhz, decimals, myrpt->freq);
03568       if (!multimode_capable(myrpt)) decimals[3] = 0;
03569       if(!res){
03570          m = atoi(mhz);
03571          if(m < 100)
03572             res = saynum(mychannel, m);
03573          else
03574             res = saycharstr(mychannel, mhz);
03575       }
03576       if(!res)
03577          res = sayfile(mychannel, "letters/dot");
03578       if(!res)
03579          res = saycharstr(mychannel, decimals);
03580    
03581       if(res)  break;
03582       if(myrpt->remmode == REM_MODE_FM){ /* Mode FM? */
03583          switch(myrpt->offset){
03584    
03585             case REM_MINUS:
03586                res = sayfile(mychannel,"rpt/minus");
03587                break;
03588             
03589             case REM_SIMPLEX:
03590                res = sayfile(mychannel,"rpt/simplex");
03591                break;
03592                
03593             case REM_PLUS:
03594                res = sayfile(mychannel,"rpt/plus");
03595                break;
03596                
03597             default:
03598                break;
03599          }
03600       }
03601       else{ /* Must be USB, LSB, or AM */
03602          switch(myrpt->remmode){
03603 
03604             case REM_MODE_USB:
03605                res = saycharstr(mychannel, "USB");
03606                break;
03607 
03608             case REM_MODE_LSB:
03609                res = saycharstr(mychannel, "LSB");
03610                break;
03611 
03612             case REM_MODE_AM:
03613                res = saycharstr(mychannel, "AM");
03614                break;
03615 
03616 
03617             default:
03618                break;
03619          }
03620       }
03621 
03622       if (res == -1) break;
03623 
03624       if(mytele->mode == REMSHORTSTATUS){ /* Short status? */
03625          wait_interval(myrpt, DLY_COMP, mychannel);
03626          if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03627          break;
03628       }
03629 
03630       if (strcmp(myrpt->remote,remote_rig_ic706))
03631       {
03632          switch(myrpt->powerlevel){
03633 
03634             case REM_LOWPWR:
03635                res = sayfile(mychannel,"rpt/lopwr") ;
03636                break;
03637             case REM_MEDPWR:
03638                res = sayfile(mychannel,"rpt/medpwr");
03639                break;
03640             case REM_HIPWR:
03641                res = sayfile(mychannel,"rpt/hipwr"); 
03642                break;
03643             }
03644       }
03645 
03646       rbimode = ((!strncmp(myrpt->remote,remote_rig_rbi,3))
03647         || (!strncmp(myrpt->remote,remote_rig_ic706,3)));
03648       if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
03649       if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
03650       if ((sayfile(mychannel,"rpt/frequency") == -1) ||
03651          (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
03652       if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
03653          (sayfile(mychannel,"rpt/frequency") == -1) ||
03654          (saycharstr(mychannel,myrpt->txpl) == -1))) break;
03655       if(myrpt->remmode == REM_MODE_FM){ /* Mode FM? */
03656          if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
03657             (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
03658             (sayfile(mychannel,"rpt/txpl") == -1) ||
03659             (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
03660             {
03661                break;
03662             }
03663       }
03664       wait_interval(myrpt, DLY_COMP, mychannel);
03665       if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
03666       break;
03667        case STATUS:
03668       /* wait a little bit */
03669       wait_interval(myrpt, DLY_TELEM, mychannel);
03670       hastx = 0;
03671       linkbase.next = &linkbase;
03672       linkbase.prev = &linkbase;
03673       rpt_mutex_lock(&myrpt->lock);
03674       /* make our own list of links */
03675       l = myrpt->links.next;
03676       while(l != &myrpt->links)
03677       {
03678          if (l->name[0] == '0')
03679          {
03680             l = l->next;
03681             continue;
03682          }
03683          l1 = malloc(sizeof(struct rpt_link));
03684          if (!l1)
03685          {
03686             ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
03687             remque((struct qelem *)mytele);
03688             rpt_mutex_unlock(&myrpt->lock);
03689             ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
03690             free(mytele);     
03691             ast_hangup(mychannel);
03692             pthread_exit(NULL);
03693          }
03694          memcpy(l1,l,sizeof(struct rpt_link));
03695          l1->next = l1->prev = NULL;
03696          insque((struct qelem *)l1,(struct qelem *)linkbase.next);
03697          l = l->next;
03698       }
03699       rpt_mutex_unlock(&myrpt->lock);
03700       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03701       if (!res) 
03702          res = ast_waitstream(mychannel, "");
03703       else
03704           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03705       ast_stopstream(mychannel);
03706       ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03707       if (!res) 
03708          res = ast_waitstream(mychannel, "");
03709       else
03710           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03711       ast_stopstream(mychannel);
03712       if (myrpt->callmode)
03713       {
03714          hastx = 1;
03715          res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
03716          if (!res) 
03717             res = ast_waitstream(mychannel, "");
03718          else
03719              ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03720          ast_stopstream(mychannel);
03721       }
03722       l = linkbase.next;
03723       while(l != &linkbase)
03724       {
03725          char *s;
03726 
03727          hastx = 1;
03728          res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03729          if (!res) 
03730             res = ast_waitstream(mychannel, "");
03731          else
03732             ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03733          ast_stopstream(mychannel);
03734          ast_say_character_str(mychannel,l->name,NULL,mychannel->language);
03735          if (!res) 
03736             res = ast_waitstream(mychannel, "");
03737          else
03738              ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03739          ast_stopstream(mychannel);
03740          s = "rpt/tranceive";
03741          if (!l->mode) s = "rpt/monitor";
03742          if (!l->thisconnected) s = "rpt/connecting";
03743          res = ast_streamfile(mychannel, s, mychannel->language);
03744          if (!res) 
03745             res = ast_waitstream(mychannel, "");
03746          else
03747             ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03748          ast_stopstream(mychannel);
03749          l = l->next;
03750       }        
03751       if (!hastx)
03752       {
03753          res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
03754          if (!res) 
03755             res = ast_waitstream(mychannel, "");
03756          else
03757              ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03758          ast_stopstream(mychannel);
03759       }
03760       /* destroy our local link queue */
03761       l = linkbase.next;
03762       while(l != &linkbase)
03763       {
03764          l1 = l;
03765          l = l->next;
03766          remque((struct qelem *)l1);
03767          free(l1);
03768       }        
03769       imdone = 1;
03770       break;
03771        case FULLSTATUS:
03772       rpt_mutex_lock(&myrpt->lock);
03773       /* get all the nodes */
03774       __mklinklist(myrpt,NULL,lbuf);
03775       rpt_mutex_unlock(&myrpt->lock);
03776       /* parse em */
03777       ns = finddelim(lbuf,strs,MAXLINKLIST);
03778       /* sort em */
03779       if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
03780       /* wait a little bit */
03781       wait_interval(myrpt, DLY_TELEM, mychannel);
03782       hastx = 0;
03783       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03784       if (!res) 
03785          res = ast_waitstream(mychannel, "");
03786       else
03787           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03788       ast_stopstream(mychannel);
03789       ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03790       if (!res) 
03791          res = ast_waitstream(mychannel, "");
03792       else
03793           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03794       ast_stopstream(mychannel);
03795       if (myrpt->callmode)
03796       {
03797          hastx = 1;
03798          res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
03799          if (!res) 
03800             res = ast_waitstream(mychannel, "");
03801          else
03802              ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03803          ast_stopstream(mychannel);
03804       }
03805       /* go thru all the nodes in list */
03806       for(i = 0; i < ns; i++)
03807       {
03808          char *s,mode = 'T';
03809 
03810          /* if a mode spec at first, handle it */
03811          if ((*strs[i] < '0') || (*strs[i] > '9'))
03812          {
03813             mode = *strs[i];
03814             strs[i]++;
03815          }
03816 
03817          hastx = 1;
03818          res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03819          if (!res) 
03820             res = ast_waitstream(mychannel, "");
03821          else
03822             ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03823          ast_stopstream(mychannel);
03824          ast_say_character_str(mychannel,strs[i],NULL,mychannel->language);
03825          if (!res) 
03826             res = ast_waitstream(mychannel, "");
03827          else
03828              ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03829          ast_stopstream(mychannel);
03830          s = "rpt/tranceive";
03831          if (mode == 'R') s = "rpt/monitor";
03832          if (mode == 'C') s = "rpt/connecting";
03833          res = ast_streamfile(mychannel, s, mychannel->language);
03834          if (!res) 
03835             res = ast_waitstream(mychannel, "");
03836          else
03837             ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03838          ast_stopstream(mychannel);
03839       }        
03840       if (!hastx)
03841       {
03842          res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
03843          if (!res) 
03844             res = ast_waitstream(mychannel, "");
03845          else
03846              ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03847          ast_stopstream(mychannel);
03848       }
03849       imdone = 1;
03850       break;
03851 
03852        case LASTNODEKEY: /* Identify last node which keyed us up */
03853       rpt_mutex_lock(&myrpt->lock);
03854       if(myrpt->lastnodewhichkeyedusup)
03855          p = ast_strdupa(myrpt->lastnodewhichkeyedusup); /* Make a local copy of the node name */
03856       else
03857          p = NULL;
03858       rpt_mutex_unlock(&myrpt->lock);
03859       if(!p){
03860          imdone = 1; /* no node previously keyed us up, or the node which did has been disconnected */
03861          break;
03862       }
03863       wait_interval(myrpt, DLY_TELEM, mychannel);
03864       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03865       if (!res) 
03866          res = ast_waitstream(mychannel, "");
03867       else
03868           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03869       ast_stopstream(mychannel);
03870       ast_say_character_str(mychannel, p, NULL, mychannel->language);
03871       if (!res) 
03872          res = ast_waitstream(mychannel, "");
03873       else
03874          ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03875       ast_stopstream(mychannel);
03876       imdone = 1;
03877       break;      
03878 
03879        case UNAUTHTX: /* Say unauthorized transmit frequency */
03880       wait_interval(myrpt, DLY_TELEM, mychannel);
03881       res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
03882       if (!res) 
03883          res = ast_waitstream(mychannel, "");
03884       else
03885           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03886       ast_stopstream(mychannel);
03887       imdone = 1;
03888       break;
03889       
03890 
03891        case TIMEOUT:
03892       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03893       if (!res) 
03894          res = ast_waitstream(mychannel, "");
03895       else
03896           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03897       ast_stopstream(mychannel);
03898       ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03899       res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
03900       break;
03901       
03902        case TIMEOUT_WARNING:
03903       time(&t);
03904       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03905       if (!res) 
03906          res = ast_waitstream(mychannel, "");
03907       else
03908           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03909       ast_stopstream(mychannel);
03910       ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03911       res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
03912       if (!res) 
03913          res = ast_waitstream(mychannel, "");
03914       else
03915           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03916       ast_stopstream(mychannel);
03917       if(!res) /* Say number of seconds */
03918          ast_say_number(mychannel, myrpt->p.remotetimeout - 
03919              (t - myrpt->last_activity_time), 
03920             "", mychannel->language, (char *) NULL);
03921       if (!res) 
03922          res = ast_waitstream(mychannel, "");
03923       ast_stopstream(mychannel); 
03924       res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
03925       break;
03926 
03927        case ACT_TIMEOUT_WARNING:
03928       time(&t);
03929       res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
03930       if (!res) 
03931          res = ast_waitstream(mychannel, "");
03932       else
03933           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03934       ast_stopstream(mychannel);
03935       ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
03936       res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
03937       if (!res) 
03938          res = ast_waitstream(mychannel, "");
03939       else
03940           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
03941       ast_stopstream(mychannel);
03942       if(!res) /* Say number of seconds */
03943          ast_say_number(mychannel, myrpt->p.remoteinacttimeout - 
03944              (t - myrpt->last_activity_time), 
03945             "", mychannel->language, (char *) NULL);
03946       if (!res) 
03947          res = ast_waitstream(mychannel, "");
03948       ast_stopstream(mychannel); 
03949       res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
03950       break;
03951       
03952        case STATS_TIME:
03953          wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
03954       t = time(NULL);
03955       rpt_localtime(&t, &localtm);
03956       /* Say the phase of the day is before the time */
03957       if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
03958          p = "rpt/goodmorning";
03959       else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
03960          p = "rpt/goodafternoon";
03961       else
03962          p = "rpt/goodevening";
03963       if (sayfile(mychannel,p) == -1)
03964       {
03965          imdone = 1;
03966          break;
03967       }
03968       /* Say the time is ... */     
03969       if (sayfile(mychannel,"rpt/thetimeis") == -1)
03970       {
03971          imdone = 1;
03972          break;
03973       }
03974       /* Say the time */            
03975          res = ast_say_time(mychannel, t, "", mychannel->language);
03976       if (!res) 
03977          res = ast_waitstream(mychannel, "");
03978       ast_stopstream(mychannel);    
03979       imdone = 1;
03980          break;
03981        case STATS_VERSION:
03982       p = strstr(tdesc, "version"); 
03983       if(!p)
03984          break;   
03985       if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
03986          break;
03987          wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
03988       /* Say "version" */
03989       if (sayfile(mychannel,"rpt/version") == -1)
03990       {
03991          imdone = 1;
03992          break;
03993       }
03994       if(!res) /* Say "X" */
03995          ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
03996       if (!res) 
03997          res = ast_waitstream(mychannel, "");
03998       ast_stopstream(mychannel); 
03999       if (saycharstr(mychannel,".") == -1)
04000       {
04001          imdone = 1;
04002          break;
04003       }
04004       if(!res) /* Say "Y" */
04005          ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
04006       if (!res){
04007          res = ast_waitstream(mychannel, "");
04008          ast_stopstream(mychannel);
04009       }  
04010       else
04011           ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04012       imdone = 1;
04013          break;
04014        case ARB_ALPHA:
04015          wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
04016          if(mytele->param)
04017             saycharstr(mychannel, mytele->param);
04018          imdone = 1;
04019       break;
04020        case REV_PATCH:
04021          wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
04022          if(mytele->param) {
04023 
04024          /* Parts of this section taken from app_parkandannounce */
04025          char *tpl_working, *tpl_current;
04026          char *tmp[100], *myparm;
04027          int looptemp=0,i=0, dres = 0;
04028    
04029 
04030          tpl_working = strdupa(mytele->param);
04031          myparm = strsep(&tpl_working,",");
04032          tpl_current=strsep(&tpl_working, ":");
04033 
04034          while(tpl_current && looptemp < sizeof(tmp)) {
04035             tmp[looptemp]=tpl_current;
04036             looptemp++;
04037             tpl_current=strsep(&tpl_working,":");
04038          }
04039 
04040          for(i=0; i<looptemp; i++) {
04041             if(!strcmp(tmp[i], "PARKED")) {
04042                ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
04043             } else if(!strcmp(tmp[i], "NODE")) {
04044                ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
04045             } else {
04046                dres = ast_streamfile(mychannel, tmp[i], mychannel->language);
04047                if(!dres) {
04048                   dres = ast_waitstream(mychannel, "");
04049                } else {
04050                   ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name);
04051                   dres = 0;
04052                }
04053             }
04054          }
04055       }
04056          imdone = 1;
04057       break;
04058        case TEST_TONE:
04059       imdone = 1;
04060       if (myrpt->stopgen) break;
04061       myrpt->stopgen = -1;
04062            if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0))) 
04063       {
04064          myrpt->stopgen = 0;
04065          break;
04066       }
04067            while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
04068          if (ast_safe_sleep(mychannel,1)) break;
04069             imdone = 1;
04070          }
04071       myrpt->stopgen = 0;
04072       break;
04073        default:
04074          break;
04075    }
04076    if (!imdone)
04077    {
04078       if (!res) 
04079          res = ast_waitstream(mychannel, "");
04080       else {
04081          ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
04082          res = 0;
04083       }
04084    }
04085    ast_stopstream(mychannel);
04086    rpt_mutex_lock(&myrpt->lock);
04087    if (mytele->mode == TAILMSG)
04088    {
04089       if (!res)
04090       {
04091          myrpt->tailmessagen++;
04092          if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
04093       }
04094       else
04095       {
04096          myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
04097       }
04098    }
04099    remque((struct qelem *)mytele);
04100    rpt_mutex_unlock(&myrpt->lock);
04101    free(mytele);     
04102    ast_hangup(mychannel);
04103 #ifdef  APP_RPT_LOCK_DEBUG
04104    {
04105       struct lockthread *t;
04106 
04107       sleep(5);
04108       ast_mutex_lock(&locklock);
04109       t = get_lockthread(pthread_self());
04110       if (t) memset(t,0,sizeof(struct lockthread));
04111       ast_mutex_unlock(&locklock);
04112    }        
04113 #endif
04114    pthread_exit(NULL);
04115 }

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

Definition at line 4117 of file app_rpt.c.

References ARB_ALPHA, ast_log(), ast_pthread_create, CONNECTED, CONNFAIL, LINKUNKEY, rpt::lock, LOG_WARNING, malloc, rpt_tele::next, REMDISC, REMXXX, REV_PATCH, rpt_mutex_lock, rpt_mutex_unlock, rpt_tele_thread(), rpt::tele, and TELEPARAMSIZE.

Referenced by function_autopatchdn(), function_cop(), function_ilink(), function_macro(), function_remote(), function_status(), handle_link_data(), handle_link_phone_dtmf(), handle_remote_data(), handle_remote_phone_dtmf(), local_dtmf_helper(), queue_id(), rpt(), rpt_call(), setrem(), and stop_scan().

04118 {
04119 struct rpt_tele *tele;
04120 struct rpt_link *mylink = (struct rpt_link *) data;
04121 int res;
04122 pthread_attr_t attr;
04123 
04124    tele = malloc(sizeof(struct rpt_tele));
04125    if (!tele)
04126    {
04127       ast_log(LOG_WARNING, "Unable to allocate memory\n");
04128       pthread_exit(NULL);
04129       return;
04130    }
04131    /* zero it out */
04132    memset((char *)tele,0,sizeof(struct rpt_tele));
04133    tele->rpt = myrpt;
04134    tele->mode = mode;
04135    rpt_mutex_lock(&myrpt->lock);
04136    if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
04137        (mode == LINKUNKEY)){
04138       memset(&tele->mylink,0,sizeof(struct rpt_link));
04139       if (mylink){
04140          memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
04141       }
04142    }
04143    else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) {
04144       strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
04145       tele->param[TELEPARAMSIZE - 1] = 0;
04146    }
04147    if (mode == REMXXX) tele->submode = (int) data;
04148    insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
04149    rpt_mutex_unlock(&myrpt->lock);
04150         pthread_attr_init(&attr);
04151         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04152    res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
04153    if(res < 0){
04154       rpt_mutex_lock(&myrpt->lock);
04155       remque((struct qlem *) tele); /* We don't like stuck transmitters, remove it from the queue */
04156       rpt_mutex_unlock(&myrpt->lock);  
04157       ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
04158    }
04159    return;
04160 }

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

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

02689 {
02690 int   res;
02691 
02692    res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
02693    if (!res) 
02694       res = ast_waitstream(mychannel, "");
02695    else
02696        ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
02697    ast_stopstream(mychannel);
02698    return res;
02699 }

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

Definition at line 2675 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 rpt_tele_thread(), and telem_any().

02676 {
02677 int   res;
02678 
02679    res = ast_streamfile(mychannel, fname, mychannel->language);
02680    if (!res) 
02681       res = ast_waitstream(mychannel, "");
02682    else
02683        ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
02684    ast_stopstream(mychannel);
02685    return res;
02686 }

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

Definition at line 2701 of file app_rpt.c.

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

Referenced by rpt_tele_thread().

02702 {
02703    int res;
02704    res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
02705    if(!res)
02706       res = ast_waitstream(mychannel, "");
02707    else
02708       ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
02709    ast_stopstream(mychannel);
02710    return res;
02711 }

static int select_mem_ic706 ( struct rpt myrpt,
int  slot 
) [static]

Definition at line 7202 of file app_rpt.c.

References civ_cmd(), rpt::civaddr, and rpt::p.

Referenced by set_ic706().

07203 {
07204    unsigned char cmdstr[10];
07205    
07206    cmdstr[0] = cmdstr[1] = 0xfe;
07207    cmdstr[2] = myrpt->p.civaddr;
07208    cmdstr[3] = 0xe0;
07209    cmdstr[4] = 8;
07210    cmdstr[5] = 0;
07211    cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
07212    cmdstr[7] = 0xfd;
07213 
07214    return(civ_cmd(myrpt,cmdstr,8));
07215 }

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

Definition at line 4414 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, and ast_frame::subclass.

Referenced by handle_link_phone_dtmf(), and local_dtmf_helper().

04415 {
04416 char  str[300];
04417 struct   ast_frame wf;
04418 struct   rpt_link *l;
04419 
04420    snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
04421    wf.frametype = AST_FRAME_TEXT;
04422    wf.subclass = 0;
04423    wf.offset = 0;
04424    wf.mallocd = 0;
04425    wf.datalen = strlen(str) + 1;
04426    wf.samples = 0;
04427    l = myrpt->links.next;
04428    /* first, see if our dude is there */
04429    while(l != &myrpt->links)
04430    {
04431       if (l->name[0] == '0') 
04432       {
04433          l = l->next;
04434          continue;
04435       }
04436       /* if we found it, write it and were done */
04437       if (!strcmp(l->name,myrpt->cmdnode))
04438       {
04439          wf.data = str;
04440          if (l->chan) ast_write(l->chan,&wf);
04441          return;
04442       }
04443       l = l->next;
04444    }
04445    l = myrpt->links.next;
04446    /* if not, give it to everyone */
04447    while(l != &myrpt->links)
04448    {
04449       wf.data = str;
04450       if (l->chan) ast_write(l->chan,&wf);
04451       l = l->next;
04452    }
04453    return;
04454 }

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

Definition at line 2462 of file app_rpt.c.

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

Referenced by telem_any().

02463 {
02464 
02465 static struct morse_bits mbits[] = {
02466       {0, 0}, /* SPACE */
02467       {0, 0}, 
02468       {6, 18},/* " */
02469       {0, 0},
02470       {7, 72},/* $ */
02471       {0, 0},
02472       {0, 0},
02473       {6, 30},/* ' */
02474       {5, 13},/* ( */
02475       {6, 29},/* ) */
02476       {0, 0},
02477       {5, 10},/* + */
02478       {6, 51},/* , */
02479       {6, 33},/* - */
02480       {6, 42},/* . */
02481       {5, 9}, /* / */
02482       {5, 31},/* 0 */
02483       {5, 30},/* 1 */
02484       {5, 28},/* 2 */
02485       {5, 24},/* 3 */
02486       {5, 16},/* 4 */
02487       {5, 0}, /* 5 */
02488       {5, 1}, /* 6 */
02489       {5, 3}, /* 7 */
02490       {5, 7}, /* 8 */
02491       {5, 15},/* 9 */
02492       {6, 7}, /* : */
02493       {6, 21},/* ; */
02494       {0, 0},
02495       {5, 33},/* = */
02496       {0, 0},
02497       {6, 12},/* ? */
02498       {0, 0},
02499          {2, 2}, /* A */
02500       {4, 1}, /* B */
02501       {4, 5}, /* C */
02502       {3, 1}, /* D */
02503       {1, 0}, /* E */
02504       {4, 4}, /* F */
02505       {3, 3}, /* G */
02506       {4, 0}, /* H */
02507       {2, 0}, /* I */
02508       {4, 14},/* J */
02509       {3, 5}, /* K */
02510       {4, 2}, /* L */
02511       {2, 3}, /* M */
02512       {2, 1}, /* N */
02513       {3, 7}, /* O */
02514       {4, 6}, /* P */
02515       {4, 11},/* Q */
02516       {3, 2}, /* R */
02517       {3, 0}, /* S */
02518       {1, 1}, /* T */
02519       {3, 4}, /* U */
02520       {4, 8}, /* V */
02521       {3, 6}, /* W */
02522       {4, 9}, /* X */
02523       {4, 13},/* Y */
02524       {4, 3}  /* Z */
02525    };
02526 
02527 
02528    int dottime;
02529    int dashtime;
02530    int intralettertime;
02531    int interlettertime;
02532    int interwordtime;
02533    int len, ddcomb;
02534    int res;
02535    int c;
02536    int i;
02537    int flags;
02538          
02539    res = 0;
02540    
02541    /* Approximate the dot time from the speed arg. */
02542    
02543    dottime = 900/speed;
02544    
02545    /* Establish timing releationships */
02546    
02547    dashtime = 3 * dottime;
02548    intralettertime = dottime;
02549    interlettertime = dottime * 4 ;
02550    interwordtime = dottime * 7;
02551    
02552    for(;(*string) && (!res); string++){
02553    
02554       c = *string;
02555       
02556       /* Convert lower case to upper case */
02557       
02558       if((c >= 'a') && (c <= 'z'))
02559          c -= 0x20;
02560       
02561       /* Can't deal with any char code greater than Z, skip it */
02562       
02563       if(c  > 'Z')
02564          continue;
02565       
02566       /* If space char, wait the inter word time */
02567                
02568       if(c == ' '){
02569          if(!res)
02570             res = play_silence(chan, interwordtime);
02571          continue;
02572       }
02573       
02574       /* Subtract out control char offset to match our table */
02575       
02576       c -= 0x20;
02577       
02578       /* Get the character data */
02579       
02580       len = mbits[c].len;
02581       ddcomb = mbits[c].ddcomb;
02582       
02583       /* Send the character */
02584       
02585       for(; len ; len--){
02586          if(!res)
02587             res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
02588          if(!res)
02589             res = play_silence(chan, intralettertime);
02590          ddcomb >>= 1;
02591       }
02592       
02593       /* Wait the interletter time */
02594       
02595       if(!res)
02596          res = play_silence(chan, interlettertime - intralettertime);
02597    }
02598    
02599    /* Wait for all the frames to be sent */
02600    
02601    if (!res) 
02602       res = ast_waitstream(chan, "");
02603    ast_stopstream(chan);
02604    
02605    /*
02606    * Wait for the zaptel driver to physically write the tone blocks to the hardware
02607    */
02608 
02609    for(i = 0; i < 20 ; i++){
02610       flags =  DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT; 
02611       res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
02612       if(flags & DAHDI_IOMUX_WRITEEMPTY)
02613          break;
02614       if( ast_safe_sleep(chan, 50)){
02615          res = -1;
02616          break;
02617       }
02618    }
02619 
02620    
02621    return res;
02622 }

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

Definition at line 2624 of file app_rpt.c.

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

Referenced by telem_any().

02625 {
02626    char *stringp;
02627    char *tonesubset;
02628    int f1,f2;
02629    int duration;
02630    int amplitude;
02631    int res;
02632    int i;
02633    int flags;
02634    
02635    res = 0;
02636    
02637    stringp = ast_strdupa(tonestring);
02638 
02639    for(;tonestring;){
02640       tonesubset = strsep(&stringp,")");
02641       if(!tonesubset)
02642          break;
02643       if(sscanf(tonesubset,"(%d,%d,%d,%d", &f1, &f2, &duration, &amplitude) != 4)
02644          break;
02645       res = play_tone_pair(chan, f1, f2, duration, amplitude);
02646       if(res)
02647          break;
02648    }
02649    if(!res)
02650       res = play_tone_pair(chan, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */
02651    
02652    if (!res) 
02653       res = ast_waitstream(chan, "");
02654    ast_stopstream(chan);
02655 
02656    /*
02657    * Wait for the zaptel driver to physically write the tone blocks to the hardware
02658    */
02659 
02660    for(i = 0; i < 20 ; i++){
02661       flags =  DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT; 
02662       res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
02663       if(flags & DAHDI_IOMUX_WRITEEMPTY)
02664          break;
02665       if( ast_safe_sleep(chan, 50)){
02666          res = -1;
02667          break;
02668       }
02669    }
02670       
02671    return res;
02672       
02673 }

static int sendkenwood ( struct rpt myrpt,
char *  txstr,
char *  rxstr 
) [static]

Definition at line 5973 of file app_rpt.c.

References serial_remote_io().

Referenced by sendrxkenwood().

05974 {
05975 int   i;
05976 
05977    if (debug) printf("Send to kenwood: %s\n",txstr);
05978    i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr), 
05979       (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
05980    if (i < 0) return -1;
05981    if ((i > 0) && (rxstr[i - 1] == '\r'))
05982       rxstr[i-- - 1] = 0;
05983    if (debug) printf("Got from kenwood: %s\n",rxstr);
05984    return(i);
05985 }

static int sendrxkenwood ( struct rpt myrpt,
char *  txstr,
char *  rxstr,
char *  cmpstr 
) [static]

Definition at line 6079 of file app_rpt.c.

References KENWOOD_RETRIES, and sendkenwood().

Referenced by setkenwood().

06081 {
06082 int   i,j;
06083 
06084    for(i = 0;i < KENWOOD_RETRIES;i++)
06085    {
06086       j = sendkenwood(myrpt,txstr,rxstr);
06087       if (j < 0) return(j);
06088       if (j == 0) continue;
06089       if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
06090    }
06091    return(-1);
06092 }     

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

Definition at line 5870 of file app_rpt.c.

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

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

05872 {
05873    int i,j,index,oldmode,olddata;
05874    struct dahdi_radio_param prm;
05875    char c;
05876 
05877    if(debug){
05878       printf("String output was: ");
05879       for(i = 0; i < txbytes; i++)
05880          printf("%02X ", (unsigned char ) txbuf[i]);
05881       printf("\n");
05882    }
05883    if (myrpt->iofd > 0)  /* if to do out a serial port */
05884    {
05885       if (rxmaxbytes && rxbuf) tcflush(myrpt->iofd,TCIFLUSH);     
05886       if (write(myrpt->iofd,txbuf,txbytes) != txbytes) return -1;
05887       if ((!rxmaxbytes) || (rxbuf == NULL)) return(0);
05888       memset(rxbuf,0,rxmaxbytes);
05889       for(i = 0; i < rxmaxbytes; i++)
05890       {
05891          j = read(myrpt->iofd,&c,1);
05892          if (j < 1) return(i);
05893          rxbuf[i] = c;
05894          if (asciiflag & 1)
05895          {
05896             rxbuf[i + 1] = 0;
05897             if (c == '\r') break;
05898          }
05899       }              
05900       if(debug){
05901          printf("String returned was: ");
05902          for(j = 0; j < i; j++)
05903             printf("%02X ", (unsigned char ) rxbuf[j]);
05904          printf("\n");
05905       }
05906       return(i);
05907    }
05908 
05909    /* if not a zap channel, cant use pciradio stuff */
05910    if (myrpt->rxchannel != myrpt->zaprxchannel) return -1;  
05911 
05912    prm.radpar = DAHDI_RADPAR_UIOMODE;
05913    if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
05914    oldmode = prm.data;
05915    prm.radpar = DAHDI_RADPAR_UIODATA;
05916    if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
05917    olddata = prm.data;
05918         prm.radpar = DAHDI_RADPAR_REMMODE;
05919         if (asciiflag & 1)  prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
05920         else prm.data = DAHDI_RADPAR_REM_SERIAL;
05921    if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
05922    if (asciiflag & 2)
05923    {
05924       i = DAHDI_ONHOOK;
05925       if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
05926       usleep(100000);
05927    }
05928         prm.radpar = DAHDI_RADPAR_REMCOMMAND;
05929         prm.data = rxmaxbytes;
05930         memcpy(prm.buf,txbuf,txbytes);
05931         prm.index = txbytes;
05932    if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
05933         if (rxbuf)
05934         {
05935                 *rxbuf = 0;
05936                 memcpy(rxbuf,prm.buf,prm.index);
05937         }
05938    index = prm.index;
05939         prm.radpar = DAHDI_RADPAR_REMMODE;
05940         prm.data = DAHDI_RADPAR_REM_NONE;
05941    if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
05942    if (asciiflag & 2)
05943    {
05944       i = DAHDI_OFFHOOK;
05945       if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
05946    }
05947    prm.radpar = DAHDI_RADPAR_UIOMODE;
05948    prm.data = oldmode;
05949    if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
05950    prm.radpar = DAHDI_RADPAR_UIODATA;
05951    prm.data = olddata;
05952    if (ioctl(myrpt->zaprxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
05953         return(index);
05954 }

static int service_scan ( struct rpt myrpt  )  [static]

Definition at line 7578 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(), and split_freq().

Referenced by rpt_tele_thread().

07579 {
07580    int res, interval;
07581    char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
07582 
07583    switch(myrpt->hfscanmode){
07584 
07585       case HF_SCAN_DOWN_SLOW:
07586          interval = -10; /* 100Hz /sec */
07587          break;
07588 
07589       case HF_SCAN_DOWN_QUICK:
07590          interval = -50; /* 500Hz /sec */
07591          break;
07592 
07593       case HF_SCAN_DOWN_FAST:
07594          interval = -200; /* 2KHz /sec */
07595          break;
07596 
07597       case HF_SCAN_UP_SLOW:
07598          interval = 10; /* 100Hz /sec */
07599          break;
07600 
07601       case HF_SCAN_UP_QUICK:
07602          interval = 50; /* 500 Hz/sec */
07603          break;
07604 
07605       case HF_SCAN_UP_FAST:
07606          interval = 200; /* 2KHz /sec */
07607          break;
07608 
07609       default:
07610          myrpt->hfscanmode = 0; /* Huh? */
07611          return -1;
07612    }
07613 
07614    res = split_freq(mhz, decimals, myrpt->freq);
07615       
07616    if(!res){
07617       k100 =decimals[0];
07618       k10 = decimals[1];
07619       res = multimode_bump_freq(myrpt, interval);
07620    }
07621 
07622    if(!res)
07623       res = split_freq(mhz, decimals, myrpt->freq);
07624 
07625 
07626    if(res){
07627       myrpt->hfscanmode = 0;
07628       myrpt->hfscanstatus = -2;
07629       return -1;
07630    }
07631 
07632    /* Announce 10KHz boundaries */
07633    if(k10 != decimals[1]){
07634       int myhund = (interval < 0) ? k100 : decimals[0];
07635       int myten = (interval < 0) ? k10 : decimals[1];
07636       myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
07637    } else myrpt->hfscanstatus = 0;
07638    return res;
07639 
07640 }

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

Definition at line 6638 of file app_rpt.c.

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

Referenced by set_ft897().

06639 {
06640    unsigned char cmdstr[5];
06641    char hertz[MAXREMSTR],decimal[MAXREMSTR];
06642    int h,d; 
06643 
06644    memset(cmdstr, 0, 5);
06645 
06646    if(split_ctcss_freq(hertz, decimal, txtone))
06647       return -1; 
06648 
06649    h = atoi(hertz);
06650    d = atoi(decimal);
06651    
06652    cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
06653    cmdstr[1] = ((h % 10) << 4) + (d % 10);
06654    
06655    if(rxtone){
06656    
06657       if(split_ctcss_freq(hertz, decimal, rxtone))
06658          return -1; 
06659 
06660       h = atoi(hertz);
06661       d = atoi(decimal);
06662    
06663       cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
06664       cmdstr[3] = ((h % 10) << 4) + (d % 10);
06665    }
06666    cmdstr[4] = 0x0B; 
06667 
06668    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06669 }  

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

Definition at line 6615 of file app_rpt.c.

References serial_remote_io().

Referenced by set_ft897().

06616 {
06617    unsigned char cmdstr[5];
06618    
06619    memset(cmdstr, 0, 5);
06620    
06621    if(rxplon && txplon)
06622       cmdstr[0] = 0x2A; /* Encode and Decode */
06623    else if (!rxplon && txplon)
06624       cmdstr[0] = 0x4A; /* Encode only */
06625    else if (rxplon && !txplon)
06626       cmdstr[0] = 0x3A; /* Encode only */
06627    else
06628       cmdstr[0] = 0x8A; /* OFF */
06629 
06630    cmdstr[4] = 0x0A; 
06631 
06632    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06633 }

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

Definition at line 7100 of file app_rpt.c.

References civ_cmd(), rpt::civaddr, and rpt::p.

Referenced by set_ic706().

07101 {
07102    unsigned char cmdstr[10];
07103    int rv;
07104 
07105    cmdstr[0] = cmdstr[1] = 0xfe;
07106    cmdstr[2] = myrpt->p.civaddr;
07107    cmdstr[3] = 0xe0;
07108    cmdstr[4] = 0x16;
07109    cmdstr[5] = 0x42;
07110    cmdstr[6] = (txplon != 0);
07111    cmdstr[7] = 0xfd;
07112 
07113    rv = civ_cmd(myrpt,cmdstr,8);
07114    if (rv) return(-1);
07115 
07116    cmdstr[0] = cmdstr[1] = 0xfe;
07117    cmdstr[2] = myrpt->p.civaddr;
07118    cmdstr[3] = 0xe0;
07119    cmdstr[4] = 0x16;
07120    cmdstr[5] = 0x43;
07121    cmdstr[6] = (rxplon != 0);
07122    cmdstr[7] = 0xfd;
07123 
07124    return(civ_cmd(myrpt,cmdstr,8));
07125 }

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

Definition at line 6507 of file app_rpt.c.

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

Referenced by multimode_bump_freq_ft897(), and set_ft897().

06508 {
06509    unsigned char cmdstr[5];
06510    int fd,m,d;
06511    char mhz[MAXREMSTR];
06512    char decimals[MAXREMSTR];
06513 
06514    fd = 0;
06515    if(debug) 
06516       printf("New frequency: %s\n",newfreq);
06517 
06518    if(split_freq(mhz, decimals, newfreq))
06519       return -1; 
06520 
06521    m = atoi(mhz);
06522    d = atoi(decimals);
06523 
06524    /* The FT-897 likes packed BCD frequencies */
06525 
06526    cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);        /* 100MHz 10Mhz */
06527    cmdstr[1] = ((m % 10) << 4) + (d / 10000);         /* 1MHz 100KHz */
06528    cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);  /* 10KHz 1KHz */
06529    cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);         /* 100Hz 10Hz */
06530    cmdstr[4] = 0x01;                /* command */
06531 
06532    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06533 
06534 }

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

Definition at line 7010 of file app_rpt.c.

References civ_cmd(), rpt::civaddr, MAXREMSTR, rpt::p, and split_freq().

Referenced by set_ic706().

07011 {
07012    unsigned char cmdstr[20];
07013    char mhz[MAXREMSTR], decimals[MAXREMSTR];
07014    int fd,m,d;
07015 
07016    fd = 0;
07017    if(debug) 
07018       printf("New frequency: %s\n",newfreq);
07019 
07020    if(split_freq(mhz, decimals, newfreq))
07021       return -1; 
07022 
07023    m = atoi(mhz);
07024    d = atoi(decimals);
07025 
07026    /* The ic-706 likes packed BCD frequencies */
07027 
07028    cmdstr[0] = cmdstr[1] = 0xfe;
07029    cmdstr[2] = myrpt->p.civaddr;
07030    cmdstr[3] = 0xe0;
07031    cmdstr[4] = 5;
07032    cmdstr[5] = ((d % 10) << 4);
07033    cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
07034    cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
07035    cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
07036    cmdstr[9] = (m / 100);
07037    cmdstr[10] = 0xfd;
07038 
07039    return(civ_cmd(myrpt,cmdstr,11));
07040 }

static int set_ft897 ( struct rpt myrpt  )  [static]

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

06674 {
06675    int res;
06676    
06677    if(debug)
06678       printf("@@@@ lock on\n");
06679 
06680    res = simple_command_ft897(myrpt, 0x00);  /* LOCK on */  
06681 
06682    if(debug)
06683       printf("@@@@ ptt off\n");
06684 
06685    if(!res)
06686       res = simple_command_ft897(myrpt, 0x88);     /* PTT off */
06687 
06688    if(debug)
06689       printf("Modulation mode\n");
06690 
06691    if(!res)
06692       res = set_mode_ft897(myrpt, myrpt->remmode);    /* Modulation mode */
06693 
06694    if(debug)
06695       printf("Split off\n");
06696 
06697    if(!res)
06698       simple_command_ft897(myrpt, 0x82);        /* Split off */
06699 
06700    if(debug)
06701       printf("Frequency\n");
06702 
06703    if(!res)
06704       res = set_freq_ft897(myrpt, myrpt->freq);    /* Frequency */
06705    if((myrpt->remmode == REM_MODE_FM)){
06706       if(debug)
06707          printf("Offset\n");
06708       if(!res)
06709          res = set_offset_ft897(myrpt, myrpt->offset);   /* Offset if FM */
06710       if((!res)&&(myrpt->rxplon || myrpt->txplon)){
06711          if(debug)
06712             printf("CTCSS tone freqs.\n");
06713          res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl); /* CTCSS freqs if CTCSS is enabled */
06714       }
06715       if(!res){
06716          if(debug)
06717             printf("CTCSS mode\n");
06718          res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */
06719       }
06720    }
06721    if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
06722       if(debug)
06723          printf("Clarifier off\n");
06724       simple_command_ft897(myrpt, 0x85);        /* Clarifier off if LSB or USB */
06725    }
06726    return res;
06727 }

static int set_ic706 ( struct rpt myrpt  )  [static]

Definition at line 7217 of file app_rpt.c.

References IC706_PL_MEMORY_OFFSET, ic706_pltocode(), mem2vfo_ic706(), REM_MODE_FM, rpt::remmode, rpt::rxpl, select_mem_ic706(), set_ctcss_mode_ic706(), set_freq_ic706(), set_mode_ic706(), set_offset_ic706(), simple_command_ic706(), and vfo_ic706().

Referenced by rpt_tele_thread().

07218 {
07219    int res = 0,i;
07220    
07221    if(debug)
07222       printf("Set to VFO A\n");
07223 
07224    if (!res)
07225       res = simple_command_ic706(myrpt,7,0);
07226 
07227 
07228    if((myrpt->remmode == REM_MODE_FM))
07229    {
07230       i = ic706_pltocode(myrpt->rxpl);
07231       if (i == -1) return -1;
07232       if(debug)
07233          printf("Select memory number\n");
07234       if (!res)
07235          res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
07236       if(debug)
07237          printf("Transfer memory to VFO\n");
07238       if (!res)
07239          res = mem2vfo_ic706(myrpt);
07240    }
07241       
07242    if(debug)
07243       printf("Set to VFO\n");
07244 
07245    if (!res)
07246       res = vfo_ic706(myrpt);
07247 
07248    if(debug)
07249       printf("Modulation mode\n");
07250 
07251    if (!res)
07252       res = set_mode_ic706(myrpt, myrpt->remmode);    /* Modulation mode */
07253 
07254    if(debug)
07255       printf("Split off\n");
07256 
07257    if(!res)
07258       simple_command_ic706(myrpt, 0x82,0);         /* Split off */
07259 
07260    if(debug)
07261       printf("Frequency\n");
07262 
07263    if(!res)
07264       res = set_freq_ic706(myrpt, myrpt->freq);    /* Frequency */
07265    if((myrpt->remmode == REM_MODE_FM)){
07266       if(debug)
07267          printf("Offset\n");
07268       if(!res)
07269          res = set_offset_ic706(myrpt, myrpt->offset);   /* Offset if FM */
07270       if(!res){
07271          if(debug)
07272             printf("CTCSS mode\n");
07273          res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */
07274       }
07275    }
07276    return res;
07277 }

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

Definition at line 6582 of file app_rpt.c.

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

Referenced by rpt_tele_thread(), and set_ft897().

06583 {
06584    unsigned char cmdstr[5];
06585    
06586    memset(cmdstr, 0, 5);
06587    
06588    switch(newmode){
06589       case  REM_MODE_FM:
06590          cmdstr[0] = 0x08;
06591          break;
06592 
06593       case  REM_MODE_USB:
06594          cmdstr[0] = 0x01;
06595          break;
06596 
06597       case  REM_MODE_LSB:
06598          cmdstr[0] = 0x00;
06599          break;
06600 
06601       case  REM_MODE_AM:
06602          cmdstr[0] = 0x04;
06603          break;
06604       
06605       default:
06606          return -1;
06607    }
06608    cmdstr[4] = 0x07; 
06609 
06610    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06611 }

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

Definition at line 7071 of file app_rpt.c.

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

Referenced by rpt_tele_thread(), and set_ic706().

07072 {
07073    unsigned char c;
07074    
07075    switch(newmode){
07076       case  REM_MODE_FM:
07077          c = 5;
07078          break;
07079 
07080       case  REM_MODE_USB:
07081          c = 1;
07082          break;
07083 
07084       case  REM_MODE_LSB:
07085          c = 0;
07086          break;
07087 
07088       case  REM_MODE_AM:
07089          c = 2;
07090          break;
07091       
07092       default:
07093          return -1;
07094    }
07095    return simple_command_ic706(myrpt,6,c);
07096 }

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

Definition at line 6552 of file app_rpt.c.

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

Referenced by set_ft897().

06553 {
06554    unsigned char cmdstr[5];
06555    
06556    memset(cmdstr, 0, 5);
06557 
06558    switch(offset){
06559       case  REM_SIMPLEX:
06560          cmdstr[0] = 0x89;
06561          break;
06562 
06563       case  REM_MINUS:
06564          cmdstr[0] = 0x09;
06565          break;
06566       
06567       case  REM_PLUS:
06568          cmdstr[0] = 0x49;
06569          break;   
06570 
06571       default:
06572          return -1;
06573    }
06574 
06575    cmdstr[4] = 0x09; 
06576 
06577    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06578 }

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

Definition at line 7044 of file app_rpt.c.

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

Referenced by set_ic706().

07045 {
07046    unsigned char c;
07047 
07048    switch(offset){
07049       case  REM_SIMPLEX:
07050          c = 0x10;
07051          break;
07052 
07053       case  REM_MINUS:
07054          c = 0x11;
07055          break;
07056       
07057       case  REM_PLUS:
07058          c = 0x12;
07059          break;   
07060 
07061       default:
07062          return -1;
07063    }
07064 
07065    return simple_command_ic706(myrpt,0x0f,c);
07066 
07067 }

static int setkenwood ( struct rpt myrpt  )  [static]

Definition at line 6094 of file app_rpt.c.

References rpt::freq, kenwood_pltocode(), MAXREMSTR, rpt::offset, offset, rpt::powerlevel, rpt::rxpl, rpt::rxplon, sendrxkenwood(), split_freq(), rpt::txpl, and rpt::txplon.

Referenced by rpt_tele_thread().

06095 {
06096 char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
06097 char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
06098    
06099 int offsets[] = {0,2,1};
06100 int powers[] = {2,1,0};
06101 
06102    if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
06103    split_freq(mhz, decimals, myrpt->freq);
06104    if (atoi(mhz) > 400)
06105    {
06106       band = '6';
06107       band1 = '1';
06108       band2 = '5';
06109       strcpy(offset,"005000000");
06110    }
06111    else
06112    {
06113       band = '2';
06114       band1 = '0';
06115       band2 = '2';
06116       strcpy(offset,"000600000");
06117    }
06118    strcpy(freq,"000000");
06119    strncpy(freq,decimals,strlen(decimals));
06120    sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
06121       band,atoi(mhz),freq,offsets[(int)myrpt->offset],
06122       (myrpt->txplon != 0),(myrpt->rxplon != 0),
06123       kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
06124       offset);
06125    if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
06126    sprintf(txstr,"RBN %c\r",band2);
06127    if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
06128    sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
06129    if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
06130    return 0;
06131 }

static int setrbi ( struct rpt myrpt  )  [static]

Definition at line 6133 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::rxpl, rpt::rxplon, s, setrbi_check(), and rpt::txplon.

Referenced by rpt_tele_thread().

06134 {
06135 char tmp[MAXREMSTR] = "",*s;
06136 unsigned char rbicmd[5];
06137 int   band,txoffset = 0,txpower = 0,rxpl;
06138 
06139    /* must be a remote system */
06140    if (!myrpt->remote) return(0);
06141    /* must have rbi hardware */
06142    if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0);
06143    if (setrbi_check(myrpt) == -1) return(-1);
06144    strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
06145    s = strchr(tmp,'.');
06146    /* if no decimal, is invalid */
06147    
06148    if (s == NULL){
06149       if(debug)
06150          printf("@@@@ Frequency needs a decimal\n");
06151       return -1;
06152    }
06153    
06154    *s++ = 0;
06155    if (strlen(tmp) < 2){
06156       if(debug)
06157          printf("@@@@ Bad MHz digits: %s\n", tmp);
06158       return -1;
06159    }
06160     
06161    if (strlen(s) < 3){
06162       if(debug)
06163          printf("@@@@ Bad KHz digits: %s\n", s);
06164       return -1;
06165    }
06166 
06167    if ((s[2] != '0') && (s[2] != '5')){
06168       if(debug)
06169          printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
06170       return -1;
06171    }
06172     
06173    band = rbi_mhztoband(tmp);
06174    if (band == -1){
06175       if(debug)
06176          printf("@@@@ Bad Band: %s\n", tmp);
06177       return -1;
06178    }
06179    
06180    rxpl = rbi_pltocode(myrpt->rxpl);
06181    
06182    if (rxpl == -1){
06183       if(debug)
06184          printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
06185       return -1;
06186    }
06187 
06188    
06189    switch(myrpt->offset)
06190    {
06191        case REM_MINUS:
06192       txoffset = 0;
06193       break;
06194        case REM_PLUS:
06195       txoffset = 0x10;
06196       break;
06197        case REM_SIMPLEX:
06198       txoffset = 0x20;
06199       break;
06200    }
06201    switch(myrpt->powerlevel)
06202    {
06203        case REM_LOWPWR:
06204       txpower = 0;
06205       break;
06206        case REM_MEDPWR:
06207       txpower = 0x20;
06208       break;
06209        case REM_HIPWR:
06210       txpower = 0x10;
06211       break;
06212    }
06213    rbicmd[0] = 0;
06214    rbicmd[1] = band | txpower | 0xc0;
06215    rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
06216    if (s[2] == '5') rbicmd[2] |= 0x40;
06217    rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
06218    rbicmd[4] = rxpl;
06219    if (myrpt->txplon) rbicmd[4] |= 0x40;
06220    if (myrpt->rxplon) rbicmd[4] |= 0x80;
06221    rbi_out(myrpt,rbicmd);
06222    return 0;
06223 }

static int setrbi_check ( struct rpt myrpt  )  [static]

Definition at line 6225 of file app_rpt.c.

References rpt::freq, MAXREMSTR, rbi_mhztoband(), rbi_pltocode(), rpt::remote, s, and rpt::txpl.

Referenced by setrbi(), and setrem().

06226 {
06227 char tmp[MAXREMSTR] = "",*s;
06228 int   band,txpl;
06229 
06230    /* must be a remote system */
06231    if (!myrpt->remote) return(0);
06232    /* must have rbi hardware */
06233    if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0);
06234    strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
06235    s = strchr(tmp,'.');
06236    /* if no decimal, is invalid */
06237    
06238    if (s == NULL){
06239       if(debug)
06240          printf("@@@@ Frequency needs a decimal\n");
06241       return -1;
06242    }
06243    
06244    *s++ = 0;
06245    if (strlen(tmp) < 2){
06246       if(debug)
06247          printf("@@@@ Bad MHz digits: %s\n", tmp);
06248       return -1;
06249    }
06250     
06251    if (strlen(s) < 3){
06252       if(debug)
06253          printf("@@@@ Bad KHz digits: %s\n", s);
06254       return -1;
06255    }
06256 
06257    if ((s[2] != '0') && (s[2] != '5')){
06258       if(debug)
06259          printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
06260       return -1;
06261    }
06262     
06263    band = rbi_mhztoband(tmp);
06264    if (band == -1){
06265       if(debug)
06266          printf("@@@@ Bad Band: %s\n", tmp);
06267       return -1;
06268    }
06269    
06270    txpl = rbi_pltocode(myrpt->txpl);
06271    
06272    if (txpl == -1){
06273       if(debug)
06274          printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
06275       return -1;
06276    }
06277    return 0;
06278 }

static int setrem ( struct rpt myrpt  )  [static]

Definition at line 7343 of file app_rpt.c.

References rpt::archivedir, ast_log(), donodelog(), rpt::freq, LOG_ERROR, modes, rpt::name, rpt::offset, rpt::p, rpt::powerlevel, rpt::remmode, rpt::remote, rpt_telemetry(), rpt::rxpl, rpt::rxplon, setrbi_check(), SETREMOTE, rpt::txpl, and rpt::txplon.

Referenced by function_remote().

07344 {
07345 char  str[300];
07346 char  *offsets[] = {"MINUS","SIMPLEX","PLUS"};
07347 char  *powerlevels[] = {"LOW","MEDIUM","HIGH"};
07348 char  *modes[] = {"FM","USB","LSB","AM"};
07349 int   res = -1;
07350 
07351    if (myrpt->p.archivedir)
07352    {
07353       sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
07354          modes[(int)myrpt->remmode],
07355          myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
07356          powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
07357          myrpt->rxplon);
07358       donodelog(myrpt,str);
07359    }
07360    if(!strcmp(myrpt->remote, remote_rig_ft897))
07361    {
07362       rpt_telemetry(myrpt,SETREMOTE,NULL);
07363       res = 0;
07364    }
07365    if(!strcmp(myrpt->remote, remote_rig_ic706))
07366    {
07367       rpt_telemetry(myrpt,SETREMOTE,NULL);
07368       res = 0;
07369    }
07370    else if(!strcmp(myrpt->remote, remote_rig_rbi))
07371    {
07372       res = setrbi_check(myrpt);
07373       if (!res)
07374       {
07375          rpt_telemetry(myrpt,SETREMOTE,NULL);
07376          res = 0;
07377       }
07378    }
07379    else if(!strcmp(myrpt->remote, remote_rig_kenwood)) {
07380       rpt_telemetry(myrpt,SETREMOTE,NULL);
07381       res = 0;
07382    }
07383    else
07384       res = 0;
07385 
07386    if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
07387 
07388    return res;
07389 }

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

Definition at line 6538 of file app_rpt.c.

References serial_remote_io().

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

06539 {
06540    unsigned char cmdstr[5];
06541    
06542    memset(cmdstr, 0, 5);
06543 
06544    cmdstr[4] = command; 
06545 
06546    return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
06547 
06548 }

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

Definition at line 6992 of file app_rpt.c.

References civ_cmd(), rpt::civaddr, and rpt::p.

Referenced by set_ic706(), set_mode_ic706(), and set_offset_ic706().

06993 {
06994    unsigned char cmdstr[10];
06995    
06996    cmdstr[0] = cmdstr[1] = 0xfe;
06997    cmdstr[2] = myrpt->p.civaddr;
06998    cmdstr[3] = 0xe0;
06999    cmdstr[4] = command;
07000    cmdstr[5] = subcommand;
07001    cmdstr[6] = 0xfd;
07002 
07003    return(civ_cmd(myrpt,cmdstr,7));
07004 }

static char* skipchars ( char *  string,
char *  charlist 
) [static]

Definition at line 1500 of file app_rpt.c.

Referenced by function_autopatchup().

01501 {
01502 int i;   
01503    while(*string){
01504       for(i = 0; charlist[i] ; i++){
01505          if(*string == charlist[i]){
01506             string++;
01507             break;
01508          }
01509       }
01510       if(!charlist[i])
01511          return string;
01512    }
01513    return string;
01514 }  

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

Definition at line 6391 of file app_rpt.c.

References MAXREMSTR.

Referenced by set_ctcss_freq_ft897().

06392 {
06393    char freq_copy[MAXREMSTR];
06394    char *decp;
06395 
06396    decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
06397    if(decp){
06398       *decp++ = 0;
06399       strncpy(hertz, freq_copy, MAXREMSTR);
06400       strncpy(decimal, decp, strlen(decp));
06401       decimal[strlen(decp)] = '\0';
06402       return 0;
06403    }
06404    else
06405       return -1;
06406 }

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

Definition at line 6368 of file app_rpt.c.

References MAXREMSTR.

Referenced by check_tx_freq(), function_remote(), multimode_bump_freq_ft897(), multimode_bump_freq_ic706(), rpt_tele_thread(), service_scan(), set_freq_ft897(), set_freq_ic706(), and setkenwood().

06369 {
06370    char freq_copy[MAXREMSTR];
06371    char *decp;
06372 
06373    decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
06374    if(decp){
06375       *decp++ = 0;
06376       strncpy(mhz, freq_copy, MAXREMSTR);
06377       strcpy(decimals, "00000");
06378       strncpy(decimals, decp, strlen(decp));
06379       decimals[5] = 0;
06380       return 0;
06381    }
06382    else
06383       return -1;
06384 
06385 }

static void stop_scan ( struct rpt myrpt  )  [static]

Definition at line 7567 of file app_rpt.c.

References rpt::hfscanstop, rpt_telemetry(), and SCAN.

Referenced by handle_remote_dtmf_digit().

07568 {
07569    myrpt->hfscanstop = 1;
07570    rpt_telemetry(myrpt,SCAN,0);
07571 }

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

Definition at line 2714 of file app_rpt.c.

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

Referenced by rpt_tele_thread(), and telem_lookup().

02715 {
02716    int res;
02717    char c;
02718    
02719    static int morsespeed;
02720    static int morsefreq;
02721    static int morseampl;
02722    static int morseidfreq = 0;
02723    static int morseidampl;
02724    static char mcat[] = MORSE;
02725    
02726    res = 0;
02727    
02728    if(!morseidfreq){ /* Get the morse parameters if not already loaded */
02729       morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
02730          morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
02731          morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
02732       morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
02733       morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330); 
02734    }
02735    
02736    /* Is it a file, or a tone sequence? */
02737          
02738    if(entry[0] == '|'){
02739       c = entry[1];
02740       if((c >= 'a')&&(c <= 'z'))
02741          c -= 0x20;
02742    
02743       switch(c){
02744          case 'I': /* Morse ID */
02745             res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
02746             break;
02747          
02748          case 'M': /* Morse Message */
02749             res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
02750             break;
02751          
02752          case 'T': /* Tone sequence */
02753             res = send_tone_telemetry(chan, entry + 2);
02754             break;
02755          default:
02756             res = -1;
02757       }
02758    }
02759    else
02760       res = sayfile(chan, entry); /* File */
02761    return res;
02762 }

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

Definition at line 2770 of file app_rpt.c.

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

Referenced by rpt_tele_thread().

02771 {
02772    
02773    int res;
02774    int i;
02775    char *entry;
02776    char *telemetry;
02777    char *telemetry_save;
02778 
02779    res = 0;
02780    telemetry_save = NULL;
02781    entry = NULL;
02782    
02783    /* Retrieve the section name for telemetry from the node section */
02784    telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
02785    if(telemetry ){
02786       telemetry_save = ast_strdupa(telemetry);
02787       if(!telemetry_save){
02788          ast_log(LOG_WARNING,"ast_strdupa() failed in telem_lookup()\n");
02789          return res;
02790       }
02791       entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
02792    }
02793    
02794    /* Try to look up the telemetry name */   
02795 
02796    if(!entry){
02797       /* Telemetry name wasn't found in the config file, use the default */
02798       for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
02799          if(!strcasecmp(tele_defs[i].name, name))
02800             entry = tele_defs[i].value;
02801       }
02802    }
02803    if(entry){  
02804       if(strlen(entry))
02805          telem_any(myrpt,chan, entry);
02806    }
02807    else{
02808       res = -1;
02809    }
02810    return res;
02811 }

static int unload_module ( void   )  [static]

Definition at line 11842 of file app_rpt.c.

References ast_cli_unregister(), ast_mutex_destroy(), ast_unregister_application(), cli_debug, cli_dump, cli_fun, cli_lstats, cli_nodes, cli_reload, cli_restart, cli_stats, lock, name, rpt::nodes, and rpt_vars.

11844 {
11845    int i;
11846 
11847 #ifdef   OLD_ASTERISK
11848    STANDARD_HANGUP_LOCALUSERS;
11849 #endif
11850    for(i = 0; i < nrpts; i++) {
11851       if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
11852                 ast_mutex_destroy(&rpt_vars[i].lock);
11853                 ast_mutex_destroy(&rpt_vars[i].remlock);
11854    }
11855    i = ast_unregister_application(app);
11856 
11857    /* Unregister cli extensions */
11858    ast_cli_unregister(&cli_debug);
11859    ast_cli_unregister(&cli_dump);
11860    ast_cli_unregister(&cli_stats);
11861    ast_cli_unregister(&cli_lstats);
11862    ast_cli_unregister(&cli_nodes);
11863    ast_cli_unregister(&cli_reload);
11864    ast_cli_unregister(&cli_restart);
11865    ast_cli_unregister(&cli_fun);
11866 
11867    return i;
11868 }

static int vfo_ic706 ( struct rpt myrpt  )  [static]

Definition at line 7176 of file app_rpt.c.

References civ_cmd(), rpt::civaddr, and rpt::p.

Referenced by set_ic706().

07177 {
07178    unsigned char cmdstr[10];
07179    
07180    cmdstr[0] = cmdstr[1] = 0xfe;
07181    cmdstr[2] = myrpt->p.civaddr;
07182    cmdstr[3] = 0xe0;
07183    cmdstr[4] = 7;
07184    cmdstr[5] = 0xfd;
07185 
07186    return(civ_cmd(myrpt,cmdstr,6));
07187 }

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

Definition at line 2889 of file app_rpt.c.

References ast_log(), ast_safe_sleep(), get_wait_interval(), and LOG_NOTICE.

Referenced by rpt_tele_thread().

02890 {
02891    int interval;
02892    interval = get_wait_interval(myrpt, type);
02893    if(debug)
02894       ast_log(LOG_NOTICE," Delay interval = %d\n", interval);
02895    if(interval)
02896       ast_safe_sleep(chan,interval);
02897    if(debug)
02898       ast_log(LOG_NOTICE,"Delay complete\n");
02899    return;
02900 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Radio Repeater/Remote Base Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 11927 of file app_rpt.c.

char* app = "Rpt" [static]

Definition at line 313 of file app_rpt.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 11927 of file app_rpt.c.

struct ast_cli_entry cli_debug [static]

Initial value:

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

Definition at line 934 of file app_rpt.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_dump [static]

Initial value:

        { { "rpt", "dump" }, rpt_do_dump,
      "Dump app_rpt structs for debugging", dump_usage }

Definition at line 938 of file app_rpt.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_fun [static]

Initial value:

        { { "rpt", "fun" }, rpt_do_fun,
      "Execute a DTMF function", fun_usage }

Definition at line 962 of file app_rpt.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_lstats [static]

Initial value:

        { { "rpt", "lstats" }, rpt_do_lstats,
      "Dump link statistics", dump_lstats }

Definition at line 950 of file app_rpt.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_nodes [static]

Initial value:

        { { "rpt", "nodes" }, rpt_do_nodes,
      "Dump node list", dump_nodes }

Definition at line 946 of file app_rpt.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_reload [static]

Initial value:

        { { "rpt", "reload" }, rpt_do_reload,
      "Reload app_rpt config", reload_usage }

Definition at line 954 of file app_rpt.c.

struct ast_cli_entry cli_restart [static]

Initial value:

        { { "rpt", "restart" }, rpt_do_restart,
      "Restart app_rpt", restart_usage }

Definition at line 958 of file app_rpt.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_stats [static]

Initial value:

        { { "rpt", "stats" }, rpt_do_stats,
      "Dump node statistics", dump_stats }

Definition at line 942 of file app_rpt.c.

Referenced by load_module(), and unload_module().

int debug = 0 [static]

Definition at line 352 of file app_rpt.c.

Referenced by add_sdp(), add_t38_sdp(), aji_load_config(), check_user_full(), handle_pri_show_debug(), handle_request(), process_sdp(), set_destination(), and sip_sendtext().

char debug_usage[] [static]

Initial value:

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

Definition at line 901 of file app_rpt.c.

char* descrip [static]

Definition at line 317 of file app_rpt.c.

char* discstr = "!!DISCONNECT!!"

Definition at line 372 of file app_rpt.c.

char dump_lstats[] [static]

Initial value:

"Usage: rpt lstats <nodename>\n"
"       Dumps link statistics to console\n"

Definition at line 913 of file app_rpt.c.

char dump_nodes[] [static]

Initial value:

"Usage: rpt nodes <nodename>\n"
"       Dumps a list of directly and indirectly connected nodes to the console\n"

Definition at line 917 of file app_rpt.c.

char dump_stats[] [static]

Initial value:

"Usage: rpt stats <nodename>\n"
"       Dumps node statistics to console\n"

Definition at line 909 of file app_rpt.c.

char dump_usage[] [static]

Initial value:

"Usage: rpt dump <nodename>\n"
"       Dumps struct debug info to log\n"

Definition at line 905 of file app_rpt.c.

char fun_usage[] [static]

Initial value:

"Usage: rpt fun <nodename> <command>\n"
"       Send a DTMF function to a node\n"

Definition at line 929 of file app_rpt.c.

struct function_table_tag function_table[] [static]

Definition at line 1013 of file app_rpt.c.

Referenced by collect_function_digits().

int max_chan_stat[] = {22000,1000,22000,100,22000,2000,22000}

Definition at line 359 of file app_rpt.c.

ast_mutex_t nodeloglock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 687 of file app_rpt.c.

Referenced by donodelog(), and rpt_master().

ast_mutex_t nodelookuplock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 689 of file app_rpt.c.

Referenced by node_lookup().

int nrpts = 0 [static]

Definition at line 353 of file app_rpt.c.

char reload_usage[] [static]

Initial value:

"Usage: rpt reload\n"
"       Reloads app_rpt running config parameters\n"

Definition at line 921 of file app_rpt.c.

char remdtmfstr[] = "0123456789*#ABCD" [static]

Definition at line 355 of file app_rpt.c.

char* remote_rig_ft897 = "ft897" [static]

Definition at line 373 of file app_rpt.c.

char* remote_rig_ic706 = "ic706" [static]

Definition at line 376 of file app_rpt.c.

char* remote_rig_kenwood = "kenwood" [static]

Definition at line 375 of file app_rpt.c.

char* remote_rig_rbi = "rbi" [static]

Definition at line 374 of file app_rpt.c.

char restart_usage[] [static]

Initial value:

"Usage: rpt restart\n"
"       Restarts app_rpt\n"

Definition at line 925 of file app_rpt.c.

pthread_t rpt_master_thread [static]

Definition at line 409 of file app_rpt.c.

struct rpt rpt_vars[MAXRPTS] [static]

Referenced by load_rpt_vars(), reload(), rpt(), rpt_do_dump(), rpt_do_fun(), rpt_do_lstats(), rpt_do_nodes(), rpt_do_reload(), rpt_do_restart(), rpt_do_stats(), rpt_exec(), rpt_master(), and unload_module().

time_t starttime = 0 [static]

Definition at line 407 of file app_rpt.c.

Referenced by tzparse(), and wait_for_answer().

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

Definition at line 315 of file app_rpt.c.

char* tdesc = "Radio Repeater / Remote Base version 0.73 09/04/2007" [static]

Definition at line 311 of file app_rpt.c.

struct telem_defaults tele_defs[] [static]

Definition at line 971 of file app_rpt.c.

Referenced by telem_lookup().


Generated on Thu Feb 5 16:25:56 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7