#include "asterisk.h"
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <search.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/io.h>
#include <math.h>
#include <tonezone.h>
#include <linux/zaptel.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/callerid.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/features.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/localtime.h"
Include dependency graph for app_rpt.c:
Go to the source code of this file.
Data Structures | |
struct | function_table_tag |
struct | morse_bits |
struct | rpt |
struct | rpt_link |
struct | rpt_tele |
struct | telem_defaults |
Defines | |
#define | ACTIONSIZE 32 |
#define | DEFAULT_IOBASE 0x378 |
#define | DISC_TIME 10000 |
#define | DTMF_TIMEOUT 3 |
#define | ENDCHAR '#' |
#define | FUNCCHAR '*' |
#define | FUNCTDELAY 1500 |
#define | FUNCTIONS "functions" |
#define | HANGTIME 5000 |
#define | IDTIME 300000 |
#define | MAX_RETRIES 5 |
#define | MAXCONNECTTIME 5000 |
#define | MAXDTMF 32 |
#define | MAXNODESTR 300 |
#define | MAXREMSTR 15 |
#define | MAXRPTS 20 |
#define | MEMORY "memory" |
#define | MORSE "morse" |
#define | MSWAIT 200 |
#define | NODES "nodes" |
#define | POLITEID 30000 |
#define | RECONNECT_KLUDGE |
#define | REDUNDANT_TX_TIME 2000 |
#define | REM_SCANTIME 100 |
#define | RETRY_TIMER_MS 5000 |
#define | TELEMETRY "telemetry" |
#define | TELEPARAMSIZE 256 |
#define | TOTIME 180000 |
Enumerations | |
enum | { REM_OFF, REM_MONITOR, REM_TX } |
enum | { ID, PROC, TERM, COMPLETE, UNKEY, REMDISC, REMALREADY, REMNOTFOUND, REMGO, CONNECTED, CONNFAIL, STATUS, TIMEOUT, ID1, STATS_TIME, STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH } |
enum | { REM_SIMPLEX, REM_MINUS, REM_PLUS } |
enum | { REM_LOWPWR, REM_MEDPWR, REM_HIPWR } |
enum | { DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_DOKEY } |
enum | { SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE } |
enum | { DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM } |
enum | { REM_MODE_FM, REM_MODE_USB, REM_MODE_LSB, REM_MODE_AM } |
enum | { HF_SCAN_OFF, HF_SCAN_DOWN_SLOW, HF_SCAN_DOWN_QUICK, HF_SCAN_DOWN_FAST, HF_SCAN_UP_SLOW, HF_SCAN_UP_QUICK, HF_SCAN_UP_FAST } |
Functions | |
static int | attempt_reconnect (struct rpt *myrpt, struct rpt_link *l) |
static int | check_freq (struct rpt *myrpt, int m, int d, int *defmode) |
static int | check_freq_ft897 (int m, int d, int *defmode) |
static int | check_freq_rbi (int m, int d, int *defmode) |
static int | closerem (struct rpt *myrpt) |
static int | closerem_ft897 (struct rpt *myrpt) |
static int | collect_function_digits (struct rpt *myrpt, char *digits, int command_source, struct rpt_link *mylink) |
char * | description (void) |
Provides a description of the module. | |
static int | function_autopatchdn (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | function_autopatchup (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | function_cop (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | function_ilink (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | function_remote (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | function_status (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | get_wait_interval (struct rpt *myrpt, int type) |
static void | handle_link_data (struct rpt *myrpt, struct rpt_link *mylink, char *str) |
static void | handle_link_phone_dtmf (struct rpt *myrpt, struct rpt_link *mylink, char c) |
static int | handle_remote_data (struct rpt *myrpt, char *str) |
static int | handle_remote_dtmf_digit (struct rpt *myrpt, char c, char *keyed, int phonemode) |
static int | handle_remote_phone_dtmf (struct rpt *myrpt, char c, char *keyed, int phonemode) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
static int | multimode_bump_freq (struct rpt *myrpt, int interval) |
static int | multimode_bump_freq_ft897 (struct rpt *myrpt, int interval) |
static int | multimode_capable (struct rpt *myrpt) |
static int | myatoi (char *str) |
static int | play_silence (struct ast_channel *chan, int duration) |
static int | play_tone (struct ast_channel *chan, int freq, int duration, int amplitude) |
static int | play_tone_pair (struct ast_channel *chan, int f1, int f2, int duration, int amplitude) |
static int | rbi_mhztoband (char *str) |
static void | rbi_out (struct rpt *myrpt, unsigned char *data) |
static void | rbi_out_parallel (struct rpt *myrpt, unsigned char *data) |
static int | rbi_pltocode (char *str) |
static int | retrieve_astcfgint (char *category, char *name, int min, int max, int defl) |
static int | rmt_saycharstr (struct rpt *myrpt, struct ast_channel *chan, int delay, char *charstr) |
static int | rmt_sayfile (struct rpt *myrpt, struct ast_channel *chan, int delay, char *filename) |
static int | rmt_telem_finish (struct rpt *myrpt, struct ast_channel *chan) |
static int | rmt_telem_start (struct rpt *myrpt, struct ast_channel *chan, int delay) |
static void * | rpt (void *this) |
static void * | rpt_call (void *this) |
static int | rpt_do_debug (int fd, int argc, char *argv[]) |
static int | rpt_exec (struct ast_channel *chan, void *data) |
static void * | rpt_master (void *ignore) |
static void * | rpt_tele_thread (void *this) |
static void | rpt_telemetry (struct rpt *myrpt, int mode, void *data) |
static int | saycharstr (struct ast_channel *mychannel, char *str) |
static int | sayfile (struct ast_channel *mychannel, char *fname) |
static int | saynum (struct ast_channel *mychannel, int num) |
static void | send_link_dtmf (struct rpt *myrpt, char c) |
static int | send_morse (struct ast_channel *chan, char *string, int speed, int freq, int amplitude) |
static int | send_tone_telemetry (struct ast_channel *chan, char *tonestring) |
static int | serial_remote_io (struct rpt *myrpt, char *txbuf, int txbytes, char *rxbuf, int rxmaxbytes, int asciiflag) |
static int | service_scan (struct rpt *myrpt) |
static int | set_ctcss_freq_ft897 (struct rpt *myrpt, char *txtone, char *rxtone) |
static int | set_ctcss_mode_ft897 (struct rpt *myrpt, char txplon, char rxplon) |
static int | set_freq_ft897 (struct rpt *myrpt, char *newfreq) |
static int | set_ft897 (struct rpt *myrpt) |
static int | set_mode_ft897 (struct rpt *myrpt, char newmode) |
static int | set_offset_ft897 (struct rpt *myrpt, char offset) |
static int | setrbi (struct rpt *myrpt) |
static int | setrem (struct rpt *myrpt) |
static int | simple_command_ft897 (struct rpt *myrpt, char command) |
static int | split_ctcss_freq (char *hertz, char *decimal, char *freq) |
static int | split_freq (char *mhz, char *decimals, char *freq) |
static void | stop_scan (struct rpt *myrpt, int flag) |
static int | telem_any (struct ast_channel *chan, char *entry) |
static int | telem_lookup (struct ast_channel *chan, char *node, char *name) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
static void | wait_interval (struct rpt *myrpt, int type, struct ast_channel *chan) |
Variables | |
static char * | app = "Rpt" |
ast_config * | cfg |
static struct ast_cli_entry | cli_debug |
static int | debug = 0 |
static char | debug_usage [] |
static char * | descrip |
char * | discstr = "!!DISCONNECT!!" |
static struct function_table_tag | function_table [] |
LOCAL_USER_DECL | |
static int | nrpts = 0 |
static char * | remote_rig_ft897 = "ft897" |
static char * | remote_rig_rbi = "rbi" |
static pthread_t | rpt_master_thread |
static struct rpt | rpt_vars [MAXRPTS] |
STANDARD_LOCAL_USER | |
static char * | synopsis = "Radio Repeater/Remote Base Control System" |
static char * | tdesc = "Radio Repeater / Remote Base version 0.37 11/03/2005" |
static struct telem_defaults | tele_defs [] |
#define DEFAULT_IOBASE 0x378 |
#define DTMF_TIMEOUT 3 |
#define ENDCHAR '#' |
#define FUNCCHAR '*' |
#define FUNCTIONS "functions" |
#define HANGTIME 5000 |
#define IDTIME 300000 |
#define MAX_RETRIES 5 |
Definition at line 109 of file app_rpt.c.
Referenced by function_ilink(), handle_link_data(), rpt(), and rpt_exec().
#define MAXDTMF 32 |
Definition at line 105 of file app_rpt.c.
Referenced by handle_link_data(), handle_link_phone_dtmf(), handle_remote_dtmf_digit(), and rpt().
#define MAXNODESTR 300 |
#define MAXREMSTR 15 |
Definition at line 115 of file app_rpt.c.
Referenced by function_remote(), multimode_bump_freq_ft897(), service_scan(), set_ctcss_freq_ft897(), set_freq_ft897(), setrbi(), split_ctcss_freq(), and split_freq().
#define MEMORY "memory" |
#define MORSE "morse" |
#define MSWAIT 200 |
#define NODES "nodes" |
#define POLITEID 30000 |
#define REDUNDANT_TX_TIME 2000 |
#define REM_SCANTIME 100 |
#define TELEMETRY "telemetry" |
#define TELEPARAMSIZE 256 |
#define TOTIME 180000 |
anonymous enum |
anonymous 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 |
Definition at line 140 of file app_rpt.c.
00140 {ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO, 00141 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, 00142 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH};
anonymous enum |
anonymous enum |
anonymous enum |
Definition at line 148 of file app_rpt.c.
00148 {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_DOKEY};
anonymous enum |
Definition at line 150 of file app_rpt.c.
00150 {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE};
anonymous enum |
anonymous enum |
anonymous 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 |
Definition at line 156 of file app_rpt.c.
00156 {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 4467 of file app_rpt.c.
References ast_call(), AST_FORMAT_SLINEAR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_set_read_format(), ast_set_write_format(), ast_variable_retrieve(), ast_verbose(), cfg, free, rpt::links, rpt::lock, LOG_NOTICE, rpt::name, rpt_link::name, rpt_link::next, rpt::nodes, option_verbose, s, strdup, strsep(), and VERBOSE_PREFIX_3.
Referenced by rpt().
04468 { 04469 char *val, *s, *s1, *s2, *tele; 04470 char tmp[300], deststr[300] = ""; 04471 04472 val = ast_variable_retrieve(cfg, myrpt->nodes, l->name); 04473 if (!val) 04474 { 04475 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name); 04476 return -1; 04477 } 04478 04479 ast_mutex_lock(&myrpt->lock); 04480 /* remove from queue */ 04481 remque((struct qelem *) l); 04482 ast_mutex_unlock(&myrpt->lock); 04483 strncpy(tmp,val,sizeof(tmp) - 1); 04484 s = tmp; 04485 s1 = strsep(&s,","); 04486 s2 = strsep(&s,","); 04487 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1); 04488 tele = strchr(deststr, '/'); 04489 if (!tele) { 04490 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr); 04491 return -1; 04492 } 04493 *tele++ = 0; 04494 l->elaptime = 0; 04495 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL); 04496 if (l->chan){ 04497 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR); 04498 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR); 04499 l->chan->whentohangup = 0; 04500 l->chan->appl = "Apprpt"; 04501 l->chan->data = "(Remote Rx)"; 04502 if (option_verbose > 2) 04503 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n", 04504 deststr, tele, l->chan->name); 04505 if(l->chan->cid.cid_num) 04506 free(l->chan->cid.cid_num); 04507 l->chan->cid.cid_num = strdup(myrpt->name); 04508 ast_call(l->chan,tele,999); 04509 04510 } 04511 else 04512 { 04513 if (option_verbose > 2) 04514 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n", 04515 deststr,tele,l->chan->name); 04516 return -1; 04517 } 04518 ast_mutex_lock(&myrpt->lock); 04519 /* put back in queue queue */ 04520 insque((struct qelem *)l,(struct qelem *)myrpt->links.next); 04521 ast_mutex_unlock(&myrpt->lock); 04522 ast_log(LOG_NOTICE,"Reconnect Attempt to %s in process\n",l->name); 04523 return 0; 04524 }
static int check_freq | ( | struct rpt * | myrpt, | |
int | m, | |||
int | d, | |||
int * | defmode | |||
) | [static] |
Definition at line 3436 of file app_rpt.c.
References check_freq_ft897(), check_freq_rbi(), and rpt::remote.
Referenced by function_remote().
03437 { 03438 if(!strcmp(myrpt->remote, remote_rig_ft897)) 03439 return check_freq_ft897(m, d, defmode); 03440 else if(!strcmp(myrpt->remote, remote_rig_rbi)) 03441 return check_freq_rbi(m, d, defmode); 03442 else 03443 return -1; 03444 }
static int check_freq_ft897 | ( | int | m, | |
int | d, | |||
int * | defmode | |||
) | [static] |
Definition at line 3041 of file app_rpt.c.
References REM_MODE_FM, REM_MODE_LSB, and REM_MODE_USB.
Referenced by check_freq(), and multimode_bump_freq_ft897().
03042 { 03043 int dflmd = REM_MODE_FM; 03044 03045 if(m == 1){ /* 160 meters */ 03046 dflmd = REM_MODE_LSB; 03047 if(d < 80001) 03048 return -1; 03049 } 03050 else if(m == 3){ /* 80 meters */ 03051 dflmd = REM_MODE_LSB; 03052 if(d < 75001) 03053 return -1; 03054 } 03055 else if(m == 7){ /* 40 meters */ 03056 dflmd = REM_MODE_LSB; 03057 if((d < 15001) || (d > 29999)) 03058 return -1; 03059 } 03060 else if(m == 14){ /* 20 meters */ 03061 dflmd = REM_MODE_USB; 03062 if((d < 15001) || (d > 34999)) 03063 return -1; 03064 } 03065 else if(m == 18){ /* 17 meters */ 03066 dflmd = REM_MODE_USB; 03067 if((d < 11001) || (d > 16797)) 03068 return -1; 03069 } 03070 else if(m == 21){ /* 15 meters */ 03071 dflmd = REM_MODE_USB; 03072 if((d < 20001) || (d > 44999)) 03073 return -1; 03074 } 03075 else if(m == 24){ /* 12 meters */ 03076 dflmd = REM_MODE_USB; 03077 if((d < 93001) || (d > 98999)) 03078 return -1; 03079 } 03080 else if(m == 28){ /* 10 meters */ 03081 dflmd = REM_MODE_USB; 03082 if(d < 30001) 03083 return -1; 03084 } 03085 else if(m == 29){ 03086 if(d >= 51000) 03087 dflmd = REM_MODE_FM; 03088 else 03089 dflmd = REM_MODE_USB; 03090 if(d > 69999) 03091 return -1; 03092 } 03093 else if(m == 50){ /* 6 meters */ 03094 if(d < 10100) 03095 return -1; 03096 if(d >= 30000) 03097 dflmd = REM_MODE_FM; 03098 else 03099 dflmd = REM_MODE_USB; 03100 03101 } 03102 else if((m >= 51) && ( m < 54)){ 03103 dflmd = REM_MODE_FM; 03104 } 03105 else if(m == 144){ /* 2 meters */ 03106 if(d < 10100) 03107 return -1; 03108 if(d >= 30000) 03109 dflmd = REM_MODE_FM; 03110 else 03111 dflmd = REM_MODE_USB; 03112 } 03113 else if((m >= 145) && (m < 148)){ 03114 dflmd = REM_MODE_FM; 03115 } 03116 else if((m >= 430) && (m < 450)){ /* 70 centimeters */ 03117 if(m < 438) 03118 dflmd = REM_MODE_USB; 03119 else 03120 dflmd = REM_MODE_FM; 03121 ; 03122 } 03123 else 03124 return -1; 03125 03126 if(defmode) 03127 *defmode = dflmd; 03128 03129 return 0; 03130 }
static int check_freq_rbi | ( | int | m, | |
int | d, | |||
int * | defmode | |||
) | [static] |
Definition at line 2950 of file app_rpt.c.
References REM_MODE_FM.
Referenced by check_freq().
02951 { 02952 int dflmd = REM_MODE_FM; 02953 02954 if(m == 50){ /* 6 meters */ 02955 if(d < 10100) 02956 return -1; 02957 } 02958 else if((m >= 51) && ( m < 54)){ 02959 ; 02960 } 02961 else if(m == 144){ /* 2 meters */ 02962 if(d < 10100) 02963 return -1; 02964 } 02965 else if((m >= 145) && (m < 148)){ 02966 ; 02967 } 02968 else if((m >= 222) && (m < 225)){ /* 1.25 meters */ 02969 ; 02970 } 02971 else if((m >= 430) && (m < 450)){ /* 70 centimeters */ 02972 ; 02973 } 02974 else if((m >= 1240) && (m < 1300)){ /* 23 centimeters */ 02975 ; 02976 } 02977 else 02978 return -1; 02979 02980 if(defmode) 02981 *defmode = dflmd; 02982 02983 02984 return 0; 02985 }
static int closerem | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 3424 of file app_rpt.c.
References closerem_ft897(), and rpt::remote.
03425 { 03426 if(!strcmp(myrpt->remote, remote_rig_ft897)) 03427 return closerem_ft897(myrpt); 03428 else 03429 return 0; 03430 }
static int closerem_ft897 | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 3358 of file app_rpt.c.
References simple_command_ft897().
Referenced by closerem().
03359 { 03360 simple_command_ft897(myrpt, 0x88); /* PTT off */ 03361 return 0; 03362 }
static int collect_function_digits | ( | struct rpt * | myrpt, | |
char * | digits, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 2260 of file app_rpt.c.
References ast_variable_browse(), cfg, DC_ERROR, DC_INDETERMINATE, rpt::dphone_functions, rpt::dphone_longestfunc, function_table, rpt::functions, rpt::link_functions, rpt::link_longestfunc, rpt::longestfunc, n, ast_variable::name, ast_variable::next, rpt::phone_functions, rpt::phone_longestfunc, SOURCE_DPHONE, SOURCE_LNK, SOURCE_PHONE, strsep(), and ast_variable::value.
Referenced by handle_link_data(), handle_link_phone_dtmf(), handle_remote_dtmf_digit(), and rpt().
02262 { 02263 int i; 02264 char *stringp,*action,*param,*functiondigits; 02265 char function_table_name[30] = ""; 02266 char workstring[80]; 02267 02268 struct ast_variable *vp; 02269 02270 if(debug) 02271 printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source); 02272 02273 if (command_source == SOURCE_DPHONE) { 02274 if (!myrpt->dphone_functions) return DC_INDETERMINATE; 02275 strncpy(function_table_name, myrpt->dphone_functions, sizeof(function_table_name) - 1); 02276 } 02277 else if (command_source == SOURCE_PHONE) { 02278 if (!myrpt->phone_functions) return DC_INDETERMINATE; 02279 strncpy(function_table_name, myrpt->phone_functions, sizeof(function_table_name) - 1); 02280 } 02281 else if (command_source == SOURCE_LNK) 02282 strncpy(function_table_name, myrpt->link_functions, sizeof(function_table_name) - 1); 02283 else 02284 strncpy(function_table_name, myrpt->functions, sizeof(function_table_name) - 1); 02285 vp = ast_variable_browse(cfg, function_table_name); 02286 while(vp) { 02287 if(!strncasecmp(vp->name, digits, strlen(vp->name))) 02288 break; 02289 vp = vp->next; 02290 } 02291 if(!vp) { 02292 int n; 02293 02294 n = myrpt->longestfunc; 02295 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc; 02296 else 02297 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc; 02298 else 02299 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc; 02300 02301 if(strlen(digits) >= n) 02302 return DC_ERROR; 02303 else 02304 return DC_INDETERMINATE; 02305 } 02306 /* Found a match, retrieve value part and parse */ 02307 strncpy(workstring, vp->value, sizeof(workstring) - 1 ); 02308 stringp = workstring; 02309 action = strsep(&stringp, ","); 02310 param = stringp; 02311 if(debug) 02312 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)"); 02313 /* Look up the action */ 02314 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){ 02315 if(!strncasecmp(action, function_table[i].action, strlen(action))) 02316 break; 02317 } 02318 if(debug) 02319 printf("@@@@ table index i = %d\n",i); 02320 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){ 02321 /* Error, action not in table */ 02322 return DC_ERROR; 02323 } 02324 if(function_table[i].function == NULL){ 02325 /* Error, function undefined */ 02326 if(debug) 02327 printf("@@@@ NULL for action: %s\n",action); 02328 return DC_ERROR; 02329 } 02330 functiondigits = digits + strlen(vp->name); 02331 return (*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink); 02332 }
char* description | ( | void | ) |
static int function_autopatchdn | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 2164 of file app_rpt.c.
References ast_mutex_lock(), ast_mutex_unlock(), rpt::callmode, DC_COMPLETE, DC_ERROR, rpt::enable, rpt::lock, rpt_telemetry(), and TERM.
02165 { 02166 if (!myrpt->enable) 02167 return DC_ERROR; 02168 02169 if(debug) 02170 printf("@@@@ Autopatch down\n"); 02171 02172 ast_mutex_lock(&myrpt->lock); 02173 02174 if (!myrpt->callmode){ 02175 ast_mutex_unlock(&myrpt->lock); 02176 return DC_COMPLETE; 02177 } 02178 02179 myrpt->callmode = 0; 02180 ast_mutex_unlock(&myrpt->lock); 02181 rpt_telemetry(myrpt, TERM, NULL); 02182 return DC_COMPLETE; 02183 }
static int function_autopatchup | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 2128 of file app_rpt.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, rpt::callmode, rpt::cidx, DC_COMPLETE, DC_ERROR, rpt::enable, rpt::exten, rpt::funcchar, rpt::lock, rpt::mydtmf, rpt_call(), and rpt::rpt_call_thread.
02129 { 02130 pthread_attr_t attr; 02131 02132 02133 if (!myrpt->enable) 02134 return DC_ERROR; 02135 02136 if(debug) 02137 printf("@@@@ Autopatch up\n"); 02138 02139 ast_mutex_lock(&myrpt->lock); 02140 02141 /* if on call, force * into current audio stream */ 02142 02143 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){ 02144 myrpt->mydtmf = myrpt->funcchar; 02145 } 02146 if (myrpt->callmode){ 02147 ast_mutex_unlock(&myrpt->lock); 02148 return DC_COMPLETE; 02149 } 02150 myrpt->callmode = 1; 02151 myrpt->cidx = 0; 02152 myrpt->exten[myrpt->cidx] = 0; 02153 ast_mutex_unlock(&myrpt->lock); 02154 pthread_attr_init(&attr); 02155 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02156 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt); 02157 return DC_COMPLETE; 02158 }
static int function_cop | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 2221 of file app_rpt.c.
References ARB_ALPHA, DC_COMPLETE, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, rpt::disgorgetime, rpt::enable, myatoi(), rpt_telemetry(), SOURCE_PHONE, and TEST_TONE.
02222 { 02223 if(!param) 02224 return DC_ERROR; 02225 02226 switch(myatoi(param)){ 02227 case 1: /* System reset */ 02228 system("killall -9 asterisk"); /* FIXME to drastic? */ 02229 return DC_COMPLETE; 02230 02231 case 2: 02232 myrpt->enable = 1; 02233 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA"); 02234 return DC_COMPLETE; 02235 02236 case 3: 02237 myrpt->enable = 0; 02238 return DC_COMPLETE; 02239 02240 case 4: /* test tone on */ 02241 rpt_telemetry(myrpt, TEST_TONE, NULL); 02242 return DC_COMPLETE; 02243 02244 case 5: /* Disgorge variables to log for debug purposes */ 02245 myrpt->disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */ 02246 return DC_COMPLETE; 02247 02248 case 6: /* Simulate COR being activated (phone only) */ 02249 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE; 02250 return DC_DOKEY; 02251 02252 } 02253 return DC_INDETERMINATE; 02254 }
static int function_ilink | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 1766 of file app_rpt.c.
References ast_call(), AST_FORMAT_SLINEAR, AST_FRAME_TEXT, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_safe_sleep(), ast_set_read_format(), ast_set_write_format(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_true(), ast_variable_retrieve(), ast_verbose(), ast_write(), cfg, rpt_link::chan, rpt::cmdnode, COMPLETE, rpt::conf, CONNFAIL, ast_frame::data, ast_frame::datalen, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt_link::disced, rpt::enable, ast_frame::frametype, free, rpt::lastlinknode, rpt::links, rpt::lock, LOG_WARNING, rpt::longestnode, malloc, ast_frame::mallocd, MAX_RETRIES, MAXNODESTR, rpt_link::mode, myatoi(), rpt::name, rpt_link::name, rpt_link::next, rpt::nodes, ast_frame::offset, option_verbose, REMALREADY, REMGO, rpt_link::retries, rpt_telemetry(), s, ast_frame::samples, SOURCE_DPHONE, SOURCE_PHONE, SOURCE_RPT, STATUS, strdup, strsep(), ast_frame::subclass, and VERBOSE_PREFIX_3.
01767 { 01768 01769 char *val, *s, *s1, *s2, *tele; 01770 char tmp[300], deststr[300] = "",modechange = 0; 01771 char digitbuf[MAXNODESTR]; 01772 struct rpt_link *l; 01773 ZT_CONFINFO ci; /* conference info */ 01774 01775 if(!param) 01776 return DC_ERROR; 01777 01778 01779 if (!myrpt->enable) 01780 return DC_ERROR; 01781 01782 strncpy(digitbuf,digits,MAXNODESTR - 1); 01783 01784 if(debug) 01785 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf); 01786 01787 switch(myatoi(param)){ 01788 case 1: /* Link off */ 01789 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0])) 01790 strcpy(digitbuf,myrpt->lastlinknode); 01791 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf); 01792 if (!val){ 01793 if(strlen(digitbuf) >= myrpt->longestnode) 01794 return DC_ERROR; 01795 break; 01796 } 01797 strncpy(tmp,val,sizeof(tmp) - 1); 01798 s = tmp; 01799 s1 = strsep(&s,","); 01800 s2 = strsep(&s,","); 01801 ast_mutex_lock(&myrpt->lock); 01802 l = myrpt->links.next; 01803 /* try to find this one in queue */ 01804 while(l != &myrpt->links){ 01805 if (l->name[0] == '0') 01806 { 01807 l = l->next; 01808 continue; 01809 } 01810 /* if found matching string */ 01811 if (!strcmp(l->name, digitbuf)) 01812 break; 01813 l = l->next; 01814 } 01815 if (l != &myrpt->links){ /* if found */ 01816 struct ast_frame wf; 01817 01818 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1); 01819 l->retries = MAX_RETRIES + 1; 01820 l->disced = 1; 01821 ast_mutex_unlock(&myrpt->lock); 01822 wf.frametype = AST_FRAME_TEXT; 01823 wf.subclass = 0; 01824 wf.offset = 0; 01825 wf.mallocd = 1; 01826 wf.datalen = strlen(discstr) + 1; 01827 wf.samples = 0; 01828 wf.data = strdup(discstr); 01829 if (l->chan) 01830 { 01831 ast_write(l->chan,&wf); 01832 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR; 01833 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV); 01834 } 01835 rpt_telemetry(myrpt, COMPLETE, NULL); 01836 return DC_COMPLETE; 01837 } 01838 ast_mutex_unlock(&myrpt->lock); 01839 return DC_COMPLETE; 01840 case 2: /* Link Monitor */ 01841 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0])) 01842 strcpy(digitbuf,myrpt->lastlinknode); 01843 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf); 01844 if (!val){ 01845 if(strlen(digitbuf) >= myrpt->longestnode) 01846 return DC_ERROR; 01847 break; 01848 } 01849 strncpy(tmp,val,sizeof(tmp) - 1); 01850 s = tmp; 01851 s1 = strsep(&s,","); 01852 s2 = strsep(&s,","); 01853 ast_mutex_lock(&myrpt->lock); 01854 l = myrpt->links.next; 01855 /* try to find this one in queue */ 01856 while(l != &myrpt->links){ 01857 if (l->name[0] == '0') 01858 { 01859 l = l->next; 01860 continue; 01861 } 01862 /* if found matching string */ 01863 if (!strcmp(l->name, digitbuf)) 01864 break; 01865 l = l->next; 01866 } 01867 /* if found */ 01868 if (l != &myrpt->links) 01869 { 01870 /* if already in this mode, just ignore */ 01871 if ((!l->mode) || (!l->chan)) { 01872 ast_mutex_unlock(&myrpt->lock); 01873 rpt_telemetry(myrpt,REMALREADY,NULL); 01874 return DC_COMPLETE; 01875 01876 } 01877 ast_mutex_unlock(&myrpt->lock); 01878 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV); 01879 l->retries = MAX_RETRIES + 1; 01880 l->disced = 2; 01881 modechange = 1; 01882 } else 01883 ast_mutex_unlock(&myrpt->lock); 01884 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1); 01885 /* establish call in monitor mode */ 01886 l = malloc(sizeof(struct rpt_link)); 01887 if (!l){ 01888 ast_log(LOG_WARNING, "Unable to malloc\n"); 01889 return DC_ERROR; 01890 } 01891 /* zero the silly thing */ 01892 memset((char *)l,0,sizeof(struct rpt_link)); 01893 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1); 01894 tele = strchr(deststr,'/'); 01895 if (!tele){ 01896 fprintf(stderr,"link2:Dial number (%s) must be in format tech/number\n",deststr); 01897 return DC_ERROR; 01898 } 01899 *tele++ = 0; 01900 l->isremote = (s && ast_true(s)); 01901 strncpy(l->name, digitbuf, MAXNODESTR - 1); 01902 l->chan = ast_request(deststr,AST_FORMAT_SLINEAR,tele,NULL); 01903 if (modechange) l->connected = 1; 01904 if (l->chan){ 01905 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR); 01906 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR); 01907 l->chan->whentohangup = 0; 01908 l->chan->appl = "Apprpt"; 01909 l->chan->data = "(Remote Rx)"; 01910 if (option_verbose > 2) 01911 ast_verbose(VERBOSE_PREFIX_3 "rpt (remote) initiating call to %s/%s on %s\n", 01912 deststr,tele,l->chan->name); 01913 if(l->chan->cid.cid_num) 01914 free(l->chan->cid.cid_num); 01915 l->chan->cid.cid_num = strdup(myrpt->name); 01916 ast_call(l->chan,tele,0); 01917 } 01918 else 01919 { 01920 rpt_telemetry(myrpt,CONNFAIL,l); 01921 free(l); 01922 if (option_verbose > 2) 01923 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n", 01924 deststr,tele,l->chan->name); 01925 return DC_ERROR; 01926 } 01927 /* allocate a pseudo-channel thru asterisk */ 01928 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL); 01929 if (!l->pchan){ 01930 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); 01931 ast_hangup(l->chan); 01932 free(l); 01933 return DC_ERROR; 01934 } 01935 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR); 01936 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR); 01937 /* make a conference for the pseudo-one */ 01938 ci.chan = 0; 01939 ci.confno = myrpt->conf; 01940 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER; 01941 /* first put the channel on the conference in proper mode */ 01942 if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1) 01943 { 01944 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 01945 ast_hangup(l->chan); 01946 ast_hangup(l->pchan); 01947 free(l); 01948 return DC_ERROR; 01949 } 01950 ast_mutex_lock(&myrpt->lock); 01951 /* insert at end of queue */ 01952 insque((struct qelem *)l,(struct qelem *)myrpt->links.next); 01953 ast_mutex_unlock(&myrpt->lock); 01954 rpt_telemetry(myrpt,COMPLETE,NULL); 01955 return DC_COMPLETE; 01956 case 3: /* Link transceive */ 01957 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0])) 01958 strcpy(digitbuf,myrpt->lastlinknode); 01959 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf); 01960 if (!val){ 01961 if(strlen(digitbuf) >= myrpt->longestnode) 01962 return DC_ERROR; 01963 break; 01964 } 01965 strncpy(tmp,val,sizeof(tmp) - 1); 01966 s = tmp; 01967 s1 = strsep(&s,","); 01968 s2 = strsep(&s,","); 01969 ast_mutex_lock(&myrpt->lock); 01970 l = myrpt->links.next; 01971 /* try to find this one in queue */ 01972 while(l != &myrpt->links){ 01973 if (l->name[0] == '0') 01974 { 01975 l = l->next; 01976 continue; 01977 } 01978 /* if found matching string */ 01979 if (!strcmp(l->name, digitbuf)) 01980 break; 01981 l = l->next; 01982 } 01983 /* if found */ 01984 if (l != &myrpt->links){ 01985 /* if already in this mode, just ignore */ 01986 if ((l->mode) || (!l->chan)) { 01987 ast_mutex_unlock(&myrpt->lock); 01988 rpt_telemetry(myrpt, REMALREADY, NULL); 01989 return DC_COMPLETE; 01990 } 01991 ast_mutex_unlock(&myrpt->lock); 01992 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); 01993 l->retries = MAX_RETRIES + 1; 01994 l->disced = 2; 01995 modechange = 1; 01996 } else 01997 ast_mutex_unlock(&myrpt->lock); 01998 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1); 01999 /* establish call in tranceive mode */ 02000 l = malloc(sizeof(struct rpt_link)); 02001 if (!l){ 02002 ast_log(LOG_WARNING, "Unable to malloc\n"); 02003 return(DC_ERROR); 02004 } 02005 /* zero the silly thing */ 02006 memset((char *)l,0,sizeof(struct rpt_link)); 02007 l->mode = 1; 02008 l->outbound = 1; 02009 strncpy(l->name, digitbuf, MAXNODESTR - 1); 02010 l->isremote = (s && ast_true(s)); 02011 if (modechange) l->connected = 1; 02012 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1); 02013 tele = strchr(deststr, '/'); 02014 if (!tele){ 02015 fprintf(stderr,"link3:Dial number (%s) must be in format tech/number\n",deststr); 02016 free(l); 02017 return DC_ERROR; 02018 } 02019 *tele++ = 0; 02020 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL); 02021 if (l->chan){ 02022 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR); 02023 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR); 02024 l->chan->whentohangup = 0; 02025 l->chan->appl = "Apprpt"; 02026 l->chan->data = "(Remote Rx)"; 02027 if (option_verbose > 2) 02028 ast_verbose(VERBOSE_PREFIX_3 "rpt (remote) initiating call to %s/%s on %s\n", 02029 deststr, tele, l->chan->name); 02030 if(l->chan->cid.cid_num) 02031 free(l->chan->cid.cid_num); 02032 l->chan->cid.cid_num = strdup(myrpt->name); 02033 ast_call(l->chan,tele,999); 02034 } 02035 else{ 02036 rpt_telemetry(myrpt,CONNFAIL,l); 02037 free(l); 02038 if (option_verbose > 2) 02039 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n", 02040 deststr,tele,l->chan->name); 02041 return DC_ERROR; 02042 } 02043 /* allocate a pseudo-channel thru asterisk */ 02044 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL); 02045 if (!l->pchan){ 02046 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); 02047 ast_hangup(l->chan); 02048 free(l); 02049 return DC_ERROR; 02050 } 02051 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR); 02052 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR); 02053 /* make a conference for the tx */ 02054 ci.chan = 0; 02055 ci.confno = myrpt->conf; 02056 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER; 02057 /* first put the channel on the conference in proper mode */ 02058 if (ioctl(l->pchan->fds[0], ZT_SETCONF, &ci) == -1) 02059 { 02060 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 02061 ast_hangup(l->chan); 02062 ast_hangup(l->pchan); 02063 free(l); 02064 return DC_ERROR; 02065 } 02066 ast_mutex_lock(&myrpt->lock); 02067 /* insert at end of queue */ 02068 insque((struct qelem *)l,(struct qelem *)myrpt->links.next); 02069 ast_mutex_unlock(&myrpt->lock); 02070 rpt_telemetry(myrpt,COMPLETE,NULL); 02071 return DC_COMPLETE; 02072 case 4: /* Enter Command Mode */ 02073 02074 /* if doesnt allow link cmd, or no links active, return */ 02075 if (((command_source != SOURCE_RPT) && (command_source != SOURCE_PHONE) && (command_source != SOURCE_DPHONE)) || (myrpt->links.next == &myrpt->links)) 02076 return DC_COMPLETE; 02077 02078 /* if already in cmd mode, or selected self, fughetabahtit */ 02079 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){ 02080 02081 rpt_telemetry(myrpt, REMALREADY, NULL); 02082 return DC_COMPLETE; 02083 } 02084 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0])) 02085 strcpy(digitbuf,myrpt->lastlinknode); 02086 /* node must at least exist in list */ 02087 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf); 02088 if (!val){ 02089 if(strlen(digitbuf) >= myrpt->longestnode) 02090 return DC_ERROR; 02091 break; 02092 02093 } 02094 ast_mutex_lock(&myrpt->lock); 02095 strcpy(myrpt->lastlinknode,digitbuf); 02096 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1); 02097 ast_mutex_unlock(&myrpt->lock); 02098 rpt_telemetry(myrpt, REMGO, NULL); 02099 return DC_COMPLETE; 02100 02101 case 5: /* Status */ 02102 rpt_telemetry(myrpt, STATUS, NULL); 02103 return DC_COMPLETE; 02104 02105 02106 case 6: /* All Links Off */ 02107 l = myrpt->links.next; 02108 02109 while(l != &myrpt->links){ 02110 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); /* Hang 'em up */ 02111 l = l->next; 02112 } 02113 rpt_telemetry(myrpt, COMPLETE, NULL); 02114 break; 02115 02116 default: 02117 return DC_ERROR; 02118 02119 } 02120 02121 return DC_INDETERMINATE; 02122 }
static int function_remote | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 3618 of file app_rpt.c.
References AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_safe_sleep(), ast_variable_retrieve(), cfg, check_freq(), DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt::freq, HF_SCAN_DOWN_FAST, HF_SCAN_DOWN_QUICK, HF_SCAN_DOWN_SLOW, HF_SCAN_UP_FAST, HF_SCAN_UP_QUICK, HF_SCAN_UP_SLOW, rpt::hfscanmode, MAXREMSTR, MEMORY, multimode_bump_freq(), multimode_capable(), myatoi(), rpt::name, rpt::offset, offset, rpt::powerlevel, REM_HIPWR, REM_LOWPWR, REM_MEDPWR, REM_MINUS, REM_MODE_AM, REM_MODE_FM, REM_MODE_LSB, REM_MODE_USB, REM_PLUS, REM_SCANTIME, REM_SIMPLEX, rpt::remchannel, rpt::remmode, rpt::remoterx, rpt::remotetx, rmt_saycharstr(), rmt_sayfile(), rmt_telem_finish(), rmt_telem_start(), rpt::rxpl, rpt::rxplon, s, saycharstr(), sayfile(), saynum(), rpt::scantimer, setrem(), SOURCE_LNK, SOURCE_RPT, split_freq(), strsep(), rpt::tunerequest, rpt::txchannel, rpt::txpl, and rpt::txplon.
03619 { 03620 char *s,*s1,*s2,*val; 03621 int i,j,ht,k,l,ls2,m,d,res,offset,offsave, modesave, defmode; 03622 char multimode = 0; 03623 char oc; 03624 char tmp[20], freq[20] = "", savestr[20] = ""; 03625 char mhz[MAXREMSTR], decimals[MAXREMSTR]; 03626 struct ast_channel *mychannel; 03627 03628 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK)) 03629 return DC_ERROR; 03630 03631 multimode = multimode_capable(myrpt); 03632 03633 mychannel = myrpt->remchannel; 03634 03635 03636 switch(myatoi(param)){ 03637 03638 case 1: /* retrieve memory */ 03639 if(strlen(digitbuf) < 2) /* needs 2 digits */ 03640 break; 03641 03642 for(i = 0 ; i < 2 ; i++){ 03643 if((digitbuf[i] < '0') || (digitbuf[i] > '9')) 03644 return DC_ERROR; 03645 } 03646 03647 val = ast_variable_retrieve(cfg, MEMORY, digitbuf); 03648 if (!val){ 03649 if (ast_safe_sleep(mychannel,1000) == -1) 03650 return DC_ERROR; 03651 sayfile(mychannel,"rpt/memory_notfound"); 03652 return DC_COMPLETE; 03653 } 03654 strncpy(tmp,val,sizeof(tmp) - 1); 03655 s = strchr(tmp,','); 03656 if (!s) 03657 return DC_ERROR; 03658 *s++ = 0; 03659 s1 = strchr(s,','); 03660 if (!s1) 03661 return DC_ERROR; 03662 *s1++ = 0; 03663 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1); 03664 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1); 03665 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1); 03666 myrpt->remmode = REM_MODE_FM; 03667 myrpt->offset = REM_SIMPLEX; 03668 myrpt->powerlevel = REM_MEDPWR; 03669 myrpt->txplon = myrpt->rxplon = 0; 03670 while(*s1) 03671 { 03672 switch(*s1++){ 03673 case 'A': 03674 case 'a': 03675 strcpy(myrpt->rxpl, "100.0"); 03676 strcpy(myrpt->txpl, "100.0"); 03677 myrpt->remmode = REM_MODE_AM; 03678 break; 03679 03680 case 'B': 03681 case 'b': 03682 strcpy(myrpt->rxpl, "100.0"); 03683 strcpy(myrpt->txpl, "100.0"); 03684 myrpt->remmode = REM_MODE_LSB; 03685 break; 03686 03687 case 'F': 03688 myrpt->remmode = REM_MODE_FM; 03689 break; 03690 03691 case 'L': 03692 case 'l': 03693 myrpt->powerlevel = REM_LOWPWR; 03694 break; 03695 case 'H': 03696 case 'h': 03697 myrpt->powerlevel = REM_HIPWR; 03698 break; 03699 03700 case 'M': 03701 case 'm': 03702 myrpt->powerlevel = REM_MEDPWR; 03703 break; 03704 03705 case '-': 03706 myrpt->offset = REM_MINUS; 03707 break; 03708 03709 case '+': 03710 myrpt->offset = REM_PLUS; 03711 break; 03712 03713 case 'S': 03714 case 's': 03715 myrpt->offset = REM_SIMPLEX; 03716 break; 03717 03718 case 'T': 03719 case 't': 03720 myrpt->txplon = 1; 03721 break; 03722 03723 case 'R': 03724 case 'r': 03725 myrpt->rxplon = 1; 03726 break; 03727 03728 case 'U': 03729 case 'u': 03730 strcpy(myrpt->rxpl, "100.0"); 03731 strcpy(myrpt->txpl, "100.0"); 03732 myrpt->remmode = REM_MODE_USB; 03733 break; 03734 } 03735 } 03736 03737 03738 if (setrem(myrpt) == -1) 03739 return DC_ERROR; 03740 03741 03742 return DC_COMPLETE; 03743 03744 case 2: /* set freq and offset */ 03745 03746 03747 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for M+*K+*O or M+*H+* depending on mode */ 03748 if(digitbuf[i] == '*'){ 03749 j++; 03750 continue; 03751 } 03752 if((digitbuf[i] < '0') || (digitbuf[i] > '9')) 03753 goto invalid_freq; 03754 else{ 03755 if(j == 0) 03756 l++; /* # of digits before first * */ 03757 if(j == 1) 03758 k++; /* # of digits after first * */ 03759 } 03760 } 03761 03762 i = strlen(digitbuf) - 1; 03763 if(multimode){ 03764 if((j > 2) || (l > 3) || (k > 6)) 03765 goto invalid_freq; /* &^@#! */ 03766 } 03767 else{ 03768 if((j > 2) || (l > 4) || (k > 3)) 03769 goto invalid_freq; /* &^@#! */ 03770 } 03771 03772 /* Wait for M+*K+* */ 03773 03774 if(j < 2) 03775 break; /* Not yet */ 03776 03777 /* We have a frequency */ 03778 03779 strncpy(tmp, digitbuf ,sizeof(tmp) - 1); 03780 03781 s = tmp; 03782 s1 = strsep(&s, "*"); /* Pick off MHz */ 03783 s2 = strsep(&s,"*"); /* Pick off KHz and Hz */ 03784 ls2 = strlen(s2); 03785 03786 switch(ls2){ /* Allow partial entry of khz and hz digits for laziness support */ 03787 case 1: 03788 ht = 0; 03789 k = 100 * atoi(s2); 03790 break; 03791 03792 case 2: 03793 ht = 0; 03794 k = 10 * atoi(s2); 03795 break; 03796 03797 case 3: 03798 if(!multimode){ 03799 if((s2[2] != '0')&&(s2[2] != '5')) 03800 goto invalid_freq; 03801 } 03802 ht = 0; 03803 k = atoi(s2); 03804 break; 03805 case 4: 03806 k = atoi(s2)/10; 03807 ht = 10 * (atoi(s2+(ls2-1))); 03808 break; 03809 03810 case 5: 03811 k = atoi(s2)/100; 03812 ht = (atoi(s2+(ls2-2))); 03813 break; 03814 03815 default: 03816 goto invalid_freq; 03817 } 03818 03819 /* Check frequency for validity and establish a default mode */ 03820 03821 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht); 03822 03823 if(debug) 03824 printf("New frequency: %s\n", freq); 03825 03826 split_freq(mhz, decimals, freq); 03827 m = atoi(mhz); 03828 d = atoi(decimals); 03829 03830 if(check_freq(myrpt, m, d, &defmode)) /* Check to see if frequency entered is legit */ 03831 goto invalid_freq; 03832 03833 03834 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*')) /* If FM, user must enter and additional offset digit */ 03835 break; /* Not yet */ 03836 03837 03838 offset = REM_SIMPLEX; /* Assume simplex */ 03839 03840 if(defmode == REM_MODE_FM){ 03841 oc = *s; /* Pick off offset */ 03842 03843 if (oc){ 03844 switch(oc){ 03845 case '1': 03846 offset = REM_MINUS; 03847 break; 03848 03849 case '2': 03850 offset = REM_SIMPLEX; 03851 break; 03852 03853 case '3': 03854 offset = REM_PLUS; 03855 break; 03856 03857 default: 03858 goto invalid_freq; 03859 } 03860 } 03861 } 03862 offsave = myrpt->offset; 03863 modesave = myrpt->remmode; 03864 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1); 03865 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1); 03866 myrpt->offset = offset; 03867 myrpt->remmode = defmode; 03868 03869 if (setrem(myrpt) == -1){ 03870 myrpt->offset = offsave; 03871 myrpt->remmode = modesave; 03872 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1); 03873 goto invalid_freq; 03874 } 03875 03876 return DC_COMPLETE; 03877 03878 03879 invalid_freq: 03880 03881 rmt_sayfile(myrpt, mychannel, 1000, "rpt/invalid-freq"); 03882 03883 return DC_ERROR; 03884 03885 case 3: /* set rx PL tone */ 03886 03887 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N */ 03888 if(digitbuf[i] == '*'){ 03889 j++; 03890 continue; 03891 } 03892 if((digitbuf[i] < '0') || (digitbuf[i] > '9')) 03893 return DC_ERROR; 03894 else{ 03895 if(j) 03896 l++; 03897 else 03898 k++; 03899 } 03900 } 03901 if((j > 1) || (k > 3) || (l > 1)) 03902 return DC_ERROR; /* &$@^! */ 03903 i = strlen(digitbuf) - 1; 03904 if((j != 1) || (k < 2)|| (l != 1)) 03905 break; /* Not yet */ 03906 if(debug) 03907 printf("PL digits entered %s\n", digitbuf); 03908 03909 strncpy(tmp, digitbuf, sizeof(tmp) - 1); 03910 /* see if we have at least 1 */ 03911 s = strchr(tmp,'*'); 03912 if(s) 03913 *s = '.'; 03914 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1); 03915 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1); 03916 03917 if (setrem(myrpt) == -1){ 03918 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1); 03919 return DC_ERROR; 03920 } 03921 03922 03923 return DC_COMPLETE; 03924 03925 case 4: /* set tx PL tone */ 03926 03927 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N */ 03928 if(digitbuf[i] == '*'){ 03929 j++; 03930 continue; 03931 } 03932 if((digitbuf[i] < '0') || (digitbuf[i] > '9')) 03933 return DC_ERROR; 03934 else{ 03935 if(j) 03936 l++; 03937 else 03938 k++; 03939 } 03940 } 03941 if((j > 1) || (k > 3) || (l > 1)) 03942 return DC_ERROR; /* &$@^! */ 03943 i = strlen(digitbuf) - 1; 03944 if((j != 1) || (k < 2)|| (l != 1)) 03945 break; /* Not yet */ 03946 if(debug) 03947 printf("PL digits entered %s\n", digitbuf); 03948 03949 strncpy(tmp, digitbuf, sizeof(tmp) - 1); 03950 /* see if we have at least 1 */ 03951 s = strchr(tmp,'*'); 03952 if(s) 03953 *s = '.'; 03954 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1); 03955 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1); 03956 03957 if (setrem(myrpt) == -1){ 03958 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1); 03959 return DC_ERROR; 03960 } 03961 03962 03963 return DC_COMPLETE; 03964 03965 03966 case 6: /* MODE (FM,USB,LSB,AM) */ 03967 if(strlen(digitbuf) < 1) 03968 break; 03969 03970 if(!multimode) 03971 return DC_ERROR; /* Multimode radios only */ 03972 03973 switch(*digitbuf){ 03974 case '1': 03975 split_freq(mhz, decimals, myrpt->freq); 03976 m=atoi(mhz); 03977 if(m < 29) /* No FM allowed below 29MHz! */ 03978 return DC_ERROR; 03979 myrpt->remmode = REM_MODE_FM; 03980 res = rmt_saycharstr(myrpt, mychannel, 1000,"FM"); 03981 break; 03982 03983 case '2': 03984 myrpt->remmode = REM_MODE_USB; 03985 res = rmt_saycharstr(myrpt, mychannel, 1000,"USB"); 03986 break; 03987 03988 case '3': 03989 myrpt->remmode = REM_MODE_LSB; 03990 res = rmt_saycharstr(myrpt, mychannel, 1000,"LSB"); 03991 break; 03992 03993 case '4': 03994 myrpt->remmode = REM_MODE_AM; 03995 res = rmt_saycharstr(myrpt, mychannel, 1000,"AM"); 03996 break; 03997 03998 default: 03999 return DC_ERROR; 04000 } 04001 if(res) 04002 return DC_ERROR; 04003 04004 if(setrem(myrpt)) 04005 return DC_ERROR; 04006 return DC_COMPLETE; 04007 04008 case 100: /* other stuff */ 04009 case 101: 04010 case 102: 04011 case 103: 04012 case 104: 04013 case 105: 04014 case 106: 04015 res = rmt_telem_start(myrpt, mychannel, 1000); 04016 switch(myatoi(param)){ /* Quick commands requiring a setrem call */ 04017 case 100: /* RX PL Off */ 04018 myrpt->rxplon = 0; 04019 if(!res) 04020 res = sayfile(mychannel, "rpt/rxpl"); 04021 if(!res) 04022 sayfile(mychannel, "rpt/off"); 04023 break; 04024 04025 case 101: /* RX PL On */ 04026 myrpt->rxplon = 1; 04027 if(!res) 04028 res = sayfile(mychannel, "rpt/rxpl"); 04029 if(!res) 04030 sayfile(mychannel, "rpt/on"); 04031 break; 04032 04033 04034 case 102: /* TX PL Off */ 04035 myrpt->txplon = 0; 04036 if(!res) 04037 res = sayfile(mychannel, "rpt/txpl"); 04038 if(!res) 04039 sayfile(mychannel, "rpt/off"); 04040 break; 04041 04042 case 103: /* TX PL On */ 04043 myrpt->txplon = 1; 04044 if(!res) 04045 res = sayfile(mychannel, "rpt/txpl"); 04046 if(!res) 04047 sayfile(mychannel, "rpt/on"); 04048 break; 04049 04050 case 104: /* Low Power */ 04051 myrpt->powerlevel = REM_LOWPWR; 04052 if(!res) 04053 res = sayfile(mychannel, "rpt/lopwr"); 04054 break; 04055 04056 case 105: /* Medium Power */ 04057 myrpt->powerlevel = REM_MEDPWR; 04058 if(!res) 04059 res = sayfile(mychannel, "rpt/medpwr"); 04060 break; 04061 04062 case 106: /* Hi Power */ 04063 myrpt->powerlevel = REM_HIPWR; 04064 if(!res) 04065 res = sayfile(mychannel, "rpt/hipwr"); 04066 break; 04067 04068 default: 04069 if(!res) 04070 rmt_telem_finish(myrpt, mychannel); 04071 return DC_ERROR; 04072 } 04073 if(!res) 04074 res = rmt_telem_finish(myrpt, mychannel); 04075 if(res) 04076 return DC_ERROR; 04077 04078 if (setrem(myrpt) == -1) 04079 return DC_ERROR; 04080 return DC_COMPLETE; 04081 04082 case 107: /* Bump down 20Hz */ 04083 multimode_bump_freq(myrpt, -20); 04084 return DC_COMPLETE; 04085 04086 case 108: /* Bump down 100Hz */ 04087 multimode_bump_freq(myrpt, -100); 04088 return DC_COMPLETE; 04089 04090 case 109: /* Bump down 500Hz */ 04091 multimode_bump_freq(myrpt, -500); 04092 return DC_COMPLETE; 04093 04094 case 110: /* Bump up 20Hz */ 04095 multimode_bump_freq(myrpt, 20); 04096 return DC_COMPLETE; 04097 04098 case 111: /* Bump up 100Hz */ 04099 multimode_bump_freq(myrpt, 100); 04100 return DC_COMPLETE; 04101 04102 case 112: /* Bump up 500Hz */ 04103 multimode_bump_freq(myrpt, 500); 04104 return DC_COMPLETE; 04105 04106 04107 case 113: 04108 case 114: 04109 case 115: 04110 case 116: 04111 case 117: 04112 case 118: 04113 myrpt->remotetx = 0; 04114 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); 04115 if (!myrpt->remoterx) 04116 ast_indicate(mychannel,AST_CONTROL_RADIO_KEY); 04117 if (ast_safe_sleep(mychannel,1000) == -1) 04118 return DC_ERROR; 04119 04120 switch(myatoi(param)){ 04121 04122 case 113: /* Scan down slow */ 04123 res = sayfile(mychannel,"rpt/down"); 04124 if(!res) 04125 res = sayfile(mychannel, "rpt/slow"); 04126 if(!res){ 04127 myrpt->scantimer = REM_SCANTIME; 04128 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW; 04129 } 04130 break; 04131 04132 case 114: /* Scan down quick */ 04133 res = sayfile(mychannel,"rpt/down"); 04134 if(!res) 04135 res = sayfile(mychannel, "rpt/quick"); 04136 if(!res){ 04137 myrpt->scantimer = REM_SCANTIME; 04138 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK; 04139 } 04140 break; 04141 04142 case 115: /* Scan down fast */ 04143 res = sayfile(mychannel,"rpt/down"); 04144 if(!res) 04145 res = sayfile(mychannel, "rpt/fast"); 04146 if(!res){ 04147 myrpt->scantimer = REM_SCANTIME; 04148 myrpt->hfscanmode = HF_SCAN_DOWN_FAST; 04149 } 04150 break; 04151 04152 case 116: /* Scan up slow */ 04153 res = sayfile(mychannel,"rpt/up"); 04154 if(!res) 04155 res = sayfile(mychannel, "rpt/slow"); 04156 if(!res){ 04157 myrpt->scantimer = REM_SCANTIME; 04158 myrpt->hfscanmode = HF_SCAN_UP_SLOW; 04159 } 04160 break; 04161 04162 case 117: /* Scan up quick */ 04163 res = sayfile(mychannel,"rpt/up"); 04164 if(!res) 04165 res = sayfile(mychannel, "rpt/quick"); 04166 if(!res){ 04167 myrpt->scantimer = REM_SCANTIME; 04168 myrpt->hfscanmode = HF_SCAN_UP_QUICK; 04169 } 04170 break; 04171 04172 case 118: /* Scan up fast */ 04173 res = sayfile(mychannel,"rpt/up"); 04174 if(!res) 04175 res = sayfile(mychannel, "rpt/fast"); 04176 if(!res){ 04177 myrpt->scantimer = REM_SCANTIME; 04178 myrpt->hfscanmode = HF_SCAN_UP_FAST; 04179 } 04180 break; 04181 } 04182 rmt_telem_finish(myrpt,mychannel); 04183 return DC_COMPLETE; 04184 04185 04186 case 119: /* Tune Request */ 04187 myrpt->tunerequest = 1; 04188 return DC_COMPLETE; 04189 04190 case 5: /* Long Status */ 04191 case 140: /* Short Status */ 04192 res = rmt_telem_start(myrpt, mychannel, 1000); 04193 04194 res = sayfile(mychannel,"rpt/node"); 04195 if(!res) 04196 res = saycharstr(mychannel, myrpt->name); 04197 if(!res) 04198 res = sayfile(mychannel,"rpt/frequency"); 04199 if(!res) 04200 res = split_freq(mhz, decimals, myrpt->freq); 04201 if(!res){ 04202 m = atoi(mhz); 04203 if(m < 100) 04204 res = saynum(mychannel, m); 04205 else 04206 res = saycharstr(mychannel, mhz); 04207 } 04208 if(!res) 04209 res = sayfile(mychannel, "letters/dot"); 04210 if(!res) 04211 res = saycharstr(mychannel, decimals); 04212 04213 if(res){ 04214 rmt_telem_finish(myrpt,mychannel); 04215 return DC_ERROR; 04216 } 04217 if(myrpt->remmode == REM_MODE_FM){ /* Mode FM? */ 04218 switch(myrpt->offset){ 04219 04220 case REM_MINUS: 04221 res = sayfile(mychannel,"rpt/minus"); 04222 break; 04223 04224 case REM_SIMPLEX: 04225 res = sayfile(mychannel,"rpt/simplex"); 04226 break; 04227 04228 case REM_PLUS: 04229 res = sayfile(mychannel,"rpt/plus"); 04230 break; 04231 04232 default: 04233 return DC_ERROR; 04234 04235 } 04236 } 04237 else{ /* Must be USB, LSB, or AM */ 04238 switch(myrpt->remmode){ 04239 04240 case REM_MODE_USB: 04241 res = saycharstr(mychannel, "USB"); 04242 break; 04243 04244 case REM_MODE_LSB: 04245 res = saycharstr(mychannel, "LSB"); 04246 break; 04247 04248 case REM_MODE_AM: 04249 res = saycharstr(mychannel, "AM"); 04250 break; 04251 04252 04253 default: 04254 return DC_ERROR; 04255 } 04256 } 04257 04258 if (res == -1){ 04259 rmt_telem_finish(myrpt,mychannel); 04260 return DC_ERROR; 04261 } 04262 04263 if(myatoi(param) == 140){ /* Short status? */ 04264 if(!res) 04265 res = rmt_telem_finish(myrpt, mychannel); 04266 if(res) 04267 return DC_ERROR; 04268 return DC_COMPLETE; 04269 } 04270 04271 switch(myrpt->powerlevel){ 04272 04273 case REM_LOWPWR: 04274 res = sayfile(mychannel,"rpt/lopwr") ; 04275 break; 04276 04277 case REM_MEDPWR: 04278 res = sayfile(mychannel,"rpt/medpwr"); 04279 break; 04280 case REM_HIPWR: 04281 res = sayfile(mychannel,"rpt/hipwr"); 04282 break; 04283 } 04284 if (res || (sayfile(mychannel,"rpt/rxpl") == -1) || 04285 (sayfile(mychannel,"rpt/frequency") == -1) || 04286 (saycharstr(mychannel,myrpt->rxpl) == -1) || 04287 (sayfile(mychannel,"rpt/txpl") == -1) || 04288 (sayfile(mychannel,"rpt/frequency") == -1) || 04289 (saycharstr(mychannel,myrpt->txpl) == -1) || 04290 (sayfile(mychannel,"rpt/txpl") == -1) || 04291 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1) || 04292 (sayfile(mychannel,"rpt/rxpl") == -1) || 04293 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1)) 04294 { 04295 rmt_telem_finish(myrpt,mychannel); 04296 return DC_ERROR; 04297 } 04298 if(!res) 04299 res = rmt_telem_finish(myrpt,mychannel); 04300 if(res) 04301 return DC_ERROR; 04302 04303 return DC_COMPLETE; 04304 default: 04305 return DC_ERROR; 04306 } 04307 04308 return DC_INDETERMINATE; 04309 }
static int function_status | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 2189 of file app_rpt.c.
References DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt::enable, ID1, myatoi(), rpt_telemetry(), STATS_TIME, and STATS_VERSION.
02190 { 02191 02192 if(!param) 02193 return DC_ERROR; 02194 02195 02196 if (!myrpt->enable) 02197 return DC_ERROR; 02198 02199 if(debug) 02200 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf); 02201 02202 switch(myatoi(param)){ 02203 case 1: /* System ID */ 02204 rpt_telemetry(myrpt, ID1, NULL); 02205 return DC_COMPLETE; 02206 case 2: /* System Time */ 02207 rpt_telemetry(myrpt, STATS_TIME, NULL); 02208 return DC_COMPLETE; 02209 case 3: /* app_rpt.c version */ 02210 rpt_telemetry(myrpt, STATS_VERSION, NULL); 02211 default: 02212 return DC_ERROR; 02213 } 02214 return DC_INDETERMINATE; 02215 }
static int get_wait_interval | ( | struct rpt * | myrpt, | |
int | type | |||
) | [static] |
Definition at line 898 of file app_rpt.c.
References ast_log(), ast_strdupa, ast_variable_retrieve(), cfg, DLY_CALLTERM, DLY_ID, DLY_TELEM, DLY_UNKEY, LOG_WARNING, rpt::name, and retrieve_astcfgint().
Referenced by rpt_tele_thread(), and wait_interval().
00899 { 00900 int interval; 00901 char *wait_times; 00902 char *wait_times_save; 00903 00904 wait_times_save = NULL; 00905 wait_times = ast_variable_retrieve(cfg, myrpt->name, "wait_times"); 00906 00907 if(wait_times){ 00908 wait_times_save = ast_strdupa(wait_times); 00909 if(!wait_times_save){ 00910 ast_log(LOG_WARNING, "Out of memory in wait_interval()\n"); 00911 wait_times = NULL; 00912 } 00913 } 00914 00915 switch(type){ 00916 case DLY_TELEM: 00917 if(wait_times) 00918 interval = retrieve_astcfgint(wait_times_save, "telemwait", 500, 5000, 1000); 00919 else 00920 interval = 1000; 00921 break; 00922 00923 case DLY_ID: 00924 if(wait_times) 00925 interval = retrieve_astcfgint(wait_times_save, "idwait",250,5000,500); 00926 else 00927 interval = 500; 00928 break; 00929 00930 case DLY_UNKEY: 00931 if(wait_times) 00932 interval = retrieve_astcfgint(wait_times_save, "unkeywait",500,5000,1000); 00933 else 00934 interval = 1000; 00935 break; 00936 00937 case DLY_CALLTERM: 00938 if(wait_times) 00939 interval = retrieve_astcfgint(wait_times_save, "calltermwait",500,5000,1500); 00940 else 00941 interval = 1500; 00942 break; 00943 00944 default: 00945 return 0; 00946 } 00947 return interval; 00948 }
Definition at line 2335 of file app_rpt.c.
References ast_canmatch_extension(), ast_exists_extension(), AST_FRAME_TEXT, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_write(), rpt::callmode, rpt_link::chan, rpt::cidx, collect_function_digits(), ast_frame::data, ast_frame::datalen, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, rpt_link::disced, rpt::endchar, rpt::exten, ast_frame::frametype, rpt::funcchar, rpt::links, rpt::lock, LOG_WARNING, ast_frame::mallocd, MAX_RETRIES, MAXDTMF, rpt::mydtmf, rpt_link::name, rpt::name, rpt_link::next, ast_frame::offset, rpt::ourcontext, rpt::pchannel, PROC, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, rpt_link::retries, rpt_telemetry(), ast_frame::samples, seq, SOURCE_LNK, rpt::stopgen, strdup, and ast_frame::subclass.
Referenced by rpt().
02337 { 02338 char tmp[300],cmd[300] = "",dest[300],src[300],c; 02339 int seq, res; 02340 struct rpt_link *l; 02341 struct ast_frame wf; 02342 02343 wf.frametype = AST_FRAME_TEXT; 02344 wf.subclass = 0; 02345 wf.offset = 0; 02346 wf.mallocd = 1; 02347 wf.datalen = strlen(str) + 1; 02348 wf.samples = 0; 02349 /* put string in our buffer */ 02350 strncpy(tmp,str,sizeof(tmp) - 1); 02351 02352 if (!strcmp(tmp,discstr)) 02353 { 02354 mylink->disced = 1; 02355 mylink->retries = MAX_RETRIES + 1; 02356 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV); 02357 return; 02358 } 02359 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5) 02360 { 02361 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str); 02362 return; 02363 } 02364 if (strcmp(cmd,"D")) 02365 { 02366 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str); 02367 return; 02368 } 02369 02370 if (dest[0] == '0') 02371 { 02372 strcpy(dest,myrpt->name); 02373 } 02374 02375 /* if not for me, redistribute to all links */ 02376 if (strcmp(dest,myrpt->name)) 02377 { 02378 l = myrpt->links.next; 02379 /* see if this is one in list */ 02380 while(l != &myrpt->links) 02381 { 02382 if (l->name[0] == '0') 02383 { 02384 l = l->next; 02385 continue; 02386 } 02387 /* dont send back from where it came */ 02388 if ((l == mylink) || (!strcmp(l->name,mylink->name))) 02389 { 02390 l = l->next; 02391 continue; 02392 } 02393 /* if it is, send it and we're done */ 02394 if (!strcmp(l->name,dest)) 02395 { 02396 /* send, but not to src */ 02397 if (strcmp(l->name,src)) { 02398 wf.data = strdup(str); 02399 if (l->chan) ast_write(l->chan,&wf); 02400 } 02401 return; 02402 } 02403 l = l->next; 02404 } 02405 l = myrpt->links.next; 02406 /* otherwise, send it to all of em */ 02407 while(l != &myrpt->links) 02408 { 02409 if (l->name[0] == '0') 02410 { 02411 l = l->next; 02412 continue; 02413 } 02414 /* dont send back from where it came */ 02415 if ((l == mylink) || (!strcmp(l->name,mylink->name))) 02416 { 02417 l = l->next; 02418 continue; 02419 } 02420 /* send, but not to src */ 02421 if (strcmp(l->name,src)) { 02422 wf.data = strdup(str); 02423 if (l->chan) ast_write(l->chan,&wf); 02424 } 02425 l = l->next; 02426 } 02427 return; 02428 } 02429 ast_mutex_lock(&myrpt->lock); 02430 if (c == myrpt->endchar) myrpt->stopgen = 1; 02431 if (myrpt->callmode == 1) 02432 { 02433 myrpt->exten[myrpt->cidx++] = c; 02434 myrpt->exten[myrpt->cidx] = 0; 02435 /* if this exists */ 02436 if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) 02437 { 02438 myrpt->callmode = 2; 02439 rpt_telemetry(myrpt,PROC,NULL); 02440 } 02441 /* if can continue, do so */ 02442 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) 02443 { 02444 /* call has failed, inform user */ 02445 myrpt->callmode = 4; 02446 } 02447 } 02448 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) 02449 { 02450 myrpt->mydtmf = c; 02451 } 02452 if (c == myrpt->funcchar) 02453 { 02454 myrpt->rem_dtmfidx = 0; 02455 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0; 02456 time(&myrpt->rem_dtmf_time); 02457 ast_mutex_unlock(&myrpt->lock); 02458 return; 02459 } 02460 else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0)) 02461 { 02462 time(&myrpt->rem_dtmf_time); 02463 if (myrpt->rem_dtmfidx < MAXDTMF) 02464 { 02465 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c; 02466 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0; 02467 02468 ast_mutex_unlock(&myrpt->lock); 02469 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1); 02470 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink); 02471 ast_mutex_lock(&myrpt->lock); 02472 02473 switch(res){ 02474 02475 case DC_INDETERMINATE: 02476 break; 02477 02478 case DC_REQ_FLUSH: 02479 myrpt->rem_dtmfidx = 0; 02480 myrpt->rem_dtmfbuf[0] = 0; 02481 break; 02482 02483 02484 case DC_COMPLETE: 02485 myrpt->rem_dtmfbuf[0] = 0; 02486 myrpt->rem_dtmfidx = -1; 02487 myrpt->rem_dtmf_time = 0; 02488 break; 02489 02490 case DC_ERROR: 02491 default: 02492 myrpt->rem_dtmfbuf[0] = 0; 02493 myrpt->rem_dtmfidx = -1; 02494 myrpt->rem_dtmf_time = 0; 02495 break; 02496 } 02497 } 02498 02499 } 02500 ast_mutex_unlock(&myrpt->lock); 02501 return; 02502 }
static void handle_link_phone_dtmf | ( | struct rpt * | myrpt, | |
struct rpt_link * | mylink, | |||
char | c | |||
) | [static] |
Definition at line 2504 of file app_rpt.c.
References ast_canmatch_extension(), ast_exists_extension(), ast_mutex_lock(), ast_mutex_unlock(), rpt::callmode, rpt::cidx, rpt::cmdnode, collect_function_digits(), COMPLETE, DC_COMPLETE, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, rpt::dtmfbuf, rpt::dtmfidx, rpt::endchar, rpt::exten, rpt::funcchar, rpt_link::lastrx, rpt::lock, MAXDTMF, rpt::mydtmf, rpt::ourcontext, rpt::pchannel, rpt_link::phonemode, PROC, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, rpt_telemetry(), send_link_dtmf(), SOURCE_DPHONE, SOURCE_PHONE, and rpt::stopgen.
Referenced by rpt().
02506 { 02507 02508 char cmd[300]; 02509 int res; 02510 02511 ast_mutex_lock(&myrpt->lock); 02512 if (c == myrpt->endchar) 02513 { 02514 if (mylink->lastrx) 02515 { 02516 mylink->lastrx = 0; 02517 ast_mutex_unlock(&myrpt->lock); 02518 return; 02519 } 02520 myrpt->stopgen = 1; 02521 if (myrpt->cmdnode[0]) 02522 { 02523 myrpt->cmdnode[0] = 0; 02524 myrpt->dtmfidx = -1; 02525 myrpt->dtmfbuf[0] = 0; 02526 ast_mutex_unlock(&myrpt->lock); 02527 rpt_telemetry(myrpt,COMPLETE,NULL); 02528 ast_mutex_unlock(&myrpt->lock); 02529 return; 02530 } 02531 } 02532 if (myrpt->cmdnode[0]) 02533 { 02534 ast_mutex_unlock(&myrpt->lock); 02535 send_link_dtmf(myrpt,c); 02536 return; 02537 } 02538 if (myrpt->callmode == 1) 02539 { 02540 myrpt->exten[myrpt->cidx++] = c; 02541 myrpt->exten[myrpt->cidx] = 0; 02542 /* if this exists */ 02543 if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) 02544 { 02545 myrpt->callmode = 2; 02546 rpt_telemetry(myrpt,PROC,NULL); 02547 } 02548 /* if can continue, do so */ 02549 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) 02550 { 02551 /* call has failed, inform user */ 02552 myrpt->callmode = 4; 02553 } 02554 } 02555 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) 02556 { 02557 myrpt->mydtmf = c; 02558 } 02559 if (c == myrpt->funcchar) 02560 { 02561 myrpt->rem_dtmfidx = 0; 02562 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0; 02563 time(&myrpt->rem_dtmf_time); 02564 ast_mutex_unlock(&myrpt->lock); 02565 return; 02566 } 02567 else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0)) 02568 { 02569 time(&myrpt->rem_dtmf_time); 02570 if (myrpt->rem_dtmfidx < MAXDTMF) 02571 { 02572 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c; 02573 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0; 02574 02575 ast_mutex_unlock(&myrpt->lock); 02576 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1); 02577 res = collect_function_digits(myrpt, cmd, 02578 ((mylink->phonemode == 2) ? SOURCE_DPHONE : SOURCE_PHONE), mylink); 02579 ast_mutex_lock(&myrpt->lock); 02580 02581 switch(res){ 02582 02583 case DC_INDETERMINATE: 02584 break; 02585 02586 case DC_DOKEY: 02587 mylink->lastrx = 1; 02588 break; 02589 02590 case DC_REQ_FLUSH: 02591 myrpt->rem_dtmfidx = 0; 02592 myrpt->rem_dtmfbuf[0] = 0; 02593 break; 02594 02595 02596 case DC_COMPLETE: 02597 myrpt->rem_dtmfbuf[0] = 0; 02598 myrpt->rem_dtmfidx = -1; 02599 myrpt->rem_dtmf_time = 0; 02600 break; 02601 02602 case DC_ERROR: 02603 default: 02604 myrpt->rem_dtmfbuf[0] = 0; 02605 myrpt->rem_dtmfidx = -1; 02606 myrpt->rem_dtmf_time = 0; 02607 break; 02608 } 02609 } 02610 02611 } 02612 ast_mutex_unlock(&myrpt->lock); 02613 return; 02614 }
static int handle_remote_data | ( | struct rpt * | myrpt, | |
char * | str | |||
) | [static] |
Definition at line 4406 of file app_rpt.c.
References AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_log(), ast_safe_sleep(), handle_remote_dtmf_digit(), LOG_WARNING, rpt::name, rpt::remchannel, rpt::remoterx, rpt::remotetx, rmt_telem_finish(), seq, telem_lookup(), and rpt::txchannel.
04407 { 04408 char tmp[300],cmd[300],dest[300],src[300],c; 04409 int seq,res; 04410 04411 /* put string in our buffer */ 04412 strncpy(tmp,str,sizeof(tmp) - 1); 04413 if (!strcmp(tmp,discstr)) return 0; 04414 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5) 04415 { 04416 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str); 04417 return 0; 04418 } 04419 if (strcmp(cmd,"D")) 04420 { 04421 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str); 04422 return 0; 04423 } 04424 /* if not for me, ignore */ 04425 if (strcmp(dest,myrpt->name)) return 0; 04426 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0); 04427 if (res != 1) 04428 return res; 04429 myrpt->remotetx = 0; 04430 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); 04431 if (!myrpt->remoterx) 04432 { 04433 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY); 04434 } 04435 if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1; 04436 res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete"); 04437 rmt_telem_finish(myrpt,myrpt->remchannel); 04438 return res; 04439 }
static int handle_remote_dtmf_digit | ( | struct rpt * | myrpt, | |
char | c, | |||
char * | keyed, | |||
int | phonemode | |||
) | [static] |
Definition at line 4311 of file app_rpt.c.
References collect_function_digits(), DC_COMPLETE, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, rpt::dtmf_time_rem, DTMF_TIMEOUT, rpt::dtmfbuf, rpt::dtmfidx, rpt::funcchar, rpt::hfscanmode, MAXDTMF, SOURCE_DPHONE, SOURCE_PHONE, SOURCE_RMT, and stop_scan().
Referenced by handle_remote_data(), and handle_remote_phone_dtmf().
04312 { 04313 time_t now; 04314 int ret,res = 0,src; 04315 04316 /* Stop scan mode if in scan mode */ 04317 if(myrpt->hfscanmode){ 04318 stop_scan(myrpt,0); 04319 return 0; 04320 } 04321 04322 time(&now); 04323 /* if timed-out */ 04324 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now) 04325 { 04326 myrpt->dtmfidx = -1; 04327 myrpt->dtmfbuf[0] = 0; 04328 myrpt->dtmf_time_rem = 0; 04329 } 04330 /* if decode not active */ 04331 if (myrpt->dtmfidx == -1) 04332 { 04333 /* if not lead-in digit, dont worry */ 04334 if (c != myrpt->funcchar) return 0; 04335 myrpt->dtmfidx = 0; 04336 myrpt->dtmfbuf[0] = 0; 04337 myrpt->dtmf_time_rem = now; 04338 return 0; 04339 } 04340 /* if too many in buffer, start over */ 04341 if (myrpt->dtmfidx >= MAXDTMF) 04342 { 04343 myrpt->dtmfidx = 0; 04344 myrpt->dtmfbuf[0] = 0; 04345 myrpt->dtmf_time_rem = now; 04346 } 04347 if (c == myrpt->funcchar) 04348 { 04349 /* if star at beginning, or 2 together, erase buffer */ 04350 if ((myrpt->dtmfidx < 1) || 04351 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->funcchar)) 04352 { 04353 myrpt->dtmfidx = 0; 04354 myrpt->dtmfbuf[0] = 0; 04355 myrpt->dtmf_time_rem = now; 04356 return 0; 04357 } 04358 } 04359 myrpt->dtmfbuf[myrpt->dtmfidx++] = c; 04360 myrpt->dtmfbuf[myrpt->dtmfidx] = 0; 04361 myrpt->dtmf_time_rem = now; 04362 04363 04364 src = SOURCE_RMT; 04365 if (phonemode > 1) src = SOURCE_DPHONE; 04366 else if (phonemode) src = SOURCE_PHONE; 04367 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL); 04368 04369 switch(ret){ 04370 04371 case DC_INDETERMINATE: 04372 res = 0; 04373 break; 04374 04375 case DC_DOKEY: 04376 if (keyed) *keyed = 1; 04377 res = 0; 04378 break; 04379 04380 case DC_REQ_FLUSH: 04381 myrpt->dtmfidx = 0; 04382 myrpt->dtmfbuf[0] = 0; 04383 res = 0; 04384 break; 04385 04386 04387 case DC_COMPLETE: 04388 myrpt->dtmfbuf[0] = 0; 04389 myrpt->dtmfidx = -1; 04390 myrpt->dtmf_time_rem = 0; 04391 res = 1; 04392 break; 04393 04394 case DC_ERROR: 04395 default: 04396 myrpt->dtmfbuf[0] = 0; 04397 myrpt->dtmfidx = -1; 04398 myrpt->dtmf_time_rem = 0; 04399 res = 0; 04400 break; 04401 } 04402 04403 return res; 04404 }
static int handle_remote_phone_dtmf | ( | struct rpt * | myrpt, | |
char | c, | |||
char * | keyed, | |||
int | phonemode | |||
) | [static] |
Definition at line 4441 of file app_rpt.c.
References AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_safe_sleep(), DC_INDETERMINATE, rpt::endchar, handle_remote_dtmf_digit(), rpt::name, rpt::remchannel, rpt::remoterx, rpt::remotetx, rmt_telem_finish(), telem_lookup(), and rpt::txchannel.
04442 { 04443 int res; 04444 04445 04446 if (keyed && *keyed && (c == myrpt->endchar)) 04447 { 04448 *keyed = 0; 04449 return DC_INDETERMINATE; 04450 } 04451 04452 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode); 04453 if (res != 1) 04454 return res; 04455 myrpt->remotetx = 0; 04456 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); 04457 if (!myrpt->remoterx) 04458 { 04459 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY); 04460 } 04461 if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1; 04462 res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete"); 04463 rmt_telem_finish(myrpt,myrpt->remchannel); 04464 return res; 04465 }
char* key | ( | void | ) |
Returns the ASTERISK_GPL_KEY.
This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 6556 of file app_rpt.c.
References ASTERISK_GPL_KEY.
06557 { 06558 return ASTERISK_GPL_KEY; 06559 }
int load_module | ( | void | ) |
Initialize the module.
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 6534 of file app_rpt.c.
References ast_cli_register(), ast_pthread_create, ast_register_application(), cli_debug, rpt_exec(), and rpt_master().
06535 { 06536 ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL); 06537 06538 /* Register cli extensions */ 06539 ast_cli_register(&cli_debug); 06540 06541 return ast_register_application(app, rpt_exec, synopsis, descrip); 06542 }
static int multimode_bump_freq | ( | struct rpt * | myrpt, | |
int | interval | |||
) | [static] |
Definition at line 3461 of file app_rpt.c.
References multimode_bump_freq_ft897(), and rpt::remote.
Referenced by function_remote(), and service_scan().
03462 { 03463 if(!strcmp(myrpt->remote, remote_rig_ft897)) 03464 return multimode_bump_freq_ft897(myrpt, interval); 03465 else 03466 return -1; 03467 }
static int multimode_bump_freq_ft897 | ( | struct rpt * | myrpt, | |
int | interval | |||
) | [static] |
Definition at line 3370 of file app_rpt.c.
References check_freq_ft897(), rpt::freq, MAXREMSTR, set_freq_ft897(), and split_freq().
Referenced by multimode_bump_freq().
03371 { 03372 int m,d; 03373 char mhz[MAXREMSTR], decimals[MAXREMSTR]; 03374 03375 if(debug) 03376 printf("Before bump: %s\n", myrpt->freq); 03377 03378 if(split_freq(mhz, decimals, myrpt->freq)) 03379 return -1; 03380 03381 m = atoi(mhz); 03382 d = atoi(decimals); 03383 03384 d += (interval / 10); /* 10Hz resolution */ 03385 if(d < 0){ 03386 m--; 03387 d += 100000; 03388 } 03389 else if(d >= 100000){ 03390 m++; 03391 d -= 100000; 03392 } 03393 03394 if(check_freq_ft897(m, d, NULL)){ 03395 if(debug) 03396 printf("Bump freq invalid\n"); 03397 return -1; 03398 } 03399 03400 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d); 03401 03402 if(debug) 03403 printf("After bump: %s\n", myrpt->freq); 03404 03405 return set_freq_ft897(myrpt, myrpt->freq); 03406 }
static int multimode_capable | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 3450 of file app_rpt.c.
References rpt::remote.
Referenced by function_remote().
03451 { 03452 if(!strcmp(myrpt->remote, remote_rig_ft897)) 03453 return 1; 03454 return 0; 03455 }
static int myatoi | ( | char * | str | ) | [static] |
Definition at line 462 of file app_rpt.c.
Referenced by function_cop(), function_ilink(), function_remote(), function_status(), retrieve_astcfgint(), and rpt_do_debug().
00463 { 00464 int ret; 00465 00466 if (str == NULL) return -1; 00467 /* leave this %i alone, non-base-10 input is useful here */ 00468 if (sscanf(str,"%i",&ret) != 1) return -1; 00469 return ret; 00470 }
static int play_silence | ( | struct ast_channel * | chan, | |
int | duration | |||
) | [static] |
Definition at line 515 of file app_rpt.c.
References play_tone_pair().
Referenced by send_morse().
00516 { 00517 return play_tone_pair(chan, 0, 0, duration, 0); 00518 }
static int play_tone | ( | struct ast_channel * | chan, | |
int | freq, | |||
int | duration, | |||
int | amplitude | |||
) | [static] |
Definition at line 510 of file app_rpt.c.
References play_tone_pair().
Referenced by send_morse().
00511 { 00512 return play_tone_pair(chan, freq, 0, duration, amplitude); 00513 }
static int play_tone_pair | ( | struct ast_channel * | chan, | |
int | f1, | |||
int | f2, | |||
int | duration, | |||
int | amplitude | |||
) | [static] |
Definition at line 496 of file app_rpt.c.
References ast_safe_sleep(), ast_tonepair_start(), and ast_channel::generatordata.
Referenced by play_silence(), play_tone(), and send_tone_telemetry().
00497 { 00498 int res; 00499 00500 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude))) 00501 return res; 00502 00503 while(chan->generatordata) { 00504 if (ast_safe_sleep(chan,1)) return -1; 00505 } 00506 00507 return 0; 00508 }
static int rbi_mhztoband | ( | char * | str | ) | [static] |
Definition at line 2647 of file app_rpt.c.
Referenced by setrbi().
02648 { 02649 int i; 02650 02651 i = atoi(str) / 10; /* get the 10's of mhz */ 02652 switch(i) 02653 { 02654 case 2: 02655 return 10; 02656 case 5: 02657 return 11; 02658 case 14: 02659 return 2; 02660 case 22: 02661 return 3; 02662 case 44: 02663 return 4; 02664 case 124: 02665 return 0; 02666 case 125: 02667 return 1; 02668 case 126: 02669 return 8; 02670 case 127: 02671 return 5; 02672 case 128: 02673 return 6; 02674 case 129: 02675 return 7; 02676 default: 02677 break; 02678 } 02679 return -1; 02680 }
static void rbi_out | ( | struct rpt * | myrpt, | |
unsigned char * | data | |||
) | [static] |
Definition at line 2804 of file app_rpt.c.
References ast_log(), ast_channel::fds, LOG_WARNING, ast_channel::name, rbi_out_parallel(), and rpt::rxchannel.
Referenced by setrbi().
02805 { 02806 struct zt_radio_param r; 02807 02808 memset(&r,0,sizeof(struct zt_radio_param)); 02809 r.radpar = ZT_RADPAR_REMMODE; 02810 r.data = ZT_RADPAR_REM_RBI1; 02811 /* if setparam ioctl fails, its probably not a pciradio card */ 02812 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1) 02813 { 02814 rbi_out_parallel(myrpt,data); 02815 return; 02816 } 02817 r.radpar = ZT_RADPAR_REMCOMMAND; 02818 memcpy(&r.data,data,5); 02819 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1) 02820 { 02821 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->rxchannel->name); 02822 return; 02823 } 02824 }
static void rbi_out_parallel | ( | struct rpt * | myrpt, | |
unsigned char * | data | |||
) | [static] |
Definition at line 2778 of file app_rpt.c.
References rpt::iobase.
Referenced by rbi_out().
02779 { 02780 int i,j; 02781 unsigned char od,d; 02782 static volatile long long delayvar; 02783 02784 for(i = 0 ; i < 5 ; i++){ 02785 od = *data++; 02786 for(j = 0 ; j < 8 ; j++){ 02787 d = od & 1; 02788 outb(d,myrpt->iobase); 02789 /* >= 15 us */ 02790 for(delayvar = 1; delayvar < 15000; delayvar++); 02791 od >>= 1; 02792 outb(d | 2,myrpt->iobase); 02793 /* >= 30 us */ 02794 for(delayvar = 1; delayvar < 30000; delayvar++); 02795 outb(d,myrpt->iobase); 02796 /* >= 10 us */ 02797 for(delayvar = 1; delayvar < 10000; delayvar++); 02798 } 02799 } 02800 /* >= 50 us */ 02801 for(delayvar = 1; delayvar < 50000; delayvar++); 02802 }
static int rbi_pltocode | ( | char * | str | ) | [static] |
Definition at line 2683 of file app_rpt.c.
References s.
Referenced by setrbi().
02684 { 02685 int i; 02686 char *s; 02687 02688 s = strchr(str,'.'); 02689 i = 0; 02690 if (s) i = atoi(s + 1); 02691 i += atoi(str) * 10; 02692 switch(i) 02693 { 02694 case 670: 02695 return 0; 02696 case 719: 02697 return 1; 02698 case 744: 02699 return 2; 02700 case 770: 02701 return 3; 02702 case 797: 02703 return 4; 02704 case 825: 02705 return 5; 02706 case 854: 02707 return 6; 02708 case 885: 02709 return 7; 02710 case 915: 02711 return 8; 02712 case 948: 02713 return 9; 02714 case 974: 02715 return 10; 02716 case 1000: 02717 return 11; 02718 case 1035: 02719 return 12; 02720 case 1072: 02721 return 13; 02722 case 1109: 02723 return 14; 02724 case 1148: 02725 return 15; 02726 case 1188: 02727 return 16; 02728 case 1230: 02729 return 17; 02730 case 1273: 02731 return 18; 02732 case 1318: 02733 return 19; 02734 case 1365: 02735 return 20; 02736 case 1413: 02737 return 21; 02738 case 1462: 02739 return 22; 02740 case 1514: 02741 return 23; 02742 case 1567: 02743 return 24; 02744 case 1622: 02745 return 25; 02746 case 1679: 02747 return 26; 02748 case 1738: 02749 return 27; 02750 case 1799: 02751 return 28; 02752 case 1862: 02753 return 29; 02754 case 1928: 02755 return 30; 02756 case 2035: 02757 return 31; 02758 case 2107: 02759 return 32; 02760 case 2181: 02761 return 33; 02762 case 2257: 02763 return 34; 02764 case 2336: 02765 return 35; 02766 case 2418: 02767 return 36; 02768 case 2503: 02769 return 37; 02770 } 02771 return -1; 02772 }
static int retrieve_astcfgint | ( | char * | category, | |
char * | name, | |||
int | min, | |||
int | max, | |||
int | defl | |||
) | [static] |
Definition at line 776 of file app_rpt.c.
References ast_variable_retrieve(), cfg, myatoi(), and var.
Referenced by get_wait_interval(), rpt_master(), and telem_any().
00777 { 00778 char *var; 00779 int ret; 00780 00781 var = ast_variable_retrieve(cfg, category, name); 00782 if(var){ 00783 ret = myatoi(var); 00784 if(ret < min) 00785 ret = min; 00786 if(ret > max) 00787 ret = max; 00788 } 00789 else 00790 ret = defl; 00791 return ret; 00792 }
static int rmt_saycharstr | ( | struct rpt * | myrpt, | |
struct ast_channel * | chan, | |||
int | delay, | |||
char * | charstr | |||
) | [static] |
Definition at line 3598 of file app_rpt.c.
References rmt_telem_finish(), rmt_telem_start(), and saycharstr().
Referenced by function_remote().
03599 { 03600 int res; 03601 03602 res = rmt_telem_start(myrpt, chan, delay); 03603 03604 if(!res) 03605 res = saycharstr(chan, charstr); 03606 03607 if(!res) 03608 res = rmt_telem_finish(myrpt, chan); 03609 return res; 03610 }
static int rmt_sayfile | ( | struct rpt * | myrpt, | |
struct ast_channel * | chan, | |||
int | delay, | |||
char * | filename | |||
) | [static] |
Definition at line 3584 of file app_rpt.c.
References rmt_telem_finish(), rmt_telem_start(), and sayfile().
Referenced by function_remote().
03585 { 03586 int res; 03587 03588 res = rmt_telem_start(myrpt, chan, delay); 03589 03590 if(!res) 03591 res = sayfile(chan, filename); 03592 03593 if(!res) 03594 res = rmt_telem_finish(myrpt, chan); 03595 return res; 03596 }
static int rmt_telem_finish | ( | struct rpt * | myrpt, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 3561 of file app_rpt.c.
References AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_channel::fds, rpt::remchannel, rpt::remoterx, and rpt::txchannel.
Referenced by function_remote(), handle_remote_data(), handle_remote_phone_dtmf(), rmt_saycharstr(), and rmt_sayfile().
03562 { 03563 03564 struct zt_params par; 03565 03566 if (ioctl(myrpt->txchannel->fds[0],ZT_GET_PARAMS,&par) == -1) 03567 { 03568 return -1; 03569 03570 } 03571 if (!par.rxisoffhook) 03572 { 03573 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_UNKEY); 03574 myrpt->remoterx = 0; 03575 } 03576 else 03577 { 03578 myrpt->remoterx = 1; 03579 } 03580 return 0; 03581 }
static int rmt_telem_start | ( | struct rpt * | myrpt, | |
struct ast_channel * | chan, | |||
int | delay | |||
) | [static] |
Definition at line 3549 of file app_rpt.c.
References AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_safe_sleep(), rpt::remoterx, rpt::remotetx, and rpt::txchannel.
Referenced by function_remote(), rmt_saycharstr(), and rmt_sayfile().
03550 { 03551 myrpt->remotetx = 0; 03552 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); 03553 if (!myrpt->remoterx) 03554 ast_indicate(chan,AST_CONTROL_RADIO_KEY); 03555 if (ast_safe_sleep(chan, delay) == -1) 03556 return -1; 03557 return 0; 03558 }
static void* rpt | ( | void * | this | ) | [static] |
Definition at line 4527 of file app_rpt.c.
References ast_channel::_state, ast_channel::appl, ast_call(), ast_canmatch_extension(), ast_channel_setoption(), ast_check_hangup(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_exists_extension(), AST_FORMAT_SLINEAR, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frfree(), ast_hangup(), ast_indicate(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_RELAXDTMF, AST_OPTION_TONE_VERIFY, ast_pthread_create, AST_PTHREADT_STOP, ast_read(), ast_request(), ast_set_read_format(), ast_set_write_format(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_STATE_BUSY, AST_STATE_UP, ast_variable_retrieve(), ast_verbose(), ast_waitfor_n(), ast_write(), attempt_reconnect(), rpt::callmode, cfg, rpt_link::chan, rpt_tele::chan, rpt::cidx, rpt::cmdnode, collect_function_digits(), COMPLETE, rpt::conf, CONNECTED, rpt_link::connected, CONNFAIL, ast_frame::data, ast_channel::data, ast_frame::datalen, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, DISC_TIME, rpt_link::disced, rpt_link::disctime, rpt::disgorgetime, DTMF_TIMEOUT, rpt::dtmfbuf, rpt::dtmfidx, rpt_link::elaptime, rpt::enable, rpt::endchar, rpt::exten, rpt::exttx, ast_channel::fds, ast_frame::frametype, free, rpt::funcchar, handle_link_data(), handle_link_phone_dtmf(), rpt::hangtime, rpt_link::hasconnected, ID, IDTALKOVER, rpt::idtime, rpt::idtimer, rpt_link::isremote, rpt::keyed, rpt_link::killme, rpt_link::lastrx, rpt_link::lasttx, rpt::links, rpt::localtx, rpt::lock, LOG_NOTICE, LOG_WARNING, MAX_RETRIES, MAXCONNECTTIME, MAXDTMF, rpt_link::mode, rpt_tele::mode, MSWAIT, rpt::mustid, rpt::mydtmf, n, rpt_link::name, rpt::name, ast_channel::name, rpt_tele::next, rpt_link::next, option_verbose, rpt::ourcontext, rpt_link::outbound, rpt_link::pchan, rpt::pchannel, rpt_link::phonemode, rpt::politeid, rpt_link::prev, PROC, REDUNDANT_TX_TIME, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, REMDISC, rpt_link::retries, RETRY_TIMER_MS, rpt_link::retrytimer, rpt_link::retxtimer, rpt::retxtimer, rpt_call(), rpt::rpt_call_thread, rpt_telemetry(), rpt::rpt_thread, rpt::rxchanname, rpt::rxchannel, send_link_dtmf(), rpt::simple, SOURCE_RPT, rpt::stopgen, ast_frame::subclass, t, rpt::tailtimer, rpt::tele, TERM, TIMEOUT, rpt::tonotify, rpt::totime, rpt::totimer, rpt::tounkeyed, rpt::txchanname, rpt::txchannel, rpt::txconf, rpt::txpchannel, UNKEY, VERBOSE_PREFIX_3, and ast_channel::whentohangup.
04528 { 04529 struct rpt *myrpt = (struct rpt *)this; 04530 char *tele,*idtalkover; 04531 int ms = MSWAIT,lasttx=0,val,remrx=0,identqueued,nonidentqueued,res; 04532 struct ast_channel *who; 04533 ZT_CONFINFO ci; /* conference info */ 04534 time_t dtmf_time,t; 04535 struct rpt_link *l,*m; 04536 struct rpt_tele *telem; 04537 pthread_attr_t attr; 04538 char tmpstr[300]; 04539 char cmd[MAXDTMF+1] = ""; 04540 04541 04542 ast_mutex_lock(&myrpt->lock); 04543 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1); 04544 tele = strchr(tmpstr,'/'); 04545 if (!tele) 04546 { 04547 fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->rxchanname); 04548 ast_mutex_unlock(&myrpt->lock); 04549 myrpt->rpt_thread = AST_PTHREADT_STOP; 04550 pthread_exit(NULL); 04551 } 04552 *tele++ = 0; 04553 myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL); 04554 if (myrpt->rxchannel) 04555 { 04556 if (myrpt->rxchannel->_state == AST_STATE_BUSY) 04557 { 04558 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n"); 04559 ast_mutex_unlock(&myrpt->lock); 04560 ast_hangup(myrpt->rxchannel); 04561 myrpt->rpt_thread = AST_PTHREADT_STOP; 04562 pthread_exit(NULL); 04563 } 04564 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR); 04565 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR); 04566 myrpt->rxchannel->whentohangup = 0; 04567 myrpt->rxchannel->appl = "Apprpt"; 04568 myrpt->rxchannel->data = "(Repeater Rx)"; 04569 if (option_verbose > 2) 04570 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n", 04571 tmpstr,tele,myrpt->rxchannel->name); 04572 ast_call(myrpt->rxchannel,tele,999); 04573 if (myrpt->rxchannel->_state != AST_STATE_UP) 04574 { 04575 ast_mutex_unlock(&myrpt->lock); 04576 ast_hangup(myrpt->rxchannel); 04577 myrpt->rpt_thread = AST_PTHREADT_STOP; 04578 pthread_exit(NULL); 04579 } 04580 } 04581 else 04582 { 04583 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n"); 04584 ast_mutex_unlock(&myrpt->lock); 04585 myrpt->rpt_thread = AST_PTHREADT_STOP; 04586 pthread_exit(NULL); 04587 } 04588 if (myrpt->txchanname) 04589 { 04590 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1); 04591 tele = strchr(tmpstr,'/'); 04592 if (!tele) 04593 { 04594 fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->txchanname); 04595 ast_mutex_unlock(&myrpt->lock); 04596 ast_hangup(myrpt->rxchannel); 04597 myrpt->rpt_thread = AST_PTHREADT_STOP; 04598 pthread_exit(NULL); 04599 } 04600 *tele++ = 0; 04601 myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL); 04602 if (myrpt->txchannel) 04603 { 04604 if (myrpt->txchannel->_state == AST_STATE_BUSY) 04605 { 04606 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n"); 04607 ast_mutex_unlock(&myrpt->lock); 04608 ast_hangup(myrpt->txchannel); 04609 ast_hangup(myrpt->rxchannel); 04610 myrpt->rpt_thread = AST_PTHREADT_STOP; 04611 pthread_exit(NULL); 04612 } 04613 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR); 04614 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR); 04615 myrpt->txchannel->whentohangup = 0; 04616 myrpt->txchannel->appl = "Apprpt"; 04617 myrpt->txchannel->data = "(Repeater Tx)"; 04618 if (option_verbose > 2) 04619 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n", 04620 tmpstr,tele,myrpt->txchannel->name); 04621 ast_call(myrpt->txchannel,tele,999); 04622 if (myrpt->rxchannel->_state != AST_STATE_UP) 04623 { 04624 ast_mutex_unlock(&myrpt->lock); 04625 ast_hangup(myrpt->rxchannel); 04626 ast_hangup(myrpt->txchannel); 04627 myrpt->rpt_thread = AST_PTHREADT_STOP; 04628 pthread_exit(NULL); 04629 } 04630 } 04631 else 04632 { 04633 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n"); 04634 ast_mutex_unlock(&myrpt->lock); 04635 ast_hangup(myrpt->rxchannel); 04636 myrpt->rpt_thread = AST_PTHREADT_STOP; 04637 pthread_exit(NULL); 04638 } 04639 } 04640 else 04641 { 04642 myrpt->txchannel = myrpt->rxchannel; 04643 } 04644 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY); 04645 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); 04646 /* allocate a pseudo-channel thru asterisk */ 04647 myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL); 04648 if (!myrpt->pchannel) 04649 { 04650 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); 04651 ast_mutex_unlock(&myrpt->lock); 04652 if (myrpt->txchannel != myrpt->rxchannel) 04653 ast_hangup(myrpt->txchannel); 04654 ast_hangup(myrpt->rxchannel); 04655 myrpt->rpt_thread = AST_PTHREADT_STOP; 04656 pthread_exit(NULL); 04657 } 04658 /* make a conference for the tx */ 04659 ci.chan = 0; 04660 ci.confno = -1; /* make a new conf */ 04661 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER; 04662 /* first put the channel on the conference in proper mode */ 04663 if (ioctl(myrpt->txchannel->fds[0],ZT_SETCONF,&ci) == -1) 04664 { 04665 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 04666 ast_mutex_unlock(&myrpt->lock); 04667 ast_hangup(myrpt->pchannel); 04668 if (myrpt->txchannel != myrpt->rxchannel) 04669 ast_hangup(myrpt->txchannel); 04670 ast_hangup(myrpt->rxchannel); 04671 myrpt->rpt_thread = AST_PTHREADT_STOP; 04672 pthread_exit(NULL); 04673 } 04674 /* save tx conference number */ 04675 myrpt->txconf = ci.confno; 04676 /* make a conference for the pseudo */ 04677 ci.chan = 0; 04678 ci.confno = -1; /* make a new conf */ 04679 ci.confmode = ZT_CONF_CONFANNMON; 04680 /* first put the channel on the conference in announce mode */ 04681 if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1) 04682 { 04683 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 04684 ast_mutex_unlock(&myrpt->lock); 04685 ast_hangup(myrpt->pchannel); 04686 if (myrpt->txchannel != myrpt->rxchannel) 04687 ast_hangup(myrpt->txchannel); 04688 ast_hangup(myrpt->rxchannel); 04689 myrpt->rpt_thread = AST_PTHREADT_STOP; 04690 pthread_exit(NULL); 04691 } 04692 /* save pseudo channel conference number */ 04693 myrpt->conf = ci.confno; 04694 /* allocate a pseudo-channel thru asterisk */ 04695 myrpt->txpchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL); 04696 if (!myrpt->txpchannel) 04697 { 04698 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); 04699 ast_mutex_unlock(&myrpt->lock); 04700 ast_hangup(myrpt->pchannel); 04701 if (myrpt->txchannel != myrpt->rxchannel) 04702 ast_hangup(myrpt->txchannel); 04703 ast_hangup(myrpt->rxchannel); 04704 myrpt->rpt_thread = AST_PTHREADT_STOP; 04705 pthread_exit(NULL); 04706 } 04707 /* make a conference for the tx */ 04708 ci.chan = 0; 04709 ci.confno = myrpt->txconf; 04710 ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER ; 04711 /* first put the channel on the conference in proper mode */ 04712 if (ioctl(myrpt->txpchannel->fds[0],ZT_SETCONF,&ci) == -1) 04713 { 04714 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 04715 ast_mutex_unlock(&myrpt->lock); 04716 ast_hangup(myrpt->txpchannel); 04717 ast_hangup(myrpt->pchannel); 04718 if (myrpt->txchannel != myrpt->rxchannel) 04719 ast_hangup(myrpt->txchannel); 04720 ast_hangup(myrpt->rxchannel); 04721 myrpt->rpt_thread = AST_PTHREADT_STOP; 04722 pthread_exit(NULL); 04723 } 04724 /* Now, the idea here is to copy from the physical rx channel buffer 04725 into the pseudo tx buffer, and from the pseudo rx buffer into the 04726 tx channel buffer */ 04727 myrpt->links.next = &myrpt->links; 04728 myrpt->links.prev = &myrpt->links; 04729 myrpt->tailtimer = 0; 04730 myrpt->totimer = 0; 04731 myrpt->idtimer = myrpt->politeid; 04732 myrpt->mustid = 0; 04733 myrpt->callmode = 0; 04734 myrpt->tounkeyed = 0; 04735 myrpt->tonotify = 0; 04736 myrpt->retxtimer = 0; 04737 lasttx = 0; 04738 myrpt->keyed = 0; 04739 idtalkover = ast_variable_retrieve(cfg, myrpt->name, "idtalkover"); 04740 myrpt->dtmfidx = -1; 04741 myrpt->dtmfbuf[0] = 0; 04742 myrpt->rem_dtmfidx = -1; 04743 myrpt->rem_dtmfbuf[0] = 0; 04744 dtmf_time = 0; 04745 myrpt->rem_dtmf_time = 0; 04746 myrpt->enable = 1; 04747 myrpt->disgorgetime = 0; 04748 ast_mutex_unlock(&myrpt->lock); 04749 val = 0; 04750 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0); 04751 val = 1; 04752 ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0); 04753 while (ms >= 0) 04754 { 04755 struct ast_frame *f; 04756 struct ast_channel *cs[300]; 04757 int totx=0,elap=0,n,toexit=0; 04758 04759 /* DEBUG Dump */ 04760 if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){ 04761 struct rpt_link *zl; 04762 struct rpt_tele *zt; 04763 04764 myrpt->disgorgetime = 0; 04765 ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n"); 04766 ast_log(LOG_NOTICE,"totx = %d\n",totx); 04767 ast_log(LOG_NOTICE,"remrx = %d\n",remrx); 04768 ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx); 04769 ast_log(LOG_NOTICE,"elap = %d\n",elap); 04770 ast_log(LOG_NOTICE,"toexit = %d\n",toexit); 04771 04772 ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed); 04773 ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx); 04774 ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode); 04775 ast_log(LOG_NOTICE,"myrpt->enable = %d\n",myrpt->enable); 04776 ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid); 04777 ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed); 04778 ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify); 04779 ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer); 04780 ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer); 04781 ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer); 04782 04783 zl = myrpt->links.next; 04784 while(zl != &myrpt->links){ 04785 ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",zl->name); 04786 ast_log(LOG_NOTICE," link->lasttx %d\n",zl->lasttx); 04787 ast_log(LOG_NOTICE," link->lastrx %d\n",zl->lastrx); 04788 ast_log(LOG_NOTICE," link->connected %d\n",zl->connected); 04789 ast_log(LOG_NOTICE," link->hasconnected %d\n",zl->hasconnected); 04790 ast_log(LOG_NOTICE," link->outbound %d\n",zl->outbound); 04791 ast_log(LOG_NOTICE," link->disced %d\n",zl->disced); 04792 ast_log(LOG_NOTICE," link->killme %d\n",zl->killme); 04793 ast_log(LOG_NOTICE," link->disctime %ld\n",zl->disctime); 04794 ast_log(LOG_NOTICE," link->retrytimer %ld\n",zl->retrytimer); 04795 ast_log(LOG_NOTICE," link->retries = %d\n",zl->retries); 04796 04797 zl = zl->next; 04798 } 04799 04800 zt = myrpt->tele.next; 04801 if(zt != &myrpt->tele) 04802 ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n"); 04803 while(zt != &myrpt->tele){ 04804 ast_log(LOG_NOTICE," Telemetry mode: %d\n",zt->mode); 04805 zt = zt->next; 04806 } 04807 ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n"); 04808 04809 } 04810 04811 04812 04813 04814 04815 ast_mutex_lock(&myrpt->lock); 04816 if (ast_check_hangup(myrpt->rxchannel)) break; 04817 if (ast_check_hangup(myrpt->txchannel)) break; 04818 if (ast_check_hangup(myrpt->pchannel)) break; 04819 if (ast_check_hangup(myrpt->txpchannel)) break; 04820 myrpt->localtx = myrpt->keyed && (myrpt->dtmfidx == -1) && (!myrpt->cmdnode[0]); 04821 04822 /* If someone's connected, and they're transmitting from their end to us, set remrx true */ 04823 04824 l = myrpt->links.next; 04825 remrx = 0; 04826 while(l != &myrpt->links) 04827 { 04828 if (l->lastrx) remrx = 1; 04829 l = l->next; 04830 } 04831 04832 /* Create a "must_id" flag for the cleanup ID */ 04833 04834 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ; 04835 04836 /* Build a fresh totx from myrpt->keyed and autopatch activated */ 04837 04838 totx = myrpt->localtx || myrpt->callmode; 04839 04840 /* Traverse the telemetry list to see if there's an ID queued and if there is not an ID queued */ 04841 04842 identqueued = 0; 04843 nonidentqueued = 0; 04844 04845 telem = myrpt->tele.next; 04846 while(telem != &myrpt->tele) 04847 { 04848 if((telem->mode == ID) || (telem->mode == IDTALKOVER)){ 04849 identqueued = 1; 04850 } 04851 else 04852 nonidentqueued = 1; 04853 telem = telem->next; 04854 } 04855 04856 /* Add in any non-id telemetry */ 04857 04858 totx = totx || nonidentqueued; 04859 04860 /* Update external transmitter PTT state with everything but ID telemetry */ 04861 04862 myrpt->exttx = totx; 04863 04864 /* Add in ID telemetry to local transmitter */ 04865 04866 totx = totx || remrx || identqueued; 04867 04868 if (!totx) 04869 { 04870 myrpt->totimer = myrpt->totime; 04871 myrpt->tounkeyed = 0; 04872 myrpt->tonotify = 0; 04873 } 04874 else myrpt->tailtimer = myrpt->hangtime; 04875 totx = totx && myrpt->totimer; 04876 /* if timed-out and not said already, say it */ 04877 if ((!myrpt->totimer) && (!myrpt->tonotify)) 04878 { 04879 myrpt->tonotify = 1; 04880 ast_mutex_unlock(&myrpt->lock); 04881 rpt_telemetry(myrpt,TIMEOUT,NULL); 04882 ast_mutex_lock(&myrpt->lock); 04883 } 04884 /* if wants to transmit and in phone call, but timed out, 04885 reset time-out timer if keyed */ 04886 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed)) 04887 { 04888 myrpt->tounkeyed = 1; 04889 } 04890 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed) 04891 { 04892 myrpt->totimer = myrpt->totime; 04893 myrpt->tounkeyed = 0; 04894 myrpt->tonotify = 0; 04895 ast_mutex_unlock(&myrpt->lock); 04896 continue; 04897 } 04898 /* if timed-out and in circuit busy after call */ 04899 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4)) 04900 { 04901 myrpt->callmode = 0; 04902 } 04903 /* get rid of tail if timed out */ 04904 if (!myrpt->totimer) myrpt->tailtimer = 0; 04905 /* if not timed-out, add in tail */ 04906 if (myrpt->totimer) totx = totx || myrpt->tailtimer; 04907 /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */ 04908 if (identqueued && (myrpt->keyed || remrx) && idtalkover) { 04909 int hasid = 0,hastalkover = 0; 04910 04911 telem = myrpt->tele.next; 04912 while(telem != &myrpt->tele){ 04913 if(telem->mode == ID){ 04914 if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */ 04915 hasid = 1; 04916 } 04917 if (telem->mode == IDTALKOVER) hastalkover = 1; 04918 telem = telem->next; 04919 } 04920 ast_mutex_unlock(&myrpt->lock); 04921 if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL); /* Start Talkover ID */ 04922 ast_mutex_lock(&myrpt->lock); 04923 } 04924 /* Try to be polite */ 04925 /* If the repeater has been inactive for longer than the ID time, do an initial ID in the tail*/ 04926 /* If within 30 seconds of the time to ID, try do it in the tail */ 04927 /* else if at ID time limit, do it right over the top of them */ 04928 /* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */ 04929 if (((totx && (!myrpt->exttx) && (myrpt->idtimer <= myrpt->politeid) && myrpt->tailtimer)) || 04930 (myrpt->mustid && (!myrpt->idtimer))) 04931 { 04932 myrpt->mustid = 0; 04933 myrpt->idtimer = myrpt->idtime; /* Reset our ID timer */ 04934 ast_mutex_unlock(&myrpt->lock); 04935 rpt_telemetry(myrpt,ID,NULL); 04936 ast_mutex_lock(&myrpt->lock); 04937 } 04938 /* let telemetry transmit anyway (regardless of timeout) */ 04939 totx = totx || (myrpt->tele.next != &myrpt->tele); 04940 if (totx && (!lasttx)) 04941 { 04942 lasttx = 1; 04943 ast_mutex_unlock(&myrpt->lock); 04944 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY); 04945 ast_mutex_lock(&myrpt->lock); 04946 } 04947 totx = totx && myrpt->enable; 04948 if ((!totx) && lasttx) 04949 { 04950 lasttx = 0; 04951 ast_mutex_unlock(&myrpt->lock); 04952 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); 04953 ast_mutex_lock(&myrpt->lock); 04954 } 04955 time(&t); 04956 /* if DTMF timeout */ 04957 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((dtmf_time + DTMF_TIMEOUT) < t)) 04958 { 04959 myrpt->dtmfidx = -1; 04960 myrpt->dtmfbuf[0] = 0; 04961 } 04962 /* if remote DTMF timeout */ 04963 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t)) 04964 { 04965 myrpt->rem_dtmfidx = -1; 04966 myrpt->rem_dtmfbuf[0] = 0; 04967 } 04968 04969 /* Reconnect kludge */ 04970 l = myrpt->links.next; 04971 while(l != &myrpt->links) 04972 { 04973 if (l->killme) 04974 { 04975 /* remove from queue */ 04976 remque((struct qelem *) l); 04977 if (!strcmp(myrpt->cmdnode,l->name)) 04978 myrpt->cmdnode[0] = 0; 04979 ast_mutex_unlock(&myrpt->lock); 04980 /* hang-up on call to device */ 04981 if (l->chan) ast_hangup(l->chan); 04982 ast_hangup(l->pchan); 04983 free(l); 04984 ast_mutex_lock(&myrpt->lock); 04985 /* re-start link traversal */ 04986 l = myrpt->links.next; 04987 continue; 04988 } 04989 l = l->next; 04990 } 04991 n = 0; 04992 cs[n++] = myrpt->rxchannel; 04993 cs[n++] = myrpt->pchannel; 04994 cs[n++] = myrpt->txpchannel; 04995 if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel; 04996 l = myrpt->links.next; 04997 while(l != &myrpt->links) 04998 { 04999 if ((!l->killme) && (!l->disctime) && l->chan) 05000 { 05001 cs[n++] = l->chan; 05002 cs[n++] = l->pchan; 05003 } 05004 l = l->next; 05005 } 05006 ast_mutex_unlock(&myrpt->lock); 05007 ms = MSWAIT; 05008 who = ast_waitfor_n(cs,n,&ms); 05009 if (who == NULL) ms = 0; 05010 elap = MSWAIT - ms; 05011 ast_mutex_lock(&myrpt->lock); 05012 l = myrpt->links.next; 05013 while(l != &myrpt->links) 05014 { 05015 if (!l->lasttx) 05016 { 05017 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME) 05018 { 05019 l->retxtimer = 0; 05020 if (l->chan) ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY); 05021 } 05022 } else l->retxtimer = 0; 05023 #ifdef RECONNECT_KLUDGE 05024 if (l->disctime) /* Disconnect timer active on a channel ? */ 05025 { 05026 l->disctime -= elap; 05027 if (l->disctime <= 0) /* Disconnect timer expired on inbound channel ? */ 05028 l->disctime = 0; /* Yep */ 05029 } 05030 05031 if (l->retrytimer) 05032 { 05033 l->retrytimer -= elap; 05034 if (l->retrytimer < 0) l->retrytimer = 0; 05035 } 05036 #endif 05037 /* ignore non-timing channels */ 05038 if (l->elaptime < 0) 05039 { 05040 l = l->next; 05041 continue; 05042 } 05043 l->elaptime += elap; 05044 /* if connection has taken too long */ 05045 if ((l->elaptime > MAXCONNECTTIME) && 05046 ((!l->chan) || (l->chan->_state != AST_STATE_UP))) 05047 { 05048 l->elaptime = 0; 05049 ast_mutex_unlock(&myrpt->lock); 05050 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV); 05051 #ifndef RECONNECT_KLUDGE 05052 rpt_telemetry(myrpt,CONNFAIL,l); 05053 #endif 05054 ast_mutex_lock(&myrpt->lock); 05055 break; 05056 } 05057 #ifdef RECONNECT_KLUDGE 05058 if ((!l->chan) && (!l->retrytimer) && l->outbound && 05059 (l->retries++ < MAX_RETRIES) && (l->hasconnected)) 05060 { 05061 if (l->chan) ast_hangup(l->chan); 05062 ast_mutex_unlock(&myrpt->lock); 05063 if ((l->name[0] != '0') && (!l->isremote)) 05064 { 05065 l->retrytimer = MAX_RETRIES + 1; 05066 } 05067 else 05068 { 05069 if (attempt_reconnect(myrpt,l) == -1) 05070 { 05071 l->retrytimer = RETRY_TIMER_MS; 05072 } 05073 } 05074 ast_mutex_lock(&myrpt->lock); 05075 break; 05076 } 05077 if ((!l->chan) && (!l->retrytimer) && l->outbound && 05078 (l->retries >= MAX_RETRIES)) 05079 { 05080 /* remove from queue */ 05081 remque((struct qelem *) l); 05082 if (!strcmp(myrpt->cmdnode,l->name)) 05083 myrpt->cmdnode[0] = 0; 05084 ast_mutex_unlock(&myrpt->lock); 05085 if (l->name[0] != '0') 05086 { 05087 if (!l->hasconnected) 05088 rpt_telemetry(myrpt,CONNFAIL,l); 05089 else rpt_telemetry(myrpt,REMDISC,l); 05090 } 05091 /* hang-up on call to device */ 05092 ast_hangup(l->pchan); 05093 free(l); 05094 ast_mutex_lock(&myrpt->lock); 05095 break; 05096 } 05097 if ((!l->chan) && (!l->disctime) && (!l->outbound)) 05098 { 05099 /* remove from queue */ 05100 remque((struct qelem *) l); 05101 if (!strcmp(myrpt->cmdnode,l->name)) 05102 myrpt->cmdnode[0] = 0; 05103 ast_mutex_unlock(&myrpt->lock); 05104 if (l->name[0] != '0') 05105 { 05106 rpt_telemetry(myrpt,REMDISC,l); 05107 } 05108 /* hang-up on call to device */ 05109 ast_hangup(l->pchan); 05110 free(l); 05111 ast_mutex_lock(&myrpt->lock); 05112 break; 05113 } 05114 #endif 05115 l = l->next; 05116 } 05117 if (myrpt->tailtimer) myrpt->tailtimer -= elap; 05118 if (myrpt->tailtimer < 0) myrpt->tailtimer = 0; 05119 if (myrpt->totimer) myrpt->totimer -= elap; 05120 if (myrpt->totimer < 0) myrpt->totimer = 0; 05121 if (myrpt->idtimer) myrpt->idtimer -= elap; 05122 if (myrpt->idtimer < 0) myrpt->idtimer = 0; 05123 ast_mutex_unlock(&myrpt->lock); 05124 if (!ms) continue; 05125 if (who == myrpt->rxchannel) /* if it was a read from rx */ 05126 { 05127 f = ast_read(myrpt->rxchannel); 05128 if (!f) 05129 { 05130 if (debug) printf("@@@@ rpt:Hung Up\n"); 05131 break; 05132 } 05133 if (f->frametype == AST_FRAME_VOICE) 05134 { 05135 if (!myrpt->localtx) 05136 memset(f->data,0,f->datalen); 05137 ast_write(myrpt->pchannel,f); 05138 } 05139 else if (f->frametype == AST_FRAME_DTMF) 05140 { 05141 char c; 05142 05143 c = (char) f->subclass; /* get DTMF char */ 05144 ast_frfree(f); 05145 if (!myrpt->keyed) continue; 05146 if (c == myrpt->endchar) 05147 { 05148 /* if in simple mode, kill autopatch */ 05149 if (myrpt->simple && myrpt->callmode) 05150 { 05151 ast_mutex_lock(&myrpt->lock); 05152 myrpt->callmode = 0; 05153 ast_mutex_unlock(&myrpt->lock); 05154 rpt_telemetry(myrpt,TERM,NULL); 05155 continue; 05156 } 05157 ast_mutex_lock(&myrpt->lock); 05158 myrpt->stopgen = 1; 05159 if (myrpt->cmdnode[0]) 05160 { 05161 myrpt->cmdnode[0] = 0; 05162 myrpt->dtmfidx = -1; 05163 myrpt->dtmfbuf[0] = 0; 05164 ast_mutex_unlock(&myrpt->lock); 05165 rpt_telemetry(myrpt,COMPLETE,NULL); 05166 } else ast_mutex_unlock(&myrpt->lock); 05167 continue; 05168 } 05169 ast_mutex_lock(&myrpt->lock); 05170 if (myrpt->cmdnode[0]) 05171 { 05172 ast_mutex_unlock(&myrpt->lock); 05173 send_link_dtmf(myrpt,c); 05174 continue; 05175 } 05176 if (!myrpt->simple) 05177 { 05178 if (c == myrpt->funcchar) 05179 { 05180 myrpt->dtmfidx = 0; 05181 myrpt->dtmfbuf[myrpt->dtmfidx] = 0; 05182 ast_mutex_unlock(&myrpt->lock); 05183 time(&dtmf_time); 05184 continue; 05185 } 05186 else if ((c != myrpt->endchar) && (myrpt->dtmfidx >= 0)) 05187 { 05188 time(&dtmf_time); 05189 05190 if (myrpt->dtmfidx < MAXDTMF) 05191 { 05192 myrpt->dtmfbuf[myrpt->dtmfidx++] = c; 05193 myrpt->dtmfbuf[myrpt->dtmfidx] = 0; 05194 05195 strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1); 05196 05197 ast_mutex_unlock(&myrpt->lock); 05198 res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL); 05199 ast_mutex_lock(&myrpt->lock); 05200 05201 switch(res){ 05202 05203 case DC_INDETERMINATE: 05204 break; 05205 05206 case DC_REQ_FLUSH: 05207 myrpt->dtmfidx = 0; 05208 myrpt->dtmfbuf[0] = 0; 05209 break; 05210 05211 05212 case DC_COMPLETE: 05213 myrpt->dtmfbuf[0] = 0; 05214 myrpt->dtmfidx = -1; 05215 dtmf_time = 0; 05216 break; 05217 05218 case DC_ERROR: 05219 default: 05220 myrpt->dtmfbuf[0] = 0; 05221 myrpt->dtmfidx = -1; 05222 dtmf_time = 0; 05223 break; 05224 } 05225 if(res != DC_INDETERMINATE) { 05226 ast_mutex_unlock(&myrpt->lock); 05227 continue; 05228 } 05229 } 05230 } 05231 } 05232 else /* if simple */ 05233 { 05234 if ((!myrpt->callmode) && (c == myrpt->funcchar)) 05235 { 05236 myrpt->callmode = 1; 05237 myrpt->cidx = 0; 05238 myrpt->exten[myrpt->cidx] = 0; 05239 ast_mutex_unlock(&myrpt->lock); 05240 pthread_attr_init(&attr); 05241 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05242 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt); 05243 continue; 05244 } 05245 } 05246 if (myrpt->callmode == 1) 05247 { 05248 myrpt->exten[myrpt->cidx++] = c; 05249 myrpt->exten[myrpt->cidx] = 0; 05250 /* if this exists */ 05251 if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) 05252 { 05253 myrpt->callmode = 2; 05254 ast_mutex_unlock(&myrpt->lock); 05255 rpt_telemetry(myrpt,PROC,NULL); 05256 continue; 05257 } 05258 /* if can continue, do so */ 05259 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) 05260 { 05261 /* call has failed, inform user */ 05262 myrpt->callmode = 4; 05263 } 05264 ast_mutex_unlock(&myrpt->lock); 05265 continue; 05266 } 05267 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) 05268 { 05269 myrpt->mydtmf = c; 05270 } 05271 ast_mutex_unlock(&myrpt->lock); 05272 continue; 05273 } 05274 else if (f->frametype == AST_FRAME_CONTROL) 05275 { 05276 if (f->subclass == AST_CONTROL_HANGUP) 05277 { 05278 if (debug) printf("@@@@ rpt:Hung Up\n"); 05279 ast_frfree(f); 05280 break; 05281 } 05282 /* if RX key */ 05283 if (f->subclass == AST_CONTROL_RADIO_KEY) 05284 { 05285 if (debug) printf("@@@@ rx key\n"); 05286 myrpt->keyed = 1; 05287 } 05288 /* if RX un-key */ 05289 if (f->subclass == AST_CONTROL_RADIO_UNKEY) 05290 { 05291 if (debug) printf("@@@@ rx un-key\n"); 05292 if(myrpt->keyed) { 05293 rpt_telemetry(myrpt,UNKEY,NULL); 05294 } 05295 myrpt->keyed = 0; 05296 } 05297 } 05298 ast_frfree(f); 05299 continue; 05300 } 05301 if (who == myrpt->pchannel) /* if it was a read from pseudo */ 05302 { 05303 f = ast_read(myrpt->pchannel); 05304 if (!f) 05305 { 05306 if (debug) printf("@@@@ rpt:Hung Up\n"); 05307 break; 05308 } 05309 if (f->frametype == AST_FRAME_VOICE) 05310 { 05311 ast_write(myrpt->txpchannel,f); 05312 } 05313 if (f->frametype == AST_FRAME_CONTROL) 05314 { 05315 if (f->subclass == AST_CONTROL_HANGUP) 05316 { 05317 if (debug) printf("@@@@ rpt:Hung Up\n"); 05318 ast_frfree(f); 05319 break; 05320 } 05321 } 05322 ast_frfree(f); 05323 continue; 05324 } 05325 if (who == myrpt->txchannel) /* if it was a read from tx */ 05326 { 05327 f = ast_read(myrpt->txchannel); 05328 if (!f) 05329 { 05330 if (debug) printf("@@@@ rpt:Hung Up\n"); 05331 break; 05332 } 05333 if (f->frametype == AST_FRAME_CONTROL) 05334 { 05335 if (f->subclass == AST_CONTROL_HANGUP) 05336 { 05337 if (debug) printf("@@@@ rpt:Hung Up\n"); 05338 ast_frfree(f); 05339 break; 05340 } 05341 } 05342 ast_frfree(f); 05343 continue; 05344 } 05345 toexit = 0; 05346 ast_mutex_lock(&myrpt->lock); 05347 l = myrpt->links.next; 05348 while(l != &myrpt->links) 05349 { 05350 if (l->disctime) 05351 { 05352 l = l->next; 05353 continue; 05354 } 05355 if (who == l->chan) /* if it was a read from rx */ 05356 { 05357 remrx = 0; 05358 /* see if any other links are receiving */ 05359 m = myrpt->links.next; 05360 while(m != &myrpt->links) 05361 { 05362 /* if not us, count it */ 05363 if ((m != l) && (m->lastrx)) remrx = 1; 05364 m = m->next; 05365 } 05366 ast_mutex_unlock(&myrpt->lock); 05367 totx = (((l->isremote) ? myrpt->localtx : 05368 myrpt->exttx) || remrx) && l->mode; 05369 if (l->chan && (l->lasttx != totx)) 05370 { 05371 if (totx) 05372 { 05373 ast_indicate(l->chan,AST_CONTROL_RADIO_KEY); 05374 } 05375 else 05376 { 05377 ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY); 05378 } 05379 } 05380 l->lasttx = totx; 05381 f = ast_read(l->chan); 05382 if (!f) 05383 { 05384 #ifdef RECONNECT_KLUDGE 05385 if ((!l->disced) && (!l->outbound)) 05386 { 05387 if ((l->name[0] == '0') || l->isremote) 05388 l->disctime = 1; 05389 else 05390 l->disctime = DISC_TIME; 05391 ast_mutex_lock(&myrpt->lock); 05392 ast_hangup(l->chan); 05393 l->chan = 0; 05394 break; 05395 } 05396 05397 if (l->retrytimer) 05398 { 05399 ast_mutex_lock(&myrpt->lock); 05400 break; 05401 } 05402 if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected)) 05403 { 05404 ast_mutex_lock(&myrpt->lock); 05405 ast_hangup(l->chan); 05406 l->chan = 0; 05407 ast_mutex_unlock(&myrpt->lock); 05408 if (attempt_reconnect(myrpt,l) == -1) 05409 { 05410 l->retrytimer = RETRY_TIMER_MS; 05411 } 05412 ast_mutex_lock(&myrpt->lock); 05413 break; 05414 } 05415 #endif 05416 ast_mutex_lock(&myrpt->lock); 05417 /* remove from queue */ 05418 remque((struct qelem *) l); 05419 if (!strcmp(myrpt->cmdnode,l->name)) 05420 myrpt->cmdnode[0] = 0; 05421 ast_mutex_unlock(&myrpt->lock); 05422 if (!l->hasconnected) 05423 rpt_telemetry(myrpt,CONNFAIL,l); 05424 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l); 05425 /* hang-up on call to device */ 05426 ast_hangup(l->chan); 05427 ast_hangup(l->pchan); 05428 free(l); 05429 ast_mutex_lock(&myrpt->lock); 05430 break; 05431 } 05432 if (f->frametype == AST_FRAME_VOICE) 05433 { 05434 if (l->phonemode && (!l->lastrx)) 05435 { 05436 memset(f->data,0,f->datalen); 05437 } 05438 ast_write(l->pchan,f); 05439 } 05440 if (f->frametype == AST_FRAME_TEXT) 05441 { 05442 handle_link_data(myrpt,l,f->data); 05443 } 05444 if (f->frametype == AST_FRAME_DTMF) 05445 { 05446 handle_link_phone_dtmf(myrpt,l,f->subclass); 05447 } 05448 if (f->frametype == AST_FRAME_CONTROL) 05449 { 05450 if (f->subclass == AST_CONTROL_ANSWER) 05451 { 05452 char lconnected = l->connected; 05453 l->connected = 1; 05454 l->hasconnected = 1; 05455 l->elaptime = -1; 05456 l->retries = 0; 05457 if (!lconnected) rpt_telemetry(myrpt,CONNECTED,l); 05458 } 05459 /* if RX key */ 05460 if (f->subclass == AST_CONTROL_RADIO_KEY) 05461 { 05462 if (debug) printf("@@@@ rx key\n"); 05463 l->lastrx = 1; 05464 } 05465 /* if RX un-key */ 05466 if (f->subclass == AST_CONTROL_RADIO_UNKEY) 05467 { 05468 if (debug) printf("@@@@ rx un-key\n"); 05469 l->lastrx = 0; 05470 } 05471 if (f->subclass == AST_CONTROL_HANGUP) 05472 { 05473 ast_frfree(f); 05474 #ifdef RECONNECT_KLUDGE 05475 if ((!l->outbound) && (!l->disced)) 05476 { 05477 if ((l->name[0] == '0') || l->isremote) 05478 l->disctime = 1; 05479 else 05480 l->disctime = DISC_TIME; 05481 ast_mutex_lock(&myrpt->lock); 05482 ast_hangup(l->chan); 05483 l->chan = 0; 05484 break; 05485 } 05486 if (l->retrytimer) 05487 { 05488 ast_mutex_lock(&myrpt->lock); 05489 break; 05490 } 05491 if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected)) 05492 { 05493 ast_mutex_lock(&myrpt->lock); 05494 ast_hangup(l->chan); 05495 l->chan = 0; 05496 ast_mutex_unlock(&myrpt->lock); 05497 if (attempt_reconnect(myrpt,l) == -1) 05498 { 05499 l->retrytimer = RETRY_TIMER_MS; 05500 } 05501 ast_mutex_lock(&myrpt->lock); 05502 break; 05503 } 05504 #endif 05505 ast_mutex_lock(&myrpt->lock); 05506 /* remove from queue */ 05507 remque((struct qelem *) l); 05508 if (!strcmp(myrpt->cmdnode,l->name)) 05509 myrpt->cmdnode[0] = 0; 05510 ast_mutex_unlock(&myrpt->lock); 05511 if (!l->hasconnected) 05512 rpt_telemetry(myrpt,CONNFAIL,l); 05513 else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l); 05514 /* hang-up on call to device */ 05515 ast_hangup(l->chan); 05516 ast_hangup(l->pchan); 05517 free(l); 05518 ast_mutex_lock(&myrpt->lock); 05519 break; 05520 } 05521 } 05522 ast_frfree(f); 05523 ast_mutex_lock(&myrpt->lock); 05524 break; 05525 } 05526 if (who == l->pchan) 05527 { 05528 ast_mutex_unlock(&myrpt->lock); 05529 f = ast_read(l->pchan); 05530 if (!f) 05531 { 05532 if (debug) printf("@@@@ rpt:Hung Up\n"); 05533 toexit = 1; 05534 ast_mutex_lock(&myrpt->lock); 05535 break; 05536 } 05537 if (f->frametype == AST_FRAME_VOICE) 05538 { 05539 if (l->chan) ast_write(l->chan,f); 05540 } 05541 if (f->frametype == AST_FRAME_CONTROL) 05542 { 05543 if (f->subclass == AST_CONTROL_HANGUP) 05544 { 05545 if (debug) printf("@@@@ rpt:Hung Up\n"); 05546 ast_frfree(f); 05547 toexit = 1; 05548 ast_mutex_lock(&myrpt->lock); 05549 break; 05550 } 05551 } 05552 ast_frfree(f); 05553 ast_mutex_lock(&myrpt->lock); 05554 break; 05555 } 05556 l = l->next; 05557 } 05558 ast_mutex_unlock(&myrpt->lock); 05559 if (toexit) break; 05560 if (who == myrpt->txpchannel) /* if it was a read from remote tx */ 05561 { 05562 f = ast_read(myrpt->txpchannel); 05563 if (!f) 05564 { 05565 if (debug) printf("@@@@ rpt:Hung Up\n"); 05566 break; 05567 } 05568 if (f->frametype == AST_FRAME_CONTROL) 05569 { 05570 if (f->subclass == AST_CONTROL_HANGUP) 05571 { 05572 if (debug) printf("@@@@ rpt:Hung Up\n"); 05573 ast_frfree(f); 05574 break; 05575 } 05576 } 05577 ast_frfree(f); 05578 continue; 05579 } 05580 } 05581 usleep(100000); 05582 ast_hangup(myrpt->pchannel); 05583 ast_hangup(myrpt->txpchannel); 05584 if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel); 05585 ast_hangup(myrpt->rxchannel); 05586 ast_mutex_lock(&myrpt->lock); 05587 l = myrpt->links.next; 05588 while(l != &myrpt->links) 05589 { 05590 struct rpt_link *ll = l; 05591 /* remove from queue */ 05592 remque((struct qelem *) l); 05593 /* hang-up on call to device */ 05594 if (l->chan) ast_hangup(l->chan); 05595 ast_hangup(l->pchan); 05596 l = l->next; 05597 free(ll); 05598 } 05599 ast_mutex_unlock(&myrpt->lock); 05600 if (debug) printf("@@@@ rpt:Hung up channel\n"); 05601 myrpt->rpt_thread = AST_PTHREADT_STOP; 05602 pthread_exit(NULL); 05603 return NULL; 05604 }
static void* rpt_call | ( | void * | this | ) | [static] |
Definition at line 1528 of file app_rpt.c.
References ast_channel::accountcode, rpt::acctcode, ast_callerid_parse(), ast_channel_undefer_dtmf(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_request(), ast_safe_sleep(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_write(), rpt::callmode, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, rpt::cidx, rpt::conf, ast_channel::context, ast_frame::data, ast_frame::datalen, rpt::exten, ast_channel::exten, ast_channel::fds, ast_frame::frametype, free, rpt::lock, LOG_WARNING, ast_frame::mallocd, MSWAIT, rpt::mydtmf, name, ast_frame::offset, rpt::ourcallerid, rpt::ourcontext, ast_channel::pbx, ast_channel::priority, ast_frame::samples, strdup, ast_frame::subclass, and rpt::tonezone.
Referenced by function_autopatchup(), and rpt().
01529 { 01530 ZT_CONFINFO ci; /* conference info */ 01531 struct rpt *myrpt = (struct rpt *)this; 01532 int res; 01533 struct ast_frame wf; 01534 int stopped,congstarted; 01535 struct ast_channel *mychannel,*genchannel; 01536 01537 myrpt->mydtmf = 0; 01538 /* allocate a pseudo-channel thru asterisk */ 01539 mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL); 01540 if (!mychannel) 01541 { 01542 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); 01543 pthread_exit(NULL); 01544 } 01545 ci.chan = 0; 01546 ci.confno = myrpt->conf; /* use the pseudo conference */ 01547 ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER 01548 | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER; 01549 /* first put the channel on the conference */ 01550 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1) 01551 { 01552 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 01553 ast_hangup(mychannel); 01554 myrpt->callmode = 0; 01555 pthread_exit(NULL); 01556 } 01557 /* allocate a pseudo-channel thru asterisk */ 01558 genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL); 01559 if (!genchannel) 01560 { 01561 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); 01562 ast_hangup(mychannel); 01563 pthread_exit(NULL); 01564 } 01565 ci.chan = 0; 01566 ci.confno = myrpt->conf; 01567 ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER 01568 | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER; 01569 /* first put the channel on the conference */ 01570 if (ioctl(genchannel->fds[0],ZT_SETCONF,&ci) == -1) 01571 { 01572 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 01573 ast_hangup(mychannel); 01574 ast_hangup(genchannel); 01575 myrpt->callmode = 0; 01576 pthread_exit(NULL); 01577 } 01578 if (myrpt->tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->tonezone) == -1)) 01579 { 01580 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone); 01581 ast_hangup(mychannel); 01582 ast_hangup(genchannel); 01583 myrpt->callmode = 0; 01584 pthread_exit(NULL); 01585 } 01586 if (myrpt->tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->tonezone) == -1)) 01587 { 01588 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone); 01589 ast_hangup(mychannel); 01590 ast_hangup(genchannel); 01591 myrpt->callmode = 0; 01592 pthread_exit(NULL); 01593 } 01594 /* start dialtone */ 01595 if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0) 01596 { 01597 ast_log(LOG_WARNING, "Cannot start dialtone\n"); 01598 ast_hangup(mychannel); 01599 ast_hangup(genchannel); 01600 myrpt->callmode = 0; 01601 pthread_exit(NULL); 01602 } 01603 stopped = 0; 01604 congstarted = 0; 01605 while ((myrpt->callmode == 1) || (myrpt->callmode == 4)) 01606 { 01607 01608 if ((myrpt->callmode == 1) && (myrpt->cidx > 0) && (!stopped)) 01609 { 01610 stopped = 1; 01611 /* stop dial tone */ 01612 tone_zone_play_tone(mychannel->fds[0],-1); 01613 } 01614 if ((myrpt->callmode == 4) && (!congstarted)) 01615 { 01616 congstarted = 1; 01617 /* start congestion tone */ 01618 tone_zone_play_tone(mychannel->fds[0],ZT_TONE_CONGESTION); 01619 } 01620 res = ast_safe_sleep(mychannel, MSWAIT); 01621 if (res < 0) 01622 { 01623 ast_hangup(mychannel); 01624 ast_hangup(genchannel); 01625 ast_mutex_lock(&myrpt->lock); 01626 myrpt->callmode = 0; 01627 ast_mutex_unlock(&myrpt->lock); 01628 pthread_exit(NULL); 01629 } 01630 } 01631 /* stop any tone generation */ 01632 tone_zone_play_tone(mychannel->fds[0],-1); 01633 /* end if done */ 01634 if (!myrpt->callmode) 01635 { 01636 ast_hangup(mychannel); 01637 ast_hangup(genchannel); 01638 ast_mutex_lock(&myrpt->lock); 01639 myrpt->callmode = 0; 01640 ast_mutex_unlock(&myrpt->lock); 01641 pthread_exit(NULL); 01642 } 01643 01644 if (myrpt->ourcallerid && *myrpt->ourcallerid){ 01645 char *name, *loc, *instr; 01646 instr = strdup(myrpt->ourcallerid); 01647 if(instr){ 01648 ast_callerid_parse(instr, &name, &loc); 01649 if(loc){ 01650 if(mychannel->cid.cid_num) 01651 free(mychannel->cid.cid_num); 01652 mychannel->cid.cid_num = strdup(loc); 01653 } 01654 if(name){ 01655 if(mychannel->cid.cid_name) 01656 free(mychannel->cid.cid_name); 01657 mychannel->cid.cid_name = strdup(name); 01658 } 01659 free(instr); 01660 } 01661 } 01662 01663 strncpy(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1); 01664 strncpy(mychannel->context, myrpt->ourcontext, sizeof(mychannel->context) - 1); 01665 if (myrpt->acctcode) 01666 strncpy(mychannel->accountcode, myrpt->acctcode, sizeof(mychannel->accountcode) - 1); 01667 mychannel->priority = 1; 01668 ast_channel_undefer_dtmf(mychannel); 01669 if (ast_pbx_start(mychannel) < 0) 01670 { 01671 ast_log(LOG_WARNING, "Unable to start PBX!!\n"); 01672 ast_hangup(mychannel); 01673 ast_hangup(genchannel); 01674 ast_mutex_lock(&myrpt->lock); 01675 myrpt->callmode = 0; 01676 ast_mutex_unlock(&myrpt->lock); 01677 pthread_exit(NULL); 01678 } 01679 usleep(10000); 01680 ast_mutex_lock(&myrpt->lock); 01681 myrpt->callmode = 3; 01682 while(myrpt->callmode) 01683 { 01684 if ((!mychannel->pbx) && (myrpt->callmode != 4)) 01685 { 01686 myrpt->callmode = 4; 01687 ast_mutex_unlock(&myrpt->lock); 01688 /* start congestion tone */ 01689 tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION); 01690 ast_mutex_lock(&myrpt->lock); 01691 } 01692 if (myrpt->mydtmf) 01693 { 01694 wf.frametype = AST_FRAME_DTMF; 01695 wf.subclass = myrpt->mydtmf; 01696 wf.offset = 0; 01697 wf.mallocd = 0; 01698 wf.data = NULL; 01699 wf.datalen = 0; 01700 wf.samples = 0; 01701 ast_mutex_unlock(&myrpt->lock); 01702 ast_write(genchannel,&wf); 01703 ast_mutex_lock(&myrpt->lock); 01704 myrpt->mydtmf = 0; 01705 } 01706 ast_mutex_unlock(&myrpt->lock); 01707 usleep(MSWAIT * 1000); 01708 ast_mutex_lock(&myrpt->lock); 01709 } 01710 ast_mutex_unlock(&myrpt->lock); 01711 tone_zone_play_tone(genchannel->fds[0],-1); 01712 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV); 01713 ast_hangup(genchannel); 01714 ast_mutex_lock(&myrpt->lock); 01715 myrpt->callmode = 0; 01716 ast_mutex_unlock(&myrpt->lock); 01717 pthread_exit(NULL); 01718 }
static int rpt_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 476 of file app_rpt.c.
References ast_cli(), myatoi(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00477 { 00478 int newlevel; 00479 00480 if (argc != 4) 00481 return RESULT_SHOWUSAGE; 00482 newlevel = myatoi(argv[3]); 00483 if((newlevel < 0) || (newlevel > 7)) 00484 return RESULT_SHOWUSAGE; 00485 if(newlevel) 00486 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel); 00487 else 00488 ast_cli(fd, "app_rpt Debugging disabled\n"); 00489 00490 debug = newlevel; 00491 return RESULT_SUCCESS; 00492 }
static int rpt_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5830 of file app_rpt.c.
References ast_channel::_state, ahp, ast_channel::appl, ast_answer(), ast_call(), ast_callerid_parse(), ast_check_hangup(), AST_CONTROL_BUSY, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_exists_extension(), AST_FORMAT_SLINEAR, ast_gethostbyname(), ast_hangup(), ast_indicate(), ast_inet_ntoa(), ast_log(), ast_masq_park_call(), ast_mutex_lock(), ast_mutex_unlock(), AST_PBX_KEEPALIVE, ast_request(), ast_safe_sleep(), ast_set_callerid(), ast_set_read_format(), ast_set_write_format(), ast_shrink_phone_number(), AST_STATE_UP, ast_strlen_zero(), ast_variable_retrieve(), ast_verbose(), ast_waitfor_n(), rpt::callmode, cfg, rpt_link::chan, ast_channel::cid, ast_callerid::cid_num, rpt::conf, ast_channel::context, context, ast_channel::data, rpt_link::disced, rpt::dtmf_time_rem, rpt::dtmfbuf, rpt::dtmfidx, ast_channel::exten, exten, ast_channel::fds, free, rpt::hfscanmode, rpt::hfscanstatus, hp, rpt::iobase, rpt_link::killme, rpt::links, LOCAL_USER_ADD, rpt::lock, LOG_WARNING, malloc, MAX_RETRIES, MAXNODESTR, MSWAIT, n, rpt_link::name, rpt::name, ast_channel::name, name, rpt_link::next, rpt::nobusyout, rpt::nodes, option_verbose, pbx_substitute_variables_helper(), ast_channel::priority, REDUNDANT_TX_TIME, rpt::remote, rpt::remoteon, rpt::remoterx, rpt::remotetx, rpt_link::retries, rpt::retxtimer, REV_PATCH, rpt_telemetry(), rpt_vars, rpt::rxchanname, rpt::rxchannel, s, setrem(), strsep(), rpt::txchanname, rpt::txchannel, VERBOSE_PREFIX_3, and ast_channel::whentohangup.
Referenced by load_module().
05831 { 05832 int res=-1,i,rem_totx,n,phone_mode = 0; 05833 struct localuser *u; 05834 char tmp[256], keyed = 0; 05835 char *options,*stringp,*tele; 05836 struct rpt *myrpt; 05837 struct ast_frame *f; 05838 struct ast_channel *who; 05839 struct ast_channel *cs[20]; 05840 struct rpt_link *l; 05841 ZT_CONFINFO ci; /* conference info */ 05842 ZT_PARAMS par; 05843 int ms,elap; 05844 05845 if (ast_strlen_zero(data)) { 05846 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n"); 05847 return -1; 05848 } 05849 strncpy(tmp, (char *)data, sizeof(tmp)-1); 05850 stringp=tmp; 05851 strsep(&stringp, "|"); 05852 options = stringp; 05853 myrpt = NULL; 05854 /* see if we can find our specified one */ 05855 for(i = 0; i < nrpts; i++) 05856 { 05857 /* if name matches, assign it and exit loop */ 05858 if (!strcmp(tmp,rpt_vars[i].name)) 05859 { 05860 myrpt = &rpt_vars[i]; 05861 break; 05862 } 05863 } 05864 if (myrpt == NULL) 05865 { 05866 ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp); 05867 return -1; 05868 } 05869 05870 /* if not phone access, must be an IAX connection */ 05871 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R'))) 05872 { 05873 phone_mode = 1; 05874 if (*options == 'D') phone_mode = 2; 05875 ast_set_callerid(chan,"0","app_rpt user","0"); 05876 } 05877 else 05878 { 05879 if (strncmp(chan->name,"IAX2",4)) 05880 { 05881 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n"); 05882 return -1; 05883 } 05884 } 05885 if (options && (*options == 'R')) 05886 { 05887 05888 /* Parts of this section taken from app_parkandannounce */ 05889 char *return_context; 05890 int l, m, lot, timeout = 0; 05891 char tmp[256],*template; 05892 char *working, *context, *exten, *priority; 05893 char *s,*orig_s; 05894 05895 05896 ast_mutex_lock(&myrpt->lock); 05897 m = myrpt->callmode; 05898 ast_mutex_unlock(&myrpt->lock); 05899 05900 if ((!myrpt->nobusyout) && m) 05901 { 05902 if (chan->_state != AST_STATE_UP) 05903 { 05904 ast_indicate(chan,AST_CONTROL_BUSY); 05905 } 05906 while(ast_safe_sleep(chan,10000) != -1); 05907 return -1; 05908 } 05909 05910 if (chan->_state != AST_STATE_UP) 05911 { 05912 ast_answer(chan); 05913 } 05914 05915 l=strlen(options)+2; 05916 orig_s=malloc(l); 05917 if(!orig_s) { 05918 ast_log(LOG_WARNING, "Out of memory\n"); 05919 return -1; 05920 } 05921 s=orig_s; 05922 strncpy(s,options,l); 05923 05924 template=strsep(&s,"|"); 05925 if(!template) { 05926 ast_log(LOG_WARNING, "An announce template must be defined\n"); 05927 free(orig_s); 05928 return -1; 05929 } 05930 05931 if(s) { 05932 timeout = atoi(strsep(&s, "|")); 05933 timeout *= 1000; 05934 } 05935 05936 return_context = s; 05937 05938 if(return_context != NULL) { 05939 /* set the return context. Code borrowed from the Goto builtin */ 05940 05941 working = return_context; 05942 context = strsep(&working, "|"); 05943 exten = strsep(&working, "|"); 05944 if(!exten) { 05945 /* Only a priority in this one */ 05946 priority = context; 05947 exten = NULL; 05948 context = NULL; 05949 } else { 05950 priority = strsep(&working, "|"); 05951 if(!priority) { 05952 /* Only an extension and priority in this one */ 05953 priority = exten; 05954 exten = context; 05955 context = NULL; 05956 } 05957 } 05958 if(atoi(priority) < 0) { 05959 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority); 05960 free(orig_s); 05961 return -1; 05962 } 05963 /* At this point we have a priority and maybe an extension and a context */ 05964 chan->priority = atoi(priority); 05965 if(exten && strcasecmp(exten, "BYEXTENSION")) 05966 strncpy(chan->exten, exten, sizeof(chan->exten)-1); 05967 if(context) 05968 strncpy(chan->context, context, sizeof(chan->context)-1); 05969 } else { /* increment the priority by default*/ 05970 chan->priority++; 05971 } 05972 05973 if(option_verbose > 2) { 05974 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num); 05975 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { 05976 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n"); 05977 } 05978 } 05979 05980 /* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout 05981 before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */ 05982 05983 ast_masq_park_call(chan, NULL, timeout, &lot); 05984 05985 if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context); 05986 05987 snprintf(tmp,sizeof(tmp) - 1,"%d,%s",lot,template + 1); 05988 05989 rpt_telemetry(myrpt,REV_PATCH,tmp); 05990 05991 free(orig_s); 05992 05993 return 0; 05994 05995 } 05996 05997 if (!options) 05998 { 05999 struct ast_hostent ahp; 06000 struct hostent *hp; 06001 struct in_addr ia; 06002 char hisip[100],nodeip[100],*val, *s, *s1, *s2, *b,*b1; 06003 06004 /* look at callerid to see what node this comes from */ 06005 if (!chan->cid.cid_num) /* if doesn't have caller id */ 06006 { 06007 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp); 06008 return -1; 06009 } 06010 06011 /* get his IP from IAX2 module */ 06012 memset(hisip,0,sizeof(hisip)); 06013 pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1); 06014 if (!hisip[0]) 06015 { 06016 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n"); 06017 return -1; 06018 } 06019 06020 ast_callerid_parse(chan->cid.cid_num,&b,&b1); 06021 ast_shrink_phone_number(b1); 06022 if (!strcmp(myrpt->name,b1)) 06023 { 06024 ast_log(LOG_WARNING, "Trying to link to self!!\n"); 06025 return -1; 06026 } 06027 06028 if (*b1 < '1') 06029 { 06030 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1); 06031 return -1; 06032 } 06033 06034 06035 /* look for his reported node string */ 06036 val = ast_variable_retrieve(cfg, myrpt->nodes, b1); 06037 if (!val) 06038 { 06039 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1); 06040 return -1; 06041 } 06042 strncpy(tmp,val,sizeof(tmp) - 1); 06043 s = tmp; 06044 s1 = strsep(&s,","); 06045 s2 = strsep(&s,","); 06046 if (!s2) 06047 { 06048 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1); 06049 return -1; 06050 } 06051 if (strcmp(s2,"NONE")) { 06052 hp = ast_gethostbyname(s2, &ahp); 06053 if (!hp) 06054 { 06055 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2); 06056 return -1; 06057 } 06058 memcpy(&ia,hp->h_addr,sizeof(in_addr_t)); 06059 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia); 06060 if (strcmp(hisip,nodeip)) 06061 { 06062 char *s3 = strchr(s1,'@'); 06063 if (s3) s1 = s3 + 1; 06064 s3 = strchr(s1,'/'); 06065 if (s3) *s3 = 0; 06066 hp = ast_gethostbyname(s1, &ahp); 06067 if (!hp) 06068 { 06069 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1); 06070 return -1; 06071 } 06072 memcpy(&ia,hp->h_addr,sizeof(in_addr_t)); 06073 ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia); 06074 if (strcmp(hisip,nodeip)) 06075 { 06076 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip); 06077 return -1; 06078 } 06079 } 06080 } 06081 } 06082 06083 /* if is not a remote */ 06084 if (!myrpt->remote) 06085 { 06086 06087 char *b,*b1; 06088 06089 /* look at callerid to see what node this comes from */ 06090 if (!chan->cid.cid_num) /* if doesn't have caller id */ 06091 { 06092 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp); 06093 return -1; 06094 } 06095 06096 ast_callerid_parse(chan->cid.cid_num,&b,&b1); 06097 ast_shrink_phone_number(b1); 06098 if (!strcmp(myrpt->name,b1)) 06099 { 06100 ast_log(LOG_WARNING, "Trying to link to self!!\n"); 06101 return -1; 06102 } 06103 ast_mutex_lock(&myrpt->lock); 06104 l = myrpt->links.next; 06105 /* try to find this one in queue */ 06106 while(l != &myrpt->links) 06107 { 06108 if (l->name[0] == '0') 06109 { 06110 l = l->next; 06111 continue; 06112 } 06113 /* if found matching string */ 06114 if (!strcmp(l->name,b1)) break; 06115 l = l->next; 06116 } 06117 /* if found */ 06118 if (l != &myrpt->links) 06119 { 06120 l->killme = 1; 06121 l->retries = MAX_RETRIES + 1; 06122 l->disced = 2; 06123 ast_mutex_unlock(&myrpt->lock); 06124 usleep(500000); 06125 } else 06126 ast_mutex_unlock(&myrpt->lock); 06127 /* establish call in tranceive mode */ 06128 l = malloc(sizeof(struct rpt_link)); 06129 if (!l) 06130 { 06131 ast_log(LOG_WARNING, "Unable to malloc\n"); 06132 pthread_exit(NULL); 06133 } 06134 /* zero the silly thing */ 06135 memset((char *)l,0,sizeof(struct rpt_link)); 06136 l->mode = 1; 06137 strncpy(l->name,b1,MAXNODESTR - 1); 06138 l->isremote = 0; 06139 l->chan = chan; 06140 l->connected = 1; 06141 l->hasconnected = 1; 06142 l->phonemode = phone_mode; 06143 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR); 06144 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR); 06145 /* allocate a pseudo-channel thru asterisk */ 06146 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL); 06147 if (!l->pchan) 06148 { 06149 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); 06150 pthread_exit(NULL); 06151 } 06152 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR); 06153 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR); 06154 /* make a conference for the tx */ 06155 ci.chan = 0; 06156 ci.confno = myrpt->conf; 06157 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER; 06158 /* first put the channel on the conference in proper mode */ 06159 if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1) 06160 { 06161 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 06162 pthread_exit(NULL); 06163 } 06164 ast_mutex_lock(&myrpt->lock); 06165 if (phone_mode > 1) l->lastrx = 1; 06166 /* insert at end of queue */ 06167 insque((struct qelem *)l,(struct qelem *)myrpt->links.next); 06168 ast_mutex_unlock(&myrpt->lock); 06169 if (chan->_state != AST_STATE_UP) { 06170 ast_answer(chan); 06171 } 06172 return AST_PBX_KEEPALIVE; 06173 } 06174 ast_mutex_lock(&myrpt->lock); 06175 /* if remote, error if anyone else already linked */ 06176 if (myrpt->remoteon) 06177 { 06178 ast_mutex_unlock(&myrpt->lock); 06179 usleep(500000); 06180 if (myrpt->remoteon) 06181 { 06182 ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp); 06183 return -1; 06184 } 06185 ast_mutex_lock(&myrpt->lock); 06186 } 06187 myrpt->remoteon = 1; 06188 if (ioperm(myrpt->iobase,1,1) == -1) 06189 { 06190 ast_mutex_unlock(&myrpt->lock); 06191 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->iobase); 06192 return -1; 06193 } 06194 LOCAL_USER_ADD(u); 06195 tele = strchr(myrpt->rxchanname,'/'); 06196 if (!tele) 06197 { 06198 fprintf(stderr,"rpt:Dial number must be in format tech/number\n"); 06199 ast_mutex_unlock(&myrpt->lock); 06200 pthread_exit(NULL); 06201 } 06202 *tele++ = 0; 06203 myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL); 06204 if (myrpt->rxchannel) 06205 { 06206 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR); 06207 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR); 06208 myrpt->rxchannel->whentohangup = 0; 06209 myrpt->rxchannel->appl = "Apprpt"; 06210 myrpt->rxchannel->data = "(Link Rx)"; 06211 if (option_verbose > 2) 06212 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n", 06213 myrpt->rxchanname,tele,myrpt->rxchannel->name); 06214 ast_mutex_unlock(&myrpt->lock); 06215 ast_call(myrpt->rxchannel,tele,999); 06216 ast_mutex_lock(&myrpt->lock); 06217 } 06218 else 06219 { 06220 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n"); 06221 ast_mutex_unlock(&myrpt->lock); 06222 pthread_exit(NULL); 06223 } 06224 *--tele = '/'; 06225 if (myrpt->txchanname) 06226 { 06227 tele = strchr(myrpt->txchanname,'/'); 06228 if (!tele) 06229 { 06230 fprintf(stderr,"rpt:Dial number must be in format tech/number\n"); 06231 ast_mutex_unlock(&myrpt->lock); 06232 ast_hangup(myrpt->rxchannel); 06233 pthread_exit(NULL); 06234 } 06235 *tele++ = 0; 06236 myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL); 06237 if (myrpt->txchannel) 06238 { 06239 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR); 06240 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR); 06241 myrpt->txchannel->whentohangup = 0; 06242 myrpt->txchannel->appl = "Apprpt"; 06243 myrpt->txchannel->data = "(Link Tx)"; 06244 if (option_verbose > 2) 06245 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n", 06246 myrpt->txchanname,tele,myrpt->txchannel->name); 06247 ast_mutex_unlock(&myrpt->lock); 06248 ast_call(myrpt->txchannel,tele,999); 06249 ast_mutex_lock(&myrpt->lock); 06250 } 06251 else 06252 { 06253 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n"); 06254 ast_mutex_unlock(&myrpt->lock); 06255 ast_hangup(myrpt->rxchannel); 06256 pthread_exit(NULL); 06257 } 06258 *--tele = '/'; 06259 } 06260 else 06261 { 06262 myrpt->txchannel = myrpt->rxchannel; 06263 } 06264 myrpt->remoterx = 0; 06265 myrpt->remotetx = 0; 06266 myrpt->retxtimer = 0; 06267 myrpt->remoteon = 1; 06268 myrpt->dtmfidx = -1; 06269 myrpt->dtmfbuf[0] = 0; 06270 myrpt->dtmf_time_rem = 0; 06271 myrpt->hfscanmode = 0; 06272 myrpt->hfscanstatus = 0; 06273 ast_mutex_unlock(&myrpt->lock); 06274 setrem(myrpt); 06275 ast_set_write_format(chan, AST_FORMAT_SLINEAR); 06276 ast_set_read_format(chan, AST_FORMAT_SLINEAR); 06277 /* if we are on 2w loop and are a remote, turn EC on */ 06278 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel)) 06279 { 06280 i = 128; 06281 ioctl(myrpt->rxchannel->fds[0],ZT_ECHOCANCEL,&i); 06282 } 06283 if (chan->_state != AST_STATE_UP) { 06284 ast_answer(chan); 06285 } 06286 06287 if (ioctl(myrpt->txchannel->fds[0],ZT_GET_PARAMS,&par) != -1) 06288 { 06289 if (par.rxisoffhook) 06290 { 06291 ast_indicate(chan,AST_CONTROL_RADIO_KEY); 06292 myrpt->remoterx = 1; 06293 } 06294 } 06295 n = 0; 06296 cs[n++] = chan; 06297 cs[n++] = myrpt->rxchannel; 06298 if (myrpt->rxchannel != myrpt->txchannel) 06299 cs[n++] = myrpt->txchannel; 06300 for(;;) 06301 { 06302 if (ast_check_hangup(chan)) break; 06303 if (ast_check_hangup(myrpt->rxchannel)) break; 06304 ms = MSWAIT; 06305 who = ast_waitfor_n(cs,n,&ms); 06306 if (who == NULL) ms = 0; 06307 elap = MSWAIT - ms; 06308 if (!ms) continue; 06309 rem_totx = keyed; 06310 06311 06312 if ((!myrpt->remoterx) && (!myrpt->remotetx)) 06313 { 06314 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME) 06315 { 06316 myrpt->retxtimer = 0; 06317 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY); 06318 } 06319 } else myrpt->retxtimer = 0; 06320 if (rem_totx && (!myrpt->remotetx)) /* Remote base radio TX key */ 06321 { 06322 myrpt->remotetx = 1; 06323 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY); 06324 } 06325 if ((!rem_totx) && myrpt->remotetx) /* Remote base radio TX unkey */ 06326 { 06327 myrpt->remotetx = 0; 06328 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); 06329 } 06330 06331 if(myrpt->tunerequest && (!strcmp(myrpt->remote, remote_rig_ft897))){ /* ft-897 specific for now... */ 06332 myrpt->tunerequest = 0; 06333 set_mode_ft897(myrpt, REM_MODE_AM); 06334 simple_command_ft897(myrpt, 8); 06335 myrpt->remotetx = 0; 06336 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); 06337 if (!myrpt->remoterx) 06338 ast_indicate(chan, AST_CONTROL_RADIO_KEY); 06339 if(play_tone(chan, 800, 6000, 8192) == -1) 06340 break; 06341 06342 rmt_telem_finish(myrpt,chan); 06343 set_mode_ft897(myrpt, 0x88); 06344 setrem(myrpt); 06345 } 06346 06347 if (myrpt->hfscanmode){ 06348 myrpt->scantimer -= elap; 06349 if(myrpt->scantimer <= 0){ 06350 myrpt->scantimer = REM_SCANTIME; 06351 service_scan(myrpt); 06352 } 06353 } 06354 06355 06356 if (who == chan) /* if it was a read from incomming */ 06357 { 06358 f = ast_read(chan); 06359 if (!f) 06360 { 06361 if (debug) printf("@@@@ link:Hung Up\n"); 06362 break; 06363 } 06364 if (f->frametype == AST_FRAME_VOICE) 06365 { 06366 /* if not transmitting, zero-out audio */ 06367 if (!myrpt->remotetx) 06368 memset(f->data,0,f->datalen); 06369 ast_write(myrpt->txchannel,f); 06370 } 06371 if (f->frametype == AST_FRAME_DTMF) 06372 { 06373 myrpt->remchannel = chan; /* Save copy of channel */ 06374 if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1) 06375 { 06376 if (debug) printf("@@@@ rpt:Hung Up\n"); 06377 ast_frfree(f); 06378 break; 06379 } 06380 } 06381 if (f->frametype == AST_FRAME_TEXT) 06382 { 06383 myrpt->remchannel = chan; /* Save copy of channel */ 06384 if (handle_remote_data(myrpt,f->data) == -1) 06385 { 06386 if (debug) printf("@@@@ rpt:Hung Up\n"); 06387 ast_frfree(f); 06388 break; 06389 } 06390 } 06391 if (f->frametype == AST_FRAME_CONTROL) 06392 { 06393 if (f->subclass == AST_CONTROL_HANGUP) 06394 { 06395 if (debug) printf("@@@@ rpt:Hung Up\n"); 06396 ast_frfree(f); 06397 break; 06398 } 06399 /* if RX key */ 06400 if (f->subclass == AST_CONTROL_RADIO_KEY) 06401 { 06402 if (debug) printf("@@@@ rx key\n"); 06403 keyed = 1; 06404 } 06405 /* if RX un-key */ 06406 if (f->subclass == AST_CONTROL_RADIO_UNKEY) 06407 { 06408 if (debug) printf("@@@@ rx un-key\n"); 06409 keyed = 0; 06410 } 06411 } 06412 if (myrpt->hfscanstatus){ 06413 myrpt->remchannel = chan; /* Save copy of channel */ 06414 myrpt->remotetx = 0; 06415 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); 06416 if (!myrpt->remoterx) 06417 { 06418 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY); 06419 } 06420 if(myrpt->hfscanstatus < 0) { 06421 if (myrpt->hfscanstatus == -1) { 06422 if (ast_safe_sleep(myrpt->remchannel,1000) == -1) break; 06423 } 06424 sayfile(myrpt->remchannel, "rpt/stop"); 06425 } 06426 else 06427 { 06428 saynum(myrpt->remchannel, myrpt->hfscanstatus ); 06429 } 06430 rmt_telem_finish(myrpt,myrpt->remchannel); 06431 myrpt->hfscanstatus = 0; 06432 } 06433 ast_frfree(f); 06434 continue; 06435 } 06436 if (who == myrpt->rxchannel) /* if it was a read from radio */ 06437 { 06438 f = ast_read(myrpt->rxchannel); 06439 if (!f) 06440 { 06441 if (debug) printf("@@@@ link:Hung Up\n"); 06442 break; 06443 } 06444 if (f->frametype == AST_FRAME_VOICE) 06445 { 06446 if ((myrpt->remote) && (myrpt->remotetx)) 06447 memset(f->data,0,f->datalen); 06448 ast_write(chan,f); 06449 } 06450 else if (f->frametype == AST_FRAME_CONTROL) 06451 { 06452 if (f->subclass == AST_CONTROL_HANGUP) 06453 { 06454 if (debug) printf("@@@@ rpt:Hung Up\n"); 06455 ast_frfree(f); 06456 break; 06457 } 06458 /* if RX key */ 06459 if (f->subclass == AST_CONTROL_RADIO_KEY) 06460 { 06461 if (debug) printf("@@@@ remote rx key\n"); 06462 if (!myrpt->remotetx) 06463 { 06464 ast_indicate(chan,AST_CONTROL_RADIO_KEY); 06465 myrpt->remoterx = 1; 06466 } 06467 } 06468 /* if RX un-key */ 06469 if (f->subclass == AST_CONTROL_RADIO_UNKEY) 06470 { 06471 if (debug) printf("@@@@ remote rx un-key\n"); 06472 if (!myrpt->remotetx) 06473 { 06474 ast_indicate(chan,AST_CONTROL_RADIO_UNKEY); 06475 myrpt->remoterx = 0; 06476 } 06477 } 06478 } 06479 ast_frfree(f); 06480 continue; 06481 } 06482 if ((myrpt->rxchannel != myrpt->txchannel) && 06483 (who == myrpt->txchannel)) /* do this cuz you have to */ 06484 { 06485 f = ast_read(myrpt->txchannel); 06486 if (!f) 06487 { 06488 if (debug) printf("@@@@ link:Hung Up\n"); 06489 break; 06490 } 06491 if (f->frametype == AST_FRAME_CONTROL) 06492 { 06493 if (f->subclass == AST_CONTROL_HANGUP) 06494 { 06495 if (debug) printf("@@@@ rpt:Hung Up\n"); 06496 ast_frfree(f); 06497 break; 06498 } 06499 } 06500 ast_frfree(f); 06501 continue; 06502 } 06503 06504 } 06505 ast_mutex_lock(&myrpt->lock); 06506 if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel); 06507 ast_hangup(myrpt->rxchannel); 06508 myrpt->hfscanmode = 0; 06509 myrpt->hfscanstatus = 0; 06510 myrpt->remoteon = 0; 06511 ast_mutex_unlock(&myrpt->lock); 06512 closerem(myrpt); 06513 LOCAL_USER_REMOVE(u); 06514 return res; 06515 }
static void* rpt_master | ( | void * | ignore | ) | [static] |
Definition at line 5607 of file app_rpt.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_init(), ast_pthread_create, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_true(), ast_variable_browse(), ast_variable_retrieve(), cfg, DEFAULT_IOBASE, ENDCHAR, FUNCCHAR, FUNCTIONS, HANGTIME, IDTIME, lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, n, name, ast_variable::name, ast_variable::next, NODES, POLITEID, REM_MEDPWR, REM_MODE_FM, REM_SIMPLEX, retrieve_astcfgint(), rpt_vars, and TOTIME.
Referenced by load_module().
05608 { 05609 char *this,*val; 05610 struct ast_variable *vp; 05611 int i,j,n,longestnode; 05612 pthread_attr_t attr; 05613 05614 /* start with blank config */ 05615 memset(&rpt_vars,0,sizeof(rpt_vars)); 05616 05617 cfg = ast_config_load("rpt.conf"); 05618 if (!cfg) { 05619 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n"); 05620 pthread_exit(NULL); 05621 } 05622 05623 /* go thru all the specified repeaters */ 05624 this = NULL; 05625 n = 0; 05626 while((this = ast_category_browse(cfg,this)) != NULL) 05627 { 05628 05629 for(i = 0 ; i < strlen(this) ; i++){ 05630 if((this[i] < '0') || (this[i] > '9')) 05631 break; 05632 } 05633 if(i != strlen(this)) 05634 continue; /* Not a node defn */ 05635 05636 ast_log(LOG_DEBUG,"Loading config for repeater %s\n",this); 05637 ast_mutex_init(&rpt_vars[n].lock); 05638 rpt_vars[n].tele.next = &rpt_vars[n].tele; 05639 rpt_vars[n].tele.prev = &rpt_vars[n].tele; 05640 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL; 05641 rpt_vars[n].name = this; 05642 rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel"); 05643 rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel"); 05644 rpt_vars[n].ourcontext = ast_variable_retrieve(cfg,this,"context"); 05645 if (!rpt_vars[n].ourcontext) rpt_vars[n].ourcontext = this; 05646 rpt_vars[n].ourcallerid = ast_variable_retrieve(cfg,this,"callerid"); 05647 rpt_vars[n].acctcode = ast_variable_retrieve(cfg,this,"accountcode"); 05648 rpt_vars[n].ident = ast_variable_retrieve(cfg,this,"idrecording"); 05649 val = ast_variable_retrieve(cfg,this,"hangtime"); 05650 if (val) rpt_vars[n].hangtime = atoi(val); 05651 else rpt_vars[n].hangtime = HANGTIME; 05652 val = ast_variable_retrieve(cfg,this,"totime"); 05653 if (val) rpt_vars[n].totime = atoi(val); 05654 else rpt_vars[n].totime = TOTIME; 05655 05656 rpt_vars[n].idtime = retrieve_astcfgint( this, "idtime", 60000, 2400000, IDTIME); /* Enforce a min max */ 05657 rpt_vars[n].politeid = retrieve_astcfgint( this, "politeid", 30000, 300000, POLITEID); /* Enforce a min max */ 05658 rpt_vars[n].remote = ast_variable_retrieve(cfg,this,"remote"); 05659 rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone"); 05660 val = ast_variable_retrieve(cfg,this,"iobase"); 05661 /* do not use atoi() here, we need to be able to have 05662 the input specified in hex or decimal so we use 05663 sscanf with a %i */ 05664 if ((!val) || (sscanf(val,"%i",&rpt_vars[n].iobase) != 1)) 05665 rpt_vars[n].iobase = DEFAULT_IOBASE; 05666 rpt_vars[n].simple = 0; 05667 rpt_vars[n].functions = ast_variable_retrieve(cfg,this,"functions"); 05668 if (!rpt_vars[n].functions) 05669 { 05670 rpt_vars[n].functions = FUNCTIONS; 05671 rpt_vars[n].simple = 1; 05672 } 05673 rpt_vars[n].link_functions = ast_variable_retrieve(cfg,this,"link_functions"); 05674 if (!rpt_vars[n].link_functions) 05675 rpt_vars[n].link_functions = rpt_vars[n].functions; 05676 rpt_vars[n].phone_functions = ast_variable_retrieve(cfg,this,"phone_functions"); 05677 rpt_vars[n].dphone_functions = ast_variable_retrieve(cfg,this,"dphone_functions"); 05678 val = ast_variable_retrieve(cfg,this,"funcchar"); 05679 if (!val) rpt_vars[n].funcchar = FUNCCHAR; else 05680 rpt_vars[n].funcchar = *val; 05681 val = ast_variable_retrieve(cfg,this,"endchar"); 05682 if (!val) rpt_vars[n].endchar = ENDCHAR; else 05683 rpt_vars[n].endchar = *val; 05684 val = ast_variable_retrieve(cfg,this,"nobusyout"); 05685 if (val) rpt_vars[n].nobusyout = ast_true(val); 05686 rpt_vars[n].nodes = ast_variable_retrieve(cfg,this,"nodes"); 05687 if (!rpt_vars[n].nodes) 05688 rpt_vars[n].nodes = NODES; 05689 n++; 05690 } 05691 nrpts = n; 05692 ast_log(LOG_DEBUG, "Total of %d repeaters configured.\n",n); 05693 /* start em all */ 05694 for(i = 0; i < n; i++) 05695 { 05696 05697 /* 05698 * Go through the node list to determine the longest node 05699 */ 05700 longestnode = 0; 05701 05702 vp = ast_variable_browse(cfg, rpt_vars[i].nodes); 05703 05704 while(vp){ 05705 j = strlen(vp->name); 05706 if (j > longestnode) 05707 longestnode = j; 05708 vp = vp->next; 05709 } 05710 05711 05712 rpt_vars[i].longestnode = longestnode; 05713 05714 /* 05715 * For this repeater, Determine the length of the longest function 05716 */ 05717 rpt_vars[i].longestfunc = 0; 05718 vp = ast_variable_browse(cfg, rpt_vars[i].functions); 05719 while(vp){ 05720 j = strlen(vp->name); 05721 if (j > rpt_vars[i].longestfunc) 05722 rpt_vars[i].longestfunc = j; 05723 vp = vp->next; 05724 } 05725 /* 05726 * For this repeater, Determine the length of the longest function 05727 */ 05728 rpt_vars[i].link_longestfunc = 0; 05729 vp = ast_variable_browse(cfg, rpt_vars[i].link_functions); 05730 while(vp){ 05731 j = strlen(vp->name); 05732 if (j > rpt_vars[i].link_longestfunc) 05733 rpt_vars[i].link_longestfunc = j; 05734 vp = vp->next; 05735 } 05736 rpt_vars[i].phone_longestfunc = 0; 05737 if (rpt_vars[i].phone_functions) 05738 { 05739 vp = ast_variable_browse(cfg, rpt_vars[i].phone_functions); 05740 while(vp){ 05741 j = strlen(vp->name); 05742 if (j > rpt_vars[i].phone_longestfunc) 05743 rpt_vars[i].phone_longestfunc = j; 05744 vp = vp->next; 05745 } 05746 } 05747 rpt_vars[i].dphone_longestfunc = 0; 05748 if (rpt_vars[i].dphone_functions) 05749 { 05750 vp = ast_variable_browse(cfg, rpt_vars[i].dphone_functions); 05751 while(vp){ 05752 j = strlen(vp->name); 05753 if (j > rpt_vars[i].dphone_longestfunc) 05754 rpt_vars[i].dphone_longestfunc = j; 05755 vp = vp->next; 05756 } 05757 } 05758 if (!rpt_vars[i].rxchanname) 05759 { 05760 ast_log(LOG_WARNING,"Did not specify rxchanname for node %s\n",rpt_vars[i].name); 05761 ast_config_destroy(cfg); 05762 pthread_exit(NULL); 05763 } 05764 /* if is a remote, dont start one for it */ 05765 if (rpt_vars[i].remote) 05766 { 05767 strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1); 05768 strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1); 05769 05770 strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1); 05771 rpt_vars[i].remmode = REM_MODE_FM; 05772 rpt_vars[i].offset = REM_SIMPLEX; 05773 rpt_vars[i].powerlevel = REM_MEDPWR; 05774 continue; 05775 } 05776 if (!rpt_vars[i].ident) 05777 { 05778 ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name); 05779 ast_config_destroy(cfg); 05780 pthread_exit(NULL); 05781 } 05782 pthread_attr_init(&attr); 05783 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05784 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]); 05785 } 05786 usleep(500000); 05787 for(;;) 05788 { 05789 /* Now monitor each thread, and restart it if necessary */ 05790 for(i = 0; i < n; i++) 05791 { 05792 int rv; 05793 if (rpt_vars[i].remote) continue; 05794 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP) 05795 rv = -1; 05796 else 05797 rv = pthread_kill(rpt_vars[i].rpt_thread,0); 05798 if (rv) 05799 { 05800 if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15) 05801 { 05802 if(rpt_vars[i].threadrestarts >= 5) 05803 { 05804 ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n"); 05805 exit(1); /* Stuck in a restart loop, kill Asterisk and start over */ 05806 } 05807 else 05808 { 05809 ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name); 05810 rpt_vars[i].threadrestarts++; 05811 } 05812 } 05813 else 05814 rpt_vars[i].threadrestarts = 0; 05815 05816 rpt_vars[i].lastthreadrestarttime = time(NULL); 05817 pthread_attr_init(&attr); 05818 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05819 ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]); 05820 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name); 05821 } 05822 05823 } 05824 usleep(2000000); 05825 } 05826 ast_config_destroy(cfg); 05827 pthread_exit(NULL); 05828 }
static void* rpt_tele_thread | ( | void * | this | ) | [static] |
Definition at line 965 of file app_rpt.c.
References ARB_ALPHA, AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_safe_sleep(), ast_say_character_str(), ast_say_digits(), ast_say_number(), ast_say_time(), ast_stopstream(), ast_strdupa, ast_streamfile(), ast_tonepair_start(), ast_variable_retrieve(), ast_waitstream(), cfg, rpt_tele::chan, COMPLETE, CONNECTED, rpt_link::connected, CONNFAIL, DLY_CALLTERM, DLY_ID, DLY_TELEM, DLY_UNKEY, ast_channel::fds, free, get_wait_interval(), ID, ID1, IDTALKOVER, rpt_link::isremote, ast_channel::language, LOG_WARNING, malloc, rpt_link::mode, rpt_tele::mode, rpt_tele::mylink, rpt_link::name, ast_channel::name, rpt_link::next, rpt_tele::next, rpt_tele::param, rpt_link::prev, PROC, REMALREADY, REMDISC, REMGO, REMNOTFOUND, REV_PATCH, rpt_tele::rpt, saycharstr(), sayfile(), STATS_TIME, STATS_VERSION, STATUS, strsep(), t, telem_any(), telem_lookup(), TERM, TEST_TONE, TIMEOUT, UNKEY, and wait_interval().
Referenced by rpt_telemetry().
00966 { 00967 ZT_CONFINFO ci; /* conference info */ 00968 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x; 00969 struct rpt_tele *mytele = (struct rpt_tele *)this; 00970 struct rpt_tele *tlist; 00971 struct rpt *myrpt; 00972 struct rpt_link *l,*m,linkbase; 00973 struct ast_channel *mychannel; 00974 int vmajor, vminor; 00975 char *p,*ct,*ct_copy,*ident, *nodename; 00976 time_t t; 00977 struct tm localtm; 00978 00979 00980 /* get a pointer to myrpt */ 00981 myrpt = mytele->rpt; 00982 00983 /* Snag copies of a few key myrpt variables */ 00984 ast_mutex_lock(&myrpt->lock); 00985 nodename = ast_strdupa(myrpt->name); 00986 ident = ast_strdupa(myrpt->ident); 00987 ast_mutex_unlock(&myrpt->lock); 00988 00989 00990 /* allocate a pseudo-channel thru asterisk */ 00991 mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL); 00992 if (!mychannel) 00993 { 00994 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); 00995 ast_mutex_lock(&myrpt->lock); 00996 remque((struct qelem *)mytele); 00997 ast_mutex_unlock(&myrpt->lock); 00998 free(mytele); 00999 pthread_exit(NULL); 01000 } 01001 ast_mutex_lock(&myrpt->lock); 01002 mytele->chan = mychannel; /* Save a copy of the channel so we can access it externally if need be */ 01003 ast_mutex_unlock(&myrpt->lock); 01004 01005 /* make a conference for the tx */ 01006 ci.chan = 0; 01007 /* If there's an ID queued, only connect the ID audio to the local tx conference so 01008 linked systems can't hear it */ 01009 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY)) ? 01010 myrpt->txconf : myrpt->conf); 01011 ci.confmode = ZT_CONF_CONFANN; 01012 /* first put the channel on the conference in announce mode */ 01013 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1) 01014 { 01015 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 01016 ast_mutex_lock(&myrpt->lock); 01017 remque((struct qelem *)mytele); 01018 ast_mutex_unlock(&myrpt->lock); 01019 free(mytele); 01020 ast_hangup(mychannel); 01021 pthread_exit(NULL); 01022 } 01023 ast_stopstream(mychannel); 01024 switch(mytele->mode) 01025 { 01026 case ID: 01027 case ID1: 01028 /* wait a bit */ 01029 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel); 01030 res = telem_any(mychannel, ident); 01031 imdone=1; 01032 01033 break; 01034 01035 01036 case IDTALKOVER: 01037 p = ast_variable_retrieve(cfg, nodename, "idtalkover"); 01038 if(p) 01039 res = telem_any(mychannel, p); 01040 imdone=1; 01041 break; 01042 01043 case PROC: 01044 /* wait a little bit longer */ 01045 wait_interval(myrpt, DLY_TELEM, mychannel); 01046 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language); 01047 break; 01048 case TERM: 01049 /* wait a little bit longer */ 01050 wait_interval(myrpt, DLY_CALLTERM, mychannel); 01051 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language); 01052 break; 01053 case COMPLETE: 01054 /* wait a little bit */ 01055 wait_interval(myrpt, DLY_TELEM, mychannel); 01056 res = telem_lookup(mychannel, myrpt->name, "functcomplete"); 01057 break; 01058 case UNKEY: 01059 01060 /* 01061 * Reset the Unkey to CT timer 01062 */ 01063 01064 x = get_wait_interval(myrpt, DLY_UNKEY); 01065 ast_mutex_lock(&myrpt->lock); 01066 myrpt->unkeytocttimer = x; /* Must be protected as it is changed below */ 01067 ast_mutex_unlock(&myrpt->lock); 01068 01069 /* 01070 * If there's one already queued, don't do another 01071 */ 01072 01073 tlist = myrpt->tele.next; 01074 unkeys_queued = 0; 01075 if (tlist != &myrpt->tele) 01076 { 01077 ast_mutex_lock(&myrpt->lock); 01078 while(tlist != &myrpt->tele){ 01079 if (tlist->mode == UNKEY) unkeys_queued++; 01080 tlist = tlist->next; 01081 } 01082 ast_mutex_unlock(&myrpt->lock); 01083 } 01084 if( unkeys_queued > 1){ 01085 imdone = 1; 01086 break; 01087 } 01088 01089 /* Wait for the telemetry timer to expire */ 01090 /* Periodically check the timer since it can be re-initialized above */ 01091 01092 while(myrpt->unkeytocttimer) 01093 { 01094 int ctint; 01095 if(myrpt->unkeytocttimer > 100) 01096 ctint = 100; 01097 else 01098 ctint = myrpt->unkeytocttimer; 01099 ast_safe_sleep(mychannel, ctint); 01100 ast_mutex_lock(&myrpt->lock); 01101 if(myrpt->unkeytocttimer < ctint) 01102 myrpt->unkeytocttimer = 0; 01103 else 01104 myrpt->unkeytocttimer -= ctint; 01105 ast_mutex_unlock(&myrpt->lock); 01106 } 01107 01108 01109 /* 01110 * Now, the carrier on the rptr rx should be gone. 01111 * If it re-appeared, then forget about sending the CT 01112 */ 01113 if(myrpt->keyed){ 01114 imdone = 1; 01115 break; 01116 } 01117 01118 haslink = 0; 01119 hastx = 0; 01120 hasremote = 0; 01121 l = myrpt->links.next; 01122 if (l != &myrpt->links) 01123 { 01124 ast_mutex_lock(&myrpt->lock); 01125 while(l != &myrpt->links) 01126 { 01127 if (l->name[0] == '0') 01128 { 01129 l = l->next; 01130 continue; 01131 } 01132 haslink = 1; 01133 if (l->mode) { 01134 hastx++; 01135 if (l->isremote) hasremote++; 01136 } 01137 l = l->next; 01138 } 01139 ast_mutex_unlock(&myrpt->lock); 01140 } 01141 if (haslink) 01142 { 01143 01144 res = telem_lookup(mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx"); 01145 if(res) 01146 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name); 01147 01148 01149 /* if in remote cmd mode, indicate it */ 01150 if (myrpt->cmdnode[0]) 01151 { 01152 ast_safe_sleep(mychannel,200); 01153 res = telem_lookup(mychannel, myrpt->name, "cmdmode"); 01154 if(res) 01155 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name); 01156 ast_stopstream(mychannel); 01157 } 01158 } 01159 else if((ct = ast_variable_retrieve(cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */ 01160 ct_copy = ast_strdupa(ct); 01161 res = telem_lookup(mychannel, myrpt->name, ct_copy); 01162 if(res) 01163 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name); 01164 } 01165 01166 if (hasremote && (!myrpt->cmdnode[0])) 01167 { 01168 /* set for all to hear */ 01169 ci.chan = 0; 01170 ci.confno = myrpt->conf; 01171 ci.confmode = ZT_CONF_CONFANN; 01172 /* first put the channel on the conference in announce mode */ 01173 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1) 01174 { 01175 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 01176 ast_mutex_lock(&myrpt->lock); 01177 remque((struct qelem *)mytele); 01178 ast_mutex_unlock(&myrpt->lock); 01179 free(mytele); 01180 ast_hangup(mychannel); 01181 pthread_exit(NULL); 01182 } 01183 if((ct = ast_variable_retrieve(cfg, nodename, "remotect"))){ /* Unlinked Courtesy Tone */ 01184 ast_safe_sleep(mychannel,200); 01185 ct_copy = ast_strdupa(ct); 01186 res = telem_lookup(mychannel, myrpt->name, ct_copy); 01187 if(res) 01188 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name); 01189 } 01190 } 01191 imdone = 1; 01192 break; 01193 case REMDISC: 01194 /* wait a little bit */ 01195 wait_interval(myrpt, DLY_TELEM, mychannel); 01196 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 01197 if (!res) 01198 res = ast_waitstream(mychannel, ""); 01199 else 01200 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01201 ast_stopstream(mychannel); 01202 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language); 01203 res = ast_streamfile(mychannel, ((mytele->mylink.connected) ? 01204 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language); 01205 break; 01206 case REMALREADY: 01207 /* wait a little bit */ 01208 wait_interval(myrpt, DLY_TELEM, mychannel); 01209 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language); 01210 break; 01211 case REMNOTFOUND: 01212 /* wait a little bit */ 01213 wait_interval(myrpt, DLY_TELEM, mychannel); 01214 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language); 01215 break; 01216 case REMGO: 01217 /* wait a little bit */ 01218 wait_interval(myrpt, DLY_TELEM, mychannel); 01219 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language); 01220 break; 01221 case CONNECTED: 01222 /* wait a little bit */ 01223 wait_interval(myrpt, DLY_TELEM, mychannel); 01224 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 01225 if (!res) 01226 res = ast_waitstream(mychannel, ""); 01227 else 01228 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01229 ast_stopstream(mychannel); 01230 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language); 01231 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language); 01232 break; 01233 case CONNFAIL: 01234 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 01235 if (!res) 01236 res = ast_waitstream(mychannel, ""); 01237 else 01238 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01239 ast_stopstream(mychannel); 01240 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language); 01241 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language); 01242 break; 01243 case STATUS: 01244 /* wait a little bit */ 01245 wait_interval(myrpt, DLY_TELEM, mychannel); 01246 hastx = 0; 01247 linkbase.next = &linkbase; 01248 linkbase.prev = &linkbase; 01249 ast_mutex_lock(&myrpt->lock); 01250 /* make our own list of links */ 01251 l = myrpt->links.next; 01252 while(l != &myrpt->links) 01253 { 01254 if (l->name[0] == '0') 01255 { 01256 l = l->next; 01257 continue; 01258 } 01259 m = malloc(sizeof(struct rpt_link)); 01260 if (!m) 01261 { 01262 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name); 01263 ast_mutex_lock(&myrpt->lock); 01264 remque((struct qelem *)mytele); 01265 ast_mutex_unlock(&myrpt->lock); 01266 free(mytele); 01267 ast_hangup(mychannel); 01268 pthread_exit(NULL); 01269 } 01270 memcpy(m,l,sizeof(struct rpt_link)); 01271 m->next = m->prev = NULL; 01272 insque((struct qelem *)m,(struct qelem *)linkbase.next); 01273 l = l->next; 01274 } 01275 ast_mutex_unlock(&myrpt->lock); 01276 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 01277 if (!res) 01278 res = ast_waitstream(mychannel, ""); 01279 else 01280 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01281 ast_stopstream(mychannel); 01282 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language); 01283 if (!res) 01284 res = ast_waitstream(mychannel, ""); 01285 else 01286 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01287 ast_stopstream(mychannel); 01288 if (myrpt->callmode) 01289 { 01290 hastx = 1; 01291 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language); 01292 if (!res) 01293 res = ast_waitstream(mychannel, ""); 01294 else 01295 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01296 ast_stopstream(mychannel); 01297 } 01298 l = linkbase.next; 01299 while(l != &linkbase) 01300 { 01301 hastx = 1; 01302 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 01303 if (!res) 01304 res = ast_waitstream(mychannel, ""); 01305 else 01306 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01307 ast_stopstream(mychannel); 01308 ast_say_character_str(mychannel,l->name,NULL,mychannel->language); 01309 if (!res) 01310 res = ast_waitstream(mychannel, ""); 01311 else 01312 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01313 ast_stopstream(mychannel); 01314 res = ast_streamfile(mychannel, ((l->mode) ? 01315 "rpt/tranceive" : "rpt/monitor"), mychannel->language); 01316 if (!res) 01317 res = ast_waitstream(mychannel, ""); 01318 else 01319 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01320 ast_stopstream(mychannel); 01321 l = l->next; 01322 } 01323 if (!hastx) 01324 { 01325 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language); 01326 if (!res) 01327 res = ast_waitstream(mychannel, ""); 01328 else 01329 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01330 ast_stopstream(mychannel); 01331 } 01332 /* destroy our local link queue */ 01333 l = linkbase.next; 01334 while(l != &linkbase) 01335 { 01336 m = l; 01337 l = l->next; 01338 remque((struct qelem *)m); 01339 free(m); 01340 } 01341 imdone = 1; 01342 break; 01343 case TIMEOUT: 01344 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 01345 if (!res) 01346 res = ast_waitstream(mychannel, ""); 01347 else 01348 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01349 ast_stopstream(mychannel); 01350 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language); 01351 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language); 01352 break; 01353 01354 case STATS_TIME: 01355 wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */ 01356 t = time(NULL); 01357 localtime_r(&t, &localtm); 01358 /* Say the phase of the day is before the time */ 01359 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12)) 01360 p = "rpt/goodmorning"; 01361 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18)) 01362 p = "rpt/goodafternoon"; 01363 else 01364 p = "rpt/goodevening"; 01365 if (sayfile(mychannel,p) == -1) 01366 { 01367 imdone = 1; 01368 break; 01369 } 01370 /* Say the time is ... */ 01371 if (sayfile(mychannel,"rpt/thetimeis") == -1) 01372 { 01373 imdone = 1; 01374 break; 01375 } 01376 /* Say the time */ 01377 res = ast_say_time(mychannel, t, "", mychannel->language); 01378 if (!res) 01379 res = ast_waitstream(mychannel, ""); 01380 ast_stopstream(mychannel); 01381 imdone = 1; 01382 break; 01383 case STATS_VERSION: 01384 p = strstr(tdesc, "version"); 01385 if(!p) 01386 break; 01387 if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2) 01388 break; 01389 wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */ 01390 /* Say "version" */ 01391 if (sayfile(mychannel,"rpt/version") == -1) 01392 { 01393 imdone = 1; 01394 break; 01395 } 01396 if(!res) /* Say "X" */ 01397 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL); 01398 if (!res) 01399 res = ast_waitstream(mychannel, ""); 01400 ast_stopstream(mychannel); 01401 if (saycharstr(mychannel,".") == -1) 01402 { 01403 imdone = 1; 01404 break; 01405 } 01406 if(!res) /* Say "Y" */ 01407 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL); 01408 if (!res){ 01409 res = ast_waitstream(mychannel, ""); 01410 ast_stopstream(mychannel); 01411 } 01412 else 01413 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01414 imdone = 1; 01415 break; 01416 case ARB_ALPHA: 01417 wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */ 01418 if(mytele->param) 01419 saycharstr(mychannel, mytele->param); 01420 imdone = 1; 01421 break; 01422 case REV_PATCH: 01423 wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */ 01424 if(mytele->param) { 01425 01426 /* Parts of this section taken from app_parkandannounce */ 01427 char *tpl_working, *tpl_current; 01428 char *tmp[100], *myparm; 01429 int looptemp=0,i=0, dres = 0; 01430 01431 01432 tpl_working = strdupa(mytele->param); 01433 myparm = strsep(&tpl_working,","); 01434 tpl_current=strsep(&tpl_working, ":"); 01435 01436 while(tpl_current && looptemp < sizeof(tmp)) { 01437 tmp[looptemp]=tpl_current; 01438 looptemp++; 01439 tpl_current=strsep(&tpl_working,":"); 01440 } 01441 01442 for(i=0; i<looptemp; i++) { 01443 if(!strcmp(tmp[i], "PARKED")) { 01444 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language); 01445 } else if(!strcmp(tmp[i], "NODE")) { 01446 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language); 01447 } else { 01448 dres = ast_streamfile(mychannel, tmp[i], mychannel->language); 01449 if(!dres) { 01450 dres = ast_waitstream(mychannel, ""); 01451 } else { 01452 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name); 01453 dres = 0; 01454 } 01455 } 01456 } 01457 } 01458 imdone = 1; 01459 break; 01460 case TEST_TONE: 01461 imdone = 1; 01462 myrpt->stopgen = 0; 01463 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0))) 01464 break; 01465 while(mychannel->generatordata && (!myrpt->stopgen)) { 01466 if (ast_safe_sleep(mychannel,1)) break; 01467 imdone = 1; 01468 } 01469 break; 01470 default: 01471 break; 01472 } 01473 myrpt->stopgen = 0; 01474 if (!imdone) 01475 { 01476 if (!res) 01477 res = ast_waitstream(mychannel, ""); 01478 else { 01479 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01480 res = 0; 01481 } 01482 } 01483 ast_stopstream(mychannel); 01484 ast_mutex_lock(&myrpt->lock); 01485 remque((struct qelem *)mytele); 01486 ast_mutex_unlock(&myrpt->lock); 01487 free(mytele); 01488 ast_hangup(mychannel); 01489 pthread_exit(NULL); 01490 }
static void rpt_telemetry | ( | struct rpt * | myrpt, | |
int | mode, | |||
void * | data | |||
) | [static] |
Definition at line 1492 of file app_rpt.c.
References ARB_ALPHA, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, CONNECTED, CONNFAIL, rpt::lock, LOG_WARNING, malloc, rpt_tele::next, REMDISC, REV_PATCH, rpt_tele_thread(), rpt::tele, and TELEPARAMSIZE.
Referenced by function_autopatchdn(), function_cop(), function_ilink(), function_status(), handle_link_data(), handle_link_phone_dtmf(), rpt(), and rpt_exec().
01493 { 01494 struct rpt_tele *tele; 01495 struct rpt_link *mylink = (struct rpt_link *) data; 01496 pthread_attr_t attr; 01497 01498 tele = malloc(sizeof(struct rpt_tele)); 01499 if (!tele) 01500 { 01501 ast_log(LOG_WARNING, "Unable to allocate memory\n"); 01502 pthread_exit(NULL); 01503 return; 01504 } 01505 /* zero it out */ 01506 memset((char *)tele,0,sizeof(struct rpt_tele)); 01507 tele->rpt = myrpt; 01508 tele->mode = mode; 01509 ast_mutex_lock(&myrpt->lock); 01510 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED)){ 01511 memset(&tele->mylink,0,sizeof(struct rpt_link)); 01512 if (mylink){ 01513 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link)); 01514 } 01515 } 01516 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) { 01517 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1); 01518 tele->param[TELEPARAMSIZE - 1] = 0; 01519 } 01520 insque((struct qelem *)tele,(struct qelem *)myrpt->tele.next); 01521 ast_mutex_unlock(&myrpt->lock); 01522 pthread_attr_init(&attr); 01523 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 01524 ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele); 01525 return; 01526 }
static int saycharstr | ( | struct ast_channel * | mychannel, | |
char * | str | |||
) | [static] |
Definition at line 748 of file app_rpt.c.
References ast_log(), ast_say_character_str(), ast_stopstream(), ast_waitstream(), ast_channel::language, LOG_WARNING, and ast_channel::name.
Referenced by function_remote(), rmt_saycharstr(), and rpt_tele_thread().
00749 { 00750 int res; 00751 00752 res = ast_say_character_str(mychannel,str,NULL,mychannel->language); 00753 if (!res) 00754 res = ast_waitstream(mychannel, ""); 00755 else 00756 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 00757 ast_stopstream(mychannel); 00758 return res; 00759 }
static int sayfile | ( | struct ast_channel * | mychannel, | |
char * | fname | |||
) | [static] |
Definition at line 735 of file app_rpt.c.
References ast_log(), ast_stopstream(), ast_streamfile(), ast_waitstream(), ast_channel::language, LOG_WARNING, and ast_channel::name.
Referenced by function_remote(), rmt_sayfile(), rpt_tele_thread(), and telem_any().
00736 { 00737 int res; 00738 00739 res = ast_streamfile(mychannel, fname, mychannel->language); 00740 if (!res) 00741 res = ast_waitstream(mychannel, ""); 00742 else 00743 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 00744 ast_stopstream(mychannel); 00745 return res; 00746 }
static int saynum | ( | struct ast_channel * | mychannel, | |
int | num | |||
) | [static] |
Definition at line 761 of file app_rpt.c.
References ast_log(), ast_say_number(), ast_stopstream(), ast_waitstream(), ast_channel::language, LOG_WARNING, and ast_channel::name.
Referenced by function_remote().
00762 { 00763 int res; 00764 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL); 00765 if(!res) 00766 res = ast_waitstream(mychannel, ""); 00767 else 00768 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 00769 ast_stopstream(mychannel); 00770 return res; 00771 }
static void send_link_dtmf | ( | struct rpt * | myrpt, | |
char | c | |||
) | [static] |
Definition at line 1720 of file app_rpt.c.
References AST_FRAME_TEXT, ast_write(), rpt_link::chan, rpt::cmdnode, ast_frame::data, ast_frame::datalen, rpt::dtmfidx, ast_frame::frametype, rpt::links, ast_frame::mallocd, rpt_link::name, rpt::name, rpt_link::next, ast_frame::offset, ast_frame::samples, strdup, and ast_frame::subclass.
Referenced by handle_link_phone_dtmf(), and rpt().
01721 { 01722 char str[300]; 01723 struct ast_frame wf; 01724 struct rpt_link *l; 01725 01726 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c); 01727 wf.frametype = AST_FRAME_TEXT; 01728 wf.subclass = 0; 01729 wf.offset = 0; 01730 wf.mallocd = 1; 01731 wf.datalen = strlen(str) + 1; 01732 wf.samples = 0; 01733 l = myrpt->links.next; 01734 /* first, see if our dude is there */ 01735 while(l != &myrpt->links) 01736 { 01737 if (l->name[0] == '0') 01738 { 01739 l = l->next; 01740 continue; 01741 } 01742 /* if we found it, write it and were done */ 01743 if (!strcmp(l->name,myrpt->cmdnode)) 01744 { 01745 wf.data = strdup(str); 01746 if (l->chan) ast_write(l->chan,&wf); 01747 return; 01748 } 01749 l = l->next; 01750 } 01751 l = myrpt->links.next; 01752 /* if not, give it to everyone */ 01753 while(l != &myrpt->links) 01754 { 01755 wf.data = strdup(str); 01756 if (l->chan) ast_write(l->chan,&wf); 01757 l = l->next; 01758 } 01759 return; 01760 }
static int send_morse | ( | struct ast_channel * | chan, | |
char * | string, | |||
int | speed, | |||
int | freq, | |||
int | amplitude | |||
) | [static] |
Definition at line 521 of file app_rpt.c.
References ast_safe_sleep(), ast_stopstream(), ast_waitstream(), morse_bits::ddcomb, ast_channel::fds, morse_bits::len, play_silence(), and play_tone().
Referenced by telem_any().
00522 { 00523 00524 static struct morse_bits mbits[] = { 00525 {0, 0}, /* SPACE */ 00526 {0, 0}, 00527 {6, 18},/* " */ 00528 {0, 0}, 00529 {7, 72},/* $ */ 00530 {0, 0}, 00531 {0, 0}, 00532 {6, 30},/* ' */ 00533 {5, 13},/* ( */ 00534 {6, 29},/* ) */ 00535 {0, 0}, 00536 {5, 10},/* + */ 00537 {6, 51},/* , */ 00538 {6, 33},/* - */ 00539 {6, 42},/* . */ 00540 {5, 9}, /* / */ 00541 {5, 31},/* 0 */ 00542 {5, 30},/* 1 */ 00543 {5, 28},/* 2 */ 00544 {5, 24},/* 3 */ 00545 {5, 16},/* 4 */ 00546 {5, 0}, /* 5 */ 00547 {5, 1}, /* 6 */ 00548 {5, 3}, /* 7 */ 00549 {5, 7}, /* 8 */ 00550 {5, 15},/* 9 */ 00551 {6, 7}, /* : */ 00552 {6, 21},/* ; */ 00553 {0, 0}, 00554 {5, 33},/* = */ 00555 {0, 0}, 00556 {6, 12},/* ? */ 00557 {0, 0}, 00558 {2, 2}, /* A */ 00559 {4, 1}, /* B */ 00560 {4, 5}, /* C */ 00561 {3, 1}, /* D */ 00562 {1, 0}, /* E */ 00563 {4, 4}, /* F */ 00564 {3, 3}, /* G */ 00565 {4, 0}, /* H */ 00566 {2, 0}, /* I */ 00567 {4, 14},/* J */ 00568 {3, 5}, /* K */ 00569 {4, 2}, /* L */ 00570 {2, 3}, /* M */ 00571 {2, 1}, /* N */ 00572 {3, 7}, /* O */ 00573 {4, 6}, /* P */ 00574 {4, 11},/* Q */ 00575 {3, 2}, /* R */ 00576 {3, 0}, /* S */ 00577 {1, 1}, /* T */ 00578 {3, 4}, /* U */ 00579 {4, 8}, /* V */ 00580 {3, 6}, /* W */ 00581 {4, 9}, /* X */ 00582 {4, 13},/* Y */ 00583 {4, 3} /* Z */ 00584 }; 00585 00586 00587 int dottime; 00588 int dashtime; 00589 int intralettertime; 00590 int interlettertime; 00591 int interwordtime; 00592 int len, ddcomb; 00593 int res; 00594 int c; 00595 int i; 00596 int flags; 00597 00598 res = 0; 00599 00600 /* Approximate the dot time from the speed arg. */ 00601 00602 dottime = 900/speed; 00603 00604 /* Establish timing releationships */ 00605 00606 dashtime = 3 * dottime; 00607 intralettertime = dottime; 00608 interlettertime = dottime * 4 ; 00609 interwordtime = dottime * 7; 00610 00611 for(;(*string) && (!res); string++){ 00612 00613 c = *string; 00614 00615 /* Convert lower case to upper case */ 00616 00617 if((c >= 'a') && (c <= 'z')) 00618 c -= 0x20; 00619 00620 /* Can't deal with any char code greater than Z, skip it */ 00621 00622 if(c > 'Z') 00623 continue; 00624 00625 /* If space char, wait the inter word time */ 00626 00627 if(c == ' '){ 00628 if(!res) 00629 res = play_silence(chan, interwordtime); 00630 continue; 00631 } 00632 00633 /* Subtract out control char offset to match our table */ 00634 00635 c -= 0x20; 00636 00637 /* Get the character data */ 00638 00639 len = mbits[c].len; 00640 ddcomb = mbits[c].ddcomb; 00641 00642 /* Send the character */ 00643 00644 for(; len ; len--){ 00645 if(!res) 00646 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude); 00647 if(!res) 00648 res = play_silence(chan, intralettertime); 00649 ddcomb >>= 1; 00650 } 00651 00652 /* Wait the interletter time */ 00653 00654 if(!res) 00655 res = play_silence(chan, interlettertime - intralettertime); 00656 } 00657 00658 /* Wait for all the frames to be sent */ 00659 00660 if (!res) 00661 res = ast_waitstream(chan, ""); 00662 ast_stopstream(chan); 00663 00664 /* 00665 * Wait for the zaptel driver to physically write the tone blocks to the hardware 00666 */ 00667 00668 for(i = 0; i < 20 ; i++){ 00669 flags = ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT; 00670 res = ioctl(chan->fds[0], ZT_IOMUX, &flags); 00671 if(flags & ZT_IOMUX_WRITEEMPTY) 00672 break; 00673 if( ast_safe_sleep(chan, 50)){ 00674 res = -1; 00675 break; 00676 } 00677 } 00678 00679 00680 return res; 00681 }
static int send_tone_telemetry | ( | struct ast_channel * | chan, | |
char * | tonestring | |||
) | [static] |
Definition at line 683 of file app_rpt.c.
References ast_safe_sleep(), ast_stopstream(), ast_strdupa, ast_waitstream(), ast_channel::fds, play_tone_pair(), and strsep().
Referenced by telem_any().
00684 { 00685 char *stringp; 00686 char *tonesubset; 00687 int f1,f2; 00688 int duration; 00689 int amplitude; 00690 int res; 00691 int i; 00692 int flags; 00693 00694 res = 0; 00695 00696 stringp = ast_strdupa(tonestring); 00697 00698 for(;tonestring;){ 00699 tonesubset = strsep(&stringp,")"); 00700 if(!tonesubset) 00701 break; 00702 if(sscanf(tonesubset,"(%d,%d,%d,%d", &f1, &f2, &duration, &litude) != 4) 00703 break; 00704 res = play_tone_pair(chan, f1, f2, duration, amplitude); 00705 if(res) 00706 break; 00707 } 00708 if(!res) 00709 res = play_tone_pair(chan, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */ 00710 00711 if (!res) 00712 res = ast_waitstream(chan, ""); 00713 ast_stopstream(chan); 00714 00715 /* 00716 * Wait for the zaptel driver to physically write the tone blocks to the hardware 00717 */ 00718 00719 for(i = 0; i < 20 ; i++){ 00720 flags = ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT; 00721 res = ioctl(chan->fds[0], ZT_IOMUX, &flags); 00722 if(flags & ZT_IOMUX_WRITEEMPTY) 00723 break; 00724 if( ast_safe_sleep(chan, 50)){ 00725 res = -1; 00726 break; 00727 } 00728 } 00729 00730 return res; 00731 00732 }
static int serial_remote_io | ( | struct rpt * | myrpt, | |
char * | txbuf, | |||
int | txbytes, | |||
char * | rxbuf, | |||
int | rxmaxbytes, | |||
int | asciiflag | |||
) | [static] |
Definition at line 2826 of file app_rpt.c.
References ast_channel::fds, and rpt::rxchannel.
Referenced by set_ctcss_freq_ft897(), set_ctcss_mode_ft897(), set_freq_ft897(), set_mode_ft897(), set_offset_ft897(), and simple_command_ft897().
02828 { 02829 int i; 02830 struct zt_radio_param prm; 02831 02832 if(debug){ 02833 printf("String output was: "); 02834 for(i = 0; i < txbytes; i++) 02835 printf("%02X ", (unsigned char ) txbuf[i]); 02836 printf("\n"); 02837 } 02838 02839 prm.radpar = ZT_RADPAR_REMMODE; 02840 if (asciiflag) prm.data = ZT_RADPAR_REM_SERIAL_ASCII; 02841 else prm.data = ZT_RADPAR_REM_SERIAL; 02842 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1; 02843 prm.radpar = ZT_RADPAR_REMCOMMAND; 02844 prm.data = rxmaxbytes; 02845 memcpy(prm.buf,txbuf,txbytes); 02846 prm.index = txbytes; 02847 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1; 02848 if (rxbuf) 02849 { 02850 *rxbuf = 0; 02851 memcpy(rxbuf,prm.buf,prm.index); 02852 } 02853 return(prm.index); 02854 }
static int service_scan | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 3485 of file app_rpt.c.
References rpt::freq, HF_SCAN_DOWN_FAST, HF_SCAN_DOWN_QUICK, HF_SCAN_DOWN_SLOW, HF_SCAN_UP_FAST, HF_SCAN_UP_QUICK, HF_SCAN_UP_SLOW, rpt::hfscanmode, rpt::hfscanstatus, MAXREMSTR, multimode_bump_freq(), split_freq(), and stop_scan().
03486 { 03487 int res, interval; 03488 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0; 03489 03490 switch(myrpt->hfscanmode){ 03491 03492 case HF_SCAN_DOWN_SLOW: 03493 interval = -10; /* 100Hz /sec */ 03494 break; 03495 03496 case HF_SCAN_DOWN_QUICK: 03497 interval = -50; /* 500Hz /sec */ 03498 break; 03499 03500 case HF_SCAN_DOWN_FAST: 03501 interval = -200; /* 2KHz /sec */ 03502 break; 03503 03504 case HF_SCAN_UP_SLOW: 03505 interval = 10; /* 100Hz /sec */ 03506 break; 03507 03508 case HF_SCAN_UP_QUICK: 03509 interval = 50; /* 500 Hz/sec */ 03510 break; 03511 03512 case HF_SCAN_UP_FAST: 03513 interval = 200; /* 2KHz /sec */ 03514 break; 03515 03516 default: 03517 myrpt->hfscanmode = 0; /* Huh? */ 03518 return -1; 03519 } 03520 03521 res = split_freq(mhz, decimals, myrpt->freq); 03522 03523 if(!res){ 03524 k100 =decimals[0]; 03525 k10 = decimals[1]; 03526 res = multimode_bump_freq(myrpt, interval); 03527 } 03528 03529 if(!res) 03530 res = split_freq(mhz, decimals, myrpt->freq); 03531 03532 03533 if(res){ 03534 stop_scan(myrpt,1); 03535 return -1; 03536 } 03537 03538 /* Announce 10KHz boundaries */ 03539 if(k10 != decimals[1]){ 03540 int myhund = (interval < 0) ? k100 : decimals[0]; 03541 int myten = (interval < 0) ? k10 : decimals[1]; 03542 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10; 03543 } 03544 return res; 03545 03546 }
static int set_ctcss_freq_ft897 | ( | struct rpt * | myrpt, | |
char * | txtone, | |||
char * | rxtone | |||
) | [static] |
Definition at line 3267 of file app_rpt.c.
References MAXREMSTR, serial_remote_io(), and split_ctcss_freq().
Referenced by set_ft897().
03268 { 03269 unsigned char cmdstr[5]; 03270 char hertz[MAXREMSTR],decimal[MAXREMSTR]; 03271 int h,d; 03272 03273 memset(cmdstr, 0, 5); 03274 03275 if(split_ctcss_freq(hertz, decimal, txtone)) 03276 return -1; 03277 03278 h = atoi(hertz); 03279 d = atoi(decimal); 03280 03281 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10; 03282 cmdstr[1] = ((h % 10) << 4) + (d % 10); 03283 03284 if(rxtone){ 03285 03286 if(split_ctcss_freq(hertz, decimal, rxtone)) 03287 return -1; 03288 03289 h = atoi(hertz); 03290 d = atoi(decimal); 03291 03292 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10; 03293 cmdstr[3] = ((h % 10) << 4) + (d % 10); 03294 } 03295 cmdstr[4] = 0x0B; 03296 03297 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 03298 }
static int set_ctcss_mode_ft897 | ( | struct rpt * | myrpt, | |
char | txplon, | |||
char | rxplon | |||
) | [static] |
Definition at line 3244 of file app_rpt.c.
References serial_remote_io().
Referenced by set_ft897().
03245 { 03246 unsigned char cmdstr[5]; 03247 03248 memset(cmdstr, 0, 5); 03249 03250 if(rxplon && txplon) 03251 cmdstr[0] = 0x2A; /* Encode and Decode */ 03252 else if (!rxplon && txplon) 03253 cmdstr[0] = 0x4A; /* Encode only */ 03254 else if (rxplon && !txplon) 03255 cmdstr[0] = 0x3A; /* Encode only */ 03256 else 03257 cmdstr[0] = 0x8A; /* OFF */ 03258 03259 cmdstr[4] = 0x0A; 03260 03261 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 03262 }
static int set_freq_ft897 | ( | struct rpt * | myrpt, | |
char * | newfreq | |||
) | [static] |
Definition at line 3136 of file app_rpt.c.
References MAXREMSTR, serial_remote_io(), and split_freq().
Referenced by multimode_bump_freq_ft897(), and set_ft897().
03137 { 03138 char mhz[MAXREMSTR]; 03139 char decimals[MAXREMSTR]; 03140 unsigned char cmdstr[5]; 03141 int fd,m,d; 03142 03143 fd = 0; 03144 if(debug) 03145 printf("New frequency: %s\n",newfreq); 03146 03147 if(split_freq(mhz, decimals, newfreq)) 03148 return -1; 03149 03150 m = atoi(mhz); 03151 d = atoi(decimals); 03152 03153 /* The FT-897 likes packed BCD frequencies */ 03154 03155 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10); /* 100MHz 10Mhz */ 03156 cmdstr[1] = ((m % 10) << 4) + (d / 10000); /* 1MHz 100KHz */ 03157 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100); /* 10KHz 1KHz */ 03158 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10); /* 100Hz 10Hz */ 03159 cmdstr[4] = 0x01; /* command */ 03160 03161 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 03162 03163 }
static int set_ft897 | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 3302 of file app_rpt.c.
References REM_MODE_FM, REM_MODE_LSB, REM_MODE_USB, rpt::remmode, set_ctcss_freq_ft897(), set_ctcss_mode_ft897(), set_freq_ft897(), set_mode_ft897(), set_offset_ft897(), and simple_command_ft897().
Referenced by setrem().
03303 { 03304 int res; 03305 03306 if(debug) 03307 printf("@@@@ lock on\n"); 03308 03309 res = simple_command_ft897(myrpt, 0x00); /* LOCK on */ 03310 03311 if(debug) 03312 printf("@@@@ ptt off\n"); 03313 03314 if(!res) 03315 res = simple_command_ft897(myrpt, 0x88); /* PTT off */ 03316 03317 if(debug) 03318 printf("Modulation mode\n"); 03319 03320 if(!res) 03321 res = set_mode_ft897(myrpt, myrpt->remmode); /* Modulation mode */ 03322 03323 if(debug) 03324 printf("Split off\n"); 03325 03326 if(!res) 03327 simple_command_ft897(myrpt, 0x82); /* Split off */ 03328 03329 if(debug) 03330 printf("Frequency\n"); 03331 03332 if(!res) 03333 res = set_freq_ft897(myrpt, myrpt->freq); /* Frequency */ 03334 if((myrpt->remmode == REM_MODE_FM)){ 03335 if(debug) 03336 printf("Offset\n"); 03337 if(!res) 03338 res = set_offset_ft897(myrpt, myrpt->offset); /* Offset if FM */ 03339 if((!res)&&(myrpt->rxplon || myrpt->txplon)){ 03340 if(debug) 03341 printf("CTCSS tone freqs.\n"); 03342 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl); /* CTCSS freqs if CTCSS is enabled */ 03343 } 03344 if(!res){ 03345 if(debug) 03346 printf("CTCSS mode\n"); 03347 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */ 03348 } 03349 } 03350 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){ 03351 if(debug) 03352 printf("Clarifier off\n"); 03353 simple_command_ft897(myrpt, 0x85); /* Clarifier off if LSB or USB */ 03354 } 03355 return res; 03356 }
static int set_mode_ft897 | ( | struct rpt * | myrpt, | |
char | newmode | |||
) | [static] |
Definition at line 3211 of file app_rpt.c.
References REM_MODE_AM, REM_MODE_FM, REM_MODE_LSB, REM_MODE_USB, and serial_remote_io().
Referenced by set_ft897().
03212 { 03213 unsigned char cmdstr[5]; 03214 03215 memset(cmdstr, 0, 5); 03216 03217 switch(newmode){ 03218 case REM_MODE_FM: 03219 cmdstr[0] = 0x08; 03220 break; 03221 03222 case REM_MODE_USB: 03223 cmdstr[0] = 0x01; 03224 break; 03225 03226 case REM_MODE_LSB: 03227 cmdstr[0] = 0x00; 03228 break; 03229 03230 case REM_MODE_AM: 03231 cmdstr[0] = 0x04; 03232 break; 03233 03234 default: 03235 return -1; 03236 } 03237 cmdstr[4] = 0x07; 03238 03239 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 03240 }
static int set_offset_ft897 | ( | struct rpt * | myrpt, | |
char | offset | |||
) | [static] |
Definition at line 3181 of file app_rpt.c.
References REM_MINUS, REM_PLUS, REM_SIMPLEX, and serial_remote_io().
Referenced by set_ft897().
03182 { 03183 unsigned char cmdstr[5]; 03184 03185 memset(cmdstr, 0, 5); 03186 03187 switch(offset){ 03188 case REM_SIMPLEX: 03189 cmdstr[0] = 0x89; 03190 break; 03191 03192 case REM_MINUS: 03193 cmdstr[0] = 0x09; 03194 break; 03195 03196 case REM_PLUS: 03197 cmdstr[0] = 0x49; 03198 break; 03199 03200 default: 03201 return -1; 03202 } 03203 03204 cmdstr[4] = 0x09; 03205 03206 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 03207 }
static int setrbi | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 2856 of file app_rpt.c.
References rpt::freq, MAXREMSTR, rpt::offset, rpt::powerlevel, rbi_mhztoband(), rbi_out(), rbi_pltocode(), REM_HIPWR, REM_LOWPWR, REM_MEDPWR, REM_MINUS, REM_PLUS, REM_SIMPLEX, rpt::remote, rpt::rxplon, s, rpt::txpl, and rpt::txplon.
Referenced by setrem().
02857 { 02858 char tmp[MAXREMSTR] = "",rbicmd[5],*s; 02859 int band,txoffset = 0,txpower = 0,txpl; 02860 02861 /* must be a remote system */ 02862 if (!myrpt->remote) return(0); 02863 /* must have rbi hardware */ 02864 if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0); 02865 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1); 02866 s = strchr(tmp,'.'); 02867 /* if no decimal, is invalid */ 02868 02869 if (s == NULL){ 02870 if(debug) 02871 printf("@@@@ Frequency needs a decimal\n"); 02872 return -1; 02873 } 02874 02875 *s++ = 0; 02876 if (strlen(tmp) < 2){ 02877 if(debug) 02878 printf("@@@@ Bad MHz digits: %s\n", tmp); 02879 return -1; 02880 } 02881 02882 if (strlen(s) < 3){ 02883 if(debug) 02884 printf("@@@@ Bad KHz digits: %s\n", s); 02885 return -1; 02886 } 02887 02888 if ((s[2] != '0') && (s[2] != '5')){ 02889 if(debug) 02890 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]); 02891 return -1; 02892 } 02893 02894 band = rbi_mhztoband(tmp); 02895 if (band == -1){ 02896 if(debug) 02897 printf("@@@@ Bad Band: %s\n", tmp); 02898 return -1; 02899 } 02900 02901 txpl = rbi_pltocode(myrpt->txpl); 02902 02903 if (txpl == -1){ 02904 if(debug) 02905 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl); 02906 return -1; 02907 } 02908 02909 02910 switch(myrpt->offset) 02911 { 02912 case REM_MINUS: 02913 txoffset = 0; 02914 break; 02915 case REM_PLUS: 02916 txoffset = 0x10; 02917 break; 02918 case REM_SIMPLEX: 02919 txoffset = 0x20; 02920 break; 02921 } 02922 switch(myrpt->powerlevel) 02923 { 02924 case REM_LOWPWR: 02925 txpower = 0; 02926 break; 02927 case REM_MEDPWR: 02928 txpower = 0x20; 02929 break; 02930 case REM_HIPWR: 02931 txpower = 0x10; 02932 break; 02933 } 02934 rbicmd[0] = 0; 02935 rbicmd[1] = band | txpower | 0xc0; 02936 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80; 02937 if (s[2] == '5') rbicmd[2] |= 0x40; 02938 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0'); 02939 rbicmd[4] = txpl; 02940 if (myrpt->txplon) rbicmd[4] |= 0x40; 02941 if (myrpt->rxplon) rbicmd[4] |= 0x80; 02942 rbi_out(myrpt,rbicmd); 02943 return 0; 02944 }
static int setrem | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 3414 of file app_rpt.c.
References rpt::remote, set_ft897(), and setrbi().
Referenced by function_remote(), and rpt_exec().
03415 { 03416 if(!strcmp(myrpt->remote, remote_rig_ft897)) 03417 return set_ft897(myrpt); 03418 else if(!strcmp(myrpt->remote, remote_rig_rbi)) 03419 return setrbi(myrpt); 03420 else 03421 return -1; 03422 }
static int simple_command_ft897 | ( | struct rpt * | myrpt, | |
char | command | |||
) | [static] |
Definition at line 3167 of file app_rpt.c.
References serial_remote_io().
Referenced by closerem_ft897(), and set_ft897().
03168 { 03169 unsigned char cmdstr[5]; 03170 03171 memset(cmdstr, 0, 5); 03172 03173 cmdstr[4] = command; 03174 03175 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 03176 03177 }
static int split_ctcss_freq | ( | char * | hertz, | |
char * | decimal, | |||
char * | freq | |||
) | [static] |
Definition at line 3014 of file app_rpt.c.
References MAXREMSTR.
Referenced by set_ctcss_freq_ft897().
03015 { 03016 char freq_copy[MAXREMSTR]; 03017 char *decp; 03018 03019 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.'); 03020 if(decp){ 03021 *decp++ = 0; 03022 strncpy(hertz, freq_copy, MAXREMSTR); 03023 strncpy(decimal, decp, strlen(decp)); 03024 decimal[strlen(decp)] = '\0'; 03025 return 0; 03026 } 03027 else 03028 return -1; 03029 }
static int split_freq | ( | char * | mhz, | |
char * | decimals, | |||
char * | freq | |||
) | [static] |
Definition at line 2991 of file app_rpt.c.
References MAXREMSTR.
Referenced by function_remote(), multimode_bump_freq_ft897(), service_scan(), and set_freq_ft897().
02992 { 02993 char freq_copy[MAXREMSTR]; 02994 char *decp; 02995 02996 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.'); 02997 if(decp){ 02998 *decp++ = 0; 02999 strncpy(mhz, freq_copy, MAXREMSTR); 03000 strcpy(decimals, "00000"); 03001 strncpy(decimals, decp, strlen(decp)); 03002 decimals[5] = 0; 03003 return 0; 03004 } 03005 else 03006 return -1; 03007 03008 }
static void stop_scan | ( | struct rpt * | myrpt, | |
int | flag | |||
) | [static] |
Definition at line 3474 of file app_rpt.c.
References rpt::hfscanmode, and rpt::hfscanstatus.
Referenced by handle_remote_dtmf_digit(), and service_scan().
03475 { 03476 myrpt->hfscanmode = 0; 03477 myrpt->hfscanstatus = ((flag) ? -2 : -1); 03478 }
static int telem_any | ( | struct ast_channel * | chan, | |
char * | entry | |||
) | [static] |
Definition at line 794 of file app_rpt.c.
References MORSE, retrieve_astcfgint(), sayfile(), send_morse(), and send_tone_telemetry().
Referenced by rpt_tele_thread(), and telem_lookup().
00795 { 00796 int res; 00797 char c; 00798 00799 static int morsespeed; 00800 static int morsefreq; 00801 static int morseampl; 00802 static int morseidfreq = 0; 00803 static int morseidampl; 00804 static char mcat[] = MORSE; 00805 00806 res = 0; 00807 00808 if(!morseidfreq){ /* Get the morse parameters if not already loaded */ 00809 morsespeed = retrieve_astcfgint( mcat, "speed", 5, 20, 20); 00810 morsefreq = retrieve_astcfgint( mcat, "frequency", 300, 3000, 800); 00811 morseampl = retrieve_astcfgint( mcat, "amplitude", 200, 8192, 4096); 00812 morseidampl = retrieve_astcfgint( mcat, "idamplitude", 200, 8192, 2048); 00813 morseidfreq = retrieve_astcfgint( mcat, "idfrequency", 300, 3000, 330); 00814 } 00815 00816 /* Is it a file, or a tone sequence? */ 00817 00818 if(entry[0] == '|'){ 00819 c = entry[1]; 00820 if((c >= 'a')&&(c <= 'z')) 00821 c -= 0x20; 00822 00823 switch(c){ 00824 case 'I': /* Morse ID */ 00825 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl); 00826 break; 00827 00828 case 'M': /* Morse Message */ 00829 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl); 00830 break; 00831 00832 case 'T': /* Tone sequence */ 00833 res = send_tone_telemetry(chan, entry + 2); 00834 break; 00835 default: 00836 res = -1; 00837 } 00838 } 00839 else 00840 res = sayfile(chan, entry); /* File */ 00841 return res; 00842 }
static int telem_lookup | ( | struct ast_channel * | chan, | |
char * | node, | |||
char * | name | |||
) | [static] |
Definition at line 850 of file app_rpt.c.
References ast_log(), ast_strdupa, ast_variable_retrieve(), cfg, LOG_WARNING, tele_defs, telem_any(), and TELEMETRY.
Referenced by handle_remote_data(), handle_remote_phone_dtmf(), and rpt_tele_thread().
00851 { 00852 00853 int res; 00854 int i; 00855 char *entry; 00856 char *telemetry; 00857 char *telemetry_save; 00858 00859 res = 0; 00860 telemetry_save = NULL; 00861 entry = NULL; 00862 00863 00864 /* Retrieve the section name for telemetry from the node section */ 00865 00866 telemetry = ast_variable_retrieve(cfg, node, TELEMETRY); 00867 if(telemetry){ 00868 telemetry_save = ast_strdupa(telemetry); 00869 if(!telemetry_save){ 00870 ast_log(LOG_WARNING,"ast_strdupa() failed in telem_lookup()\n"); 00871 return res; 00872 } 00873 entry = ast_variable_retrieve(cfg, telemetry_save, name); 00874 } 00875 00876 /* Try to look up the telemetry name */ 00877 00878 if(!entry){ 00879 /* Telemetry name wasn't found in the config file, use the default */ 00880 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){ 00881 if(!strcasecmp(tele_defs[i].name, name)) 00882 entry = tele_defs[i].value; 00883 } 00884 } 00885 if(entry) 00886 telem_any(chan, entry); 00887 else{ 00888 ast_log(LOG_WARNING, "Telemetry name not found: %s\n", name); 00889 res = -1; 00890 } 00891 return res; 00892 }
int unload_module | ( | void | ) |
Cleanup all module structures, sockets, etc.
This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 6517 of file app_rpt.c.
References ast_cli_unregister(), ast_mutex_destroy(), ast_unregister_application(), cli_debug, lock, name, rpt_vars, and STANDARD_HANGUP_LOCALUSERS.
06518 { 06519 int i; 06520 06521 STANDARD_HANGUP_LOCALUSERS; 06522 for(i = 0; i < nrpts; i++) { 06523 if (!strcmp(rpt_vars[i].name,rpt_vars[i].nodes)) continue; 06524 ast_mutex_destroy(&rpt_vars[i].lock); 06525 } 06526 i = ast_unregister_application(app); 06527 06528 /* Unregister cli extensions */ 06529 ast_cli_unregister(&cli_debug); 06530 06531 return i; 06532 }
int usecount | ( | void | ) |
Provides a usecount.
This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 6549 of file app_rpt.c.
References STANDARD_USECOUNT.
06550 { 06551 int res; 06552 STANDARD_USECOUNT(res); 06553 return res; 06554 }
static void wait_interval | ( | struct rpt * | myrpt, | |
int | type, | |||
struct ast_channel * | chan | |||
) | [static] |
Definition at line 956 of file app_rpt.c.
References ast_safe_sleep(), and get_wait_interval().
Referenced by rpt_tele_thread().
00957 { 00958 int interval; 00959 if((interval = get_wait_interval(myrpt, type))) 00960 ast_safe_sleep(chan,interval); 00961 return; 00962 }
struct ast_config* cfg |
Definition at line 248 of file app_rpt.c.
Referenced by __load_resource(), ast_config_destroy(), ast_config_get_current_category(), ast_config_internal_load(), ast_config_load(), ast_config_set_current_category(), ast_enum_init(), ast_load_resource(), ast_readconfig(), ast_rtp_reload(), attempt_reconnect(), authenticate(), collect_function_digits(), conf_exec(), config_load(), config_odbc(), config_text_file_load(), config_text_file_save(), directory_exec(), do_directory(), festival_exec(), find_conf(), function_ilink(), function_remote(), get_wait_interval(), handle_save_dialplan(), iax_process_template(), iax_provision_reload(), iax_template_parse(), ind_load_module(), init_acf_query(), init_logger_chain(), init_manager(), load_config(), load_module(), load_modules(), load_moh_classes(), load_odbc_config(), loadconfigurationfile(), misdn_cfg_init(), my_load_module(), odbc_load_module(), osp_build(), parse_config(), pbx_load_module(), privacy_exec(), process_my_load_module(), process_text_line(), read_agent_config(), realtime_directory(), realtime_multi_odbc(), realtime_switch_common(), reload(), reload_config(), reload_queues(), retrieve_astcfgint(), rpt(), rpt_exec(), rpt_master(), rpt_tele_thread(), set_config(), setup_zap(), store_config(), tds_load_module(), and telem_lookup().
struct ast_cli_entry cli_debug [static] |
Initial value:
{ { "rpt", "debug", "level" }, rpt_do_debug, "Enable app_rpt debugging", debug_usage }
char debug_usage[] [static] |
struct function_table_tag function_table[] [static] |
char* remote_rig_ft897 = "ft897" [static] |
char* remote_rig_rbi = "rbi" [static] |
pthread_t rpt_master_thread [static] |
Referenced by rpt_exec(), rpt_master(), and unload_module().
char* synopsis = "Radio Repeater/Remote Base Control System" [static] |
char* tdesc = "Radio Repeater / Remote Base version 0.37 11/03/2005" [static] |
struct telem_defaults tele_defs[] [static] |