#include "asterisk.h"
#include <signal.h>
#include <search.h>
#include <sys/stat.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 <dahdi/user.h>
#include <dahdi/tonezone.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/file.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/cli.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/localtime.h"
#include "asterisk/app.h"
Go to the source code of this file.
Data Structures | |
struct | function_table_tag |
struct | morse_bits |
struct | rpt |
struct | rpt_link |
struct | rpt_lstat |
struct | rpt_tele |
struct | telem_defaults |
Defines | |
#define | ACTIONSIZE 32 |
#define | DEFAULT_IOBASE 0x378 |
#define | DELIMCHR ',' |
#define | DISC_TIME 10000 |
#define | DTMF_TIMEOUT 3 |
#define | ENDCHAR '#' |
#define | FUNCCHAR '*' |
#define | FUNCTDELAY 1500 |
#define | FUNCTIONS "functions" |
#define | GOSUB "gosub" |
#define | GOSUBPTIME 500 |
#define | GOSUBTIME 100 |
#define | HANGTIME 5000 |
#define | IDTIME 300000 |
#define | MACRO "macro" |
#define | MACROPTIME 500 |
#define | MACROTIME 100 |
#define | MAX_RETRIES 5 |
#define | MAX_STAT_LINKS 32 |
#define | MAXCONNECTTIME 5000 |
#define | MAXDTMF 32 |
#define | MAXGOSUB 2048 |
#define | MAXMACRO 2048 |
#define | MAXNODESTR 300 |
#define | MAXPATCHCONTEXT 100 |
#define | MAXPEERSTR 31 |
#define | MAXREMSTR 15 |
#define | MAXRPTS 20 |
#define | MEMORY "memory" |
#define | MORSE "morse" |
#define | MSWAIT 200 |
#define | NODES "nodes" |
#define | POLITEID 30000 |
#define | QUOTECHR 34 |
#define | REDUNDANT_TX_TIME 2000 |
#define | REM_SCANTIME 100 |
#define | RETRY_TIMER_MS 5000 |
#define | rpt_mutex_lock(x) ast_mutex_lock(x) |
#define | rpt_mutex_unlock(x) ast_mutex_unlock(x) |
#define | split_ctcss_freq(hertz, decimal, freq) split_decimal(freq, hertz, decimal, 1) |
#define | split_freq(mhz, decimal, freq) split_decimal(freq, mhz, decimal, 5) |
#define | TELEMETRY "telemetry" |
#define | TELEPARAMSIZE 256 |
#define | TOTIME 180000 |
Enumerations | |
enum | { REM_OFF, REM_MONITOR, REM_TX } |
enum | { ID, PROC, TERM, COMPLETE, UNKEY, REMDISC, REMALREADY, REMNOTFOUND, REMGO, CONNECTED, CONNFAIL, STATUS, TIMEOUT, ID1, STATS_TIME, STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH, TAILMSG, MACRO_NOTFOUND, GOSUB_NOTFOUND, MACRO_BUSY, GOSUB_BUSY, LASTNODEKEY } |
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 void | __reg_module (void) |
static void | __unreg_module (void) |
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) |
static void | do_scheduler (struct rpt *myrpt) |
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_gosub (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | function_ilink (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | function_macro (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | function_remote (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | function_status (struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink) |
static int | get_wait_interval (struct rpt *myrpt, int type) |
static char * | handle_cli_rpt_debug_level (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rpt_dump (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rpt_lstats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rpt_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rpt_restart (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_rpt_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static void | handle_link_data (struct rpt *myrpt, struct rpt_link *mylink, char *str) |
static void | handle_link_phone_dtmf (struct rpt *myrpt, struct rpt_link *mylink, char c) |
static int | handle_remote_data (struct rpt *myrpt, char *str) |
static int | handle_remote_dtmf_digit (struct rpt *myrpt, char c, char *keyed, int phonemode) |
static int | handle_remote_phone_dtmf (struct rpt *myrpt, char c, char *keyed, int phonemode) |
static int | load_module (void) |
static void | load_rpt_vars (int n, int init) |
static void | local_dtmf_helper (struct rpt *myrpt, char c) |
static int | matchkeyword (char *string, char **param, char *keywords[]) |
static 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 (const 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 void | queue_id (struct rpt *myrpt) |
static int | rbi_mhztoband (char *str) |
static void | rbi_out (struct rpt *myrpt, unsigned char *data) |
static void | rbi_out_parallel (struct rpt *myrpt, unsigned char *data) |
static int | rbi_pltocode (char *str) |
static int | reload (void) |
static int | retrieve_astcfgint (struct rpt *myrpt, const char *category, const 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_exec (struct ast_channel *chan, void *data) |
static void * | rpt_master (void *config) |
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 | saydigits (struct ast_channel *mychannel, int num) |
static int | sayfile (struct ast_channel *mychannel, const 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, const char *string, int speed, int freq, int amplitude) |
static int | send_tone_telemetry (struct ast_channel *chan, const char *tonestring) |
static int | serial_remote_io (struct rpt *myrpt, unsigned 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 char * | skipchars (char *string, char *charlist) |
static int | split_decimal (char *input, int *ints, int *decs, int places) |
static void | stop_scan (struct rpt *myrpt, int flag) |
static int | telem_any (struct rpt *myrpt, struct ast_channel *chan, const char *entry) |
static int | telem_lookup (struct rpt *myrpt, struct ast_channel *chan, const char *node, const char *name) |
static int | unload_module (void) |
static void | wait_interval (struct rpt *myrpt, int type, struct ast_channel *chan) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Radio Repeater / Remote Base" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } |
static char * | app = "Rpt" |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_cli_entry | cli_rpt [] |
static int | debug = 0 |
static char * | descrip |
char * | discstr = "!!DISCONNECT!!" |
static struct function_table_tag | function_table [] |
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] |
static char * | synopsis = "Radio Repeater/Remote Base Control System" |
static struct telem_defaults | tele_defs [] |
static unsigned int | vmajor = 0 |
static unsigned int | vminor = 47 |
Repeater / Remote Functions: "Simple" Mode: * - autopatch access, # - autopatch hangup Normal mode: See the function list in rpt.conf (autopatchup, autopatchdn) autopatchup can optionally take comma delimited setting=value pairs:
context=string : Override default context with "string" dialtime=ms : Specify the max number of milliseconds between phone number digits (1000 milliseconds = 1 second) farenddisconnect=1 : Automatically disconnect when called party hangs up noct=1 : Don't send repeater courtesy tone during autopatch calls quiet=1 : Don't send dial tone, or connect messages. Do not send patch down message when called party hangs up
Example: 123=autopatchup,dialtime=20000,noct=1,farenddisconnect=1
To send an asterisk (*) while dialing or talking on phone, use the autopatch acess code.
status cmds:
1 - Force ID 2 - Give Time of Day 3 - Give software Version
cop (control operator) cmds:
1 - System warm boot 2 - System enable 3 - System disable 4 - Test Tone On 5 - Dump System Variables on Console (debug) 6 - PTT (phone mode only)
ilink cmds:
1 - Disconnect specified link 2 - Connect specified link -- monitor only 3 - Connect specified link -- tranceive 4 - Enter command mode on specified link 5 - System status 6 - Disconnect all links
remote cmds:
1 - Recall Memory MM (*000-*099) (Gets memory from rpt.conf) 2 - Set VFO MMMMM*KKK*O (Mhz digits, Khz digits, Offset) 3 - Set Rx PL Tone HHH*D* 4 - Set Tx PL Tone HHH*D* (Not currently implemented with DHE RBI-1) 5 - Link Status (long) 6 - Set operating mode M (FM, USB, LSB, AM, etc) 100 - RX PL off (Default) 101 - RX PL On 102 - TX PL Off (Default) 103 - TX PL On 104 - Low Power 105 - Med Power 106 - Hi Power 107 - Bump Down 20 Hz 108 - Bump Down 100 Hz 109 - Bump Down 500 Hz 110 - Bump Up 20 Hz 111 - Bump Up 100 Hz 112 - Bump Up 500 Hz 113 - Scan Down Slow 114 - Scan Down Medium 115 - Scan Down Fast 116 - Scan Up Slow 117 - Scan Up Medium 118 - Scan Up Fast 119 - Transmit allowing auto-tune 140 - Link Status (brief)
'duplex' modes: (defaults to duplex=2)
0 - Only remote links key Tx and no main repeat audio. 1 - Everything other then main Rx keys Tx, no main repeat audio. 2 - Normal mode 3 - Normal except no main repeat audio. 4 - Normal except no main repeat audio during autopatch only
Definition in file app_rpt.c.
#define DEFAULT_IOBASE 0x378 |
#define DTMF_TIMEOUT 3 |
#define ENDCHAR '#' |
#define FUNCCHAR '*' |
#define FUNCTIONS "functions" |
#define GOSUB "gosub" |
#define GOSUBTIME 100 |
#define HANGTIME 5000 |
#define IDTIME 300000 |
#define MACRO "macro" |
#define MACROTIME 100 |
#define MAX_RETRIES 5 |
Definition at line 148 of file app_rpt.c.
Referenced by function_ilink(), handle_link_data(), and rpt().
#define MAX_STAT_LINKS 32 |
#define MAXDTMF 32 |
Definition at line 134 of file app_rpt.c.
Referenced by handle_link_data(), handle_link_phone_dtmf(), handle_remote_dtmf_digit(), and local_dtmf_helper().
#define MAXNODESTR 300 |
#define MAXPEERSTR 31 |
#define MAXREMSTR 15 |
Definition at line 155 of file app_rpt.c.
Referenced by handle_cli_rpt_lstats(), multimode_bump_freq_ft897(), and setrbi().
#define MEMORY "memory" |
#define MORSE "morse" |
#define MSWAIT 200 |
#define NODES "nodes" |
#define POLITEID 30000 |
#define REM_SCANTIME 100 |
#define rpt_mutex_lock | ( | x | ) | ast_mutex_lock(x) |
Definition at line 678 of file app_rpt.c.
Referenced by attempt_reconnect(), function_autopatchdn(), function_gosub(), function_ilink(), function_macro(), handle_cli_rpt_lstats(), handle_cli_rpt_stats(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), queue_id(), rpt(), rpt_call(), rpt_tele_thread(), and rpt_telemetry().
#define rpt_mutex_unlock | ( | x | ) | ast_mutex_unlock(x) |
Definition at line 679 of file app_rpt.c.
Referenced by attempt_reconnect(), function_autopatchdn(), function_gosub(), function_ilink(), function_macro(), handle_cli_rpt_lstats(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), queue_id(), rpt(), rpt_call(), rpt_tele_thread(), and rpt_telemetry().
#define split_ctcss_freq | ( | hertz, | |||
decimal, | |||||
freq | ) | split_decimal(freq, hertz, decimal, 1) |
#define split_freq | ( | mhz, | |||
decimal, | |||||
freq | ) | split_decimal(freq, mhz, decimal, 5) |
Definition at line 4119 of file app_rpt.c.
Referenced by function_remote(), multimode_bump_freq_ft897(), service_scan(), and set_freq_ft897().
#define TELEMETRY "telemetry" |
#define TOTIME 180000 |
anonymous enum |
anonymous enum |
Definition at line 187 of file app_rpt.c.
00187 {ID, PROC, TERM, COMPLETE, UNKEY, REMDISC, REMALREADY, REMNOTFOUND, REMGO, 00188 CONNECTED, CONNFAIL, STATUS, TIMEOUT, ID1, STATS_TIME, 00189 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH, 00190 TAILMSG, MACRO_NOTFOUND, GOSUB_NOTFOUND, MACRO_BUSY, GOSUB_BUSY, LASTNODEKEY};
anonymous enum |
anonymous enum |
anonymous enum |
Definition at line 196 of file app_rpt.c.
00196 {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_DOKEY};
anonymous enum |
Definition at line 198 of file app_rpt.c.
00198 {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE};
anonymous enum |
anonymous enum |
Definition at line 202 of file app_rpt.c.
00202 {REM_MODE_FM, REM_MODE_USB, REM_MODE_LSB, REM_MODE_AM};
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 204 of file app_rpt.c.
00204 {HF_SCAN_OFF, HF_SCAN_DOWN_SLOW, HF_SCAN_DOWN_QUICK, 00205 HF_SCAN_DOWN_FAST, HF_SCAN_UP_SLOW, HF_SCAN_UP_QUICK, HF_SCAN_UP_FAST};
Definition at line 5428 of file app_rpt.c.
References AST_APP_ARG, ast_call(), AST_DECLARE_APP_ARGS, AST_FORMAT_SLINEAR, ast_free, ast_log(), ast_request(), ast_set_read_format(), ast_set_write_format(), AST_STANDARD_APP_ARGS, ast_strdup, ast_strdupa, ast_variable_retrieve(), ast_verb, rpt::cfg, rpt::links, rpt::lock, LOG_ERROR, LOG_NOTICE, rpt::name, rpt_link::name, rpt_link::next, rpt::nodes, rpt::p, rpt_mutex_lock, rpt_mutex_unlock, and s.
Referenced by rpt().
05429 { 05430 const char *val; 05431 char *s, *tele; 05432 char deststr[300] = ""; 05433 AST_DECLARE_APP_ARGS(args, 05434 AST_APP_ARG(channel); 05435 AST_APP_ARG(extra); 05436 ); 05437 05438 val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, l->name); 05439 if (!val) { 05440 ast_log(LOG_ERROR, "attempt_reconnect: cannot find node %s\n", l->name); 05441 return -1; 05442 } 05443 05444 rpt_mutex_lock(&myrpt->lock); 05445 /* remove from queue */ 05446 remque((struct qelem *) l); 05447 rpt_mutex_unlock(&myrpt->lock); 05448 s = ast_strdupa(val); 05449 AST_STANDARD_APP_ARGS(args, s); 05450 05451 /* XXX This section doesn't make any sense. Why not just use args.channel? XXX */ 05452 snprintf(deststr, sizeof(deststr), "IAX2/%s", args.channel); 05453 tele = strchr(deststr, '/'); 05454 if (!tele) { 05455 ast_log(LOG_ERROR, "attempt_reconnect:Dial number (%s) must be in format tech/number\n", deststr); 05456 return -1; 05457 } 05458 *tele++ = 0; 05459 l->elaptime = 0; 05460 l->connecttime = 0; 05461 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele, NULL); 05462 if (l->chan) { 05463 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR); 05464 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR); 05465 l->chan->whentohangup = 0; 05466 l->chan->appl = "Apprpt"; 05467 l->chan->data = "(Remote Rx)"; 05468 ast_verb(3, "rpt (attempt_reconnect) initiating call to %s/%s on %s\n", 05469 deststr, tele, l->chan->name); 05470 if (l->chan->cid.cid_num) 05471 ast_free(l->chan->cid.cid_num); 05472 l->chan->cid.cid_num = ast_strdup(myrpt->name); 05473 ast_call(l->chan, tele, 999); 05474 05475 } else { 05476 ast_verb(3, "Unable to place call to %s/%s on %s\n", 05477 deststr, tele, l->chan->name); 05478 return -1; 05479 } 05480 rpt_mutex_lock(&myrpt->lock); 05481 /* put back in queue */ 05482 insque((struct qelem *)l, (struct qelem *)myrpt->links.next); 05483 rpt_mutex_unlock(&myrpt->lock); 05484 ast_log(LOG_NOTICE, "Reconnect Attempt to %s in process\n", l->name); 05485 return 0; 05486 }
static int check_freq | ( | struct rpt * | myrpt, | |
int | m, | |||
int | d, | |||
int * | defmode | |||
) | [static] |
Definition at line 4459 of file app_rpt.c.
References check_freq_ft897(), check_freq_rbi(), and rpt::remote.
Referenced by function_remote().
04460 { 04461 if (!strcmp(myrpt->remote, remote_rig_ft897)) 04462 return check_freq_ft897(m, d, defmode); 04463 else if (!strcmp(myrpt->remote, remote_rig_rbi)) 04464 return check_freq_rbi(m, d, defmode); 04465 else 04466 return -1; 04467 }
static int check_freq_ft897 | ( | int | m, | |
int | d, | |||
int * | defmode | |||
) | [static] |
Definition at line 4134 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().
04135 { 04136 int dflmd = REM_MODE_FM; 04137 04138 if (m == 1) { /* 160 meters */ 04139 dflmd = REM_MODE_LSB; 04140 if (d < 80001) 04141 return -1; 04142 } else if (m == 3) { /* 80 meters */ 04143 dflmd = REM_MODE_LSB; 04144 if (d < 75001) 04145 return -1; 04146 } else if (m == 7) { /* 40 meters */ 04147 dflmd = REM_MODE_LSB; 04148 if ((d < 15001) || (d > 29999)) 04149 return -1; 04150 } else if (m == 14) { /* 20 meters */ 04151 dflmd = REM_MODE_USB; 04152 if ((d < 15001) || (d > 34999)) 04153 return -1; 04154 } else if (m == 18) { /* 17 meters */ 04155 dflmd = REM_MODE_USB; 04156 if ((d < 11001) || (d > 16797)) 04157 return -1; 04158 } else if (m == 21) { /* 15 meters */ 04159 dflmd = REM_MODE_USB; 04160 if ((d < 20001) || (d > 44999)) 04161 return -1; 04162 } else if (m == 24) { /* 12 meters */ 04163 dflmd = REM_MODE_USB; 04164 if ((d < 93001) || (d > 98999)) 04165 return -1; 04166 } else if (m == 28) { /* 10 meters */ 04167 dflmd = REM_MODE_USB; 04168 if (d < 30001) 04169 return -1; 04170 } else if (m == 29) { 04171 if (d >= 51000) 04172 dflmd = REM_MODE_FM; 04173 else 04174 dflmd = REM_MODE_USB; 04175 if (d > 69999) 04176 return -1; 04177 } else if (m == 50) { /* 6 meters */ 04178 if (d < 10100) 04179 return -1; 04180 if (d >= 30000) 04181 dflmd = REM_MODE_FM; 04182 else 04183 dflmd = REM_MODE_USB; 04184 } else if ((m >= 51) && ( m < 54)) { 04185 dflmd = REM_MODE_FM; 04186 } else if (m == 144) { /* 2 meters */ 04187 if (d < 10100) 04188 return -1; 04189 if (d >= 30000) 04190 dflmd = REM_MODE_FM; 04191 else 04192 dflmd = REM_MODE_USB; 04193 } else if ((m >= 145) && (m < 148)) { 04194 dflmd = REM_MODE_FM; 04195 } else if ((m >= 430) && (m < 450)) { /* 70 centimeters */ 04196 if (m < 438) 04197 dflmd = REM_MODE_USB; 04198 else 04199 dflmd = REM_MODE_FM; 04200 ; 04201 } else 04202 return -1; 04203 04204 if (defmode) 04205 *defmode = dflmd; 04206 04207 return 0; 04208 }
static int check_freq_rbi | ( | int | m, | |
int | d, | |||
int * | defmode | |||
) | [static] |
Definition at line 4073 of file app_rpt.c.
References REM_MODE_FM.
Referenced by check_freq().
04074 { 04075 int dflmd = REM_MODE_FM; 04076 04077 if (m == 50) { /* 6 meters */ 04078 if (d < 10100) 04079 return -1; 04080 } else if ((m >= 51) && ( m < 54)) { 04081 /* nada */ 04082 } else if (m == 144) { /* 2 meters */ 04083 if (d < 10100) 04084 return -1; 04085 } else if ((m >= 145) && (m < 148)) { 04086 /* nada */ 04087 } else if ((m >= 222) && (m < 225)) { /* 1.25 meters */ 04088 /* nada */ 04089 } else if ((m >= 430) && (m < 450)) { /* 70 centimeters */ 04090 /* nada */ 04091 } else if ((m >= 1240) && (m < 1300)) { /* 23 centimeters */ 04092 /* nada */ 04093 } else 04094 return -1; 04095 04096 if (defmode) 04097 *defmode = dflmd; 04098 04099 return 0; 04100 }
static int closerem | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 4446 of file app_rpt.c.
References closerem_ft897(), and rpt::remote.
04447 { 04448 return 0; /* XXX BROKEN!! */ 04449 if (!strcmp(myrpt->remote, remote_rig_ft897)) 04450 return closerem_ft897(myrpt); 04451 else 04452 return 0; 04453 }
static int closerem_ft897 | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 4388 of file app_rpt.c.
References simple_command_ft897().
Referenced by closerem().
04389 { 04390 simple_command_ft897(myrpt, 0x88); /* PTT off */ 04391 return 0; 04392 }
static int collect_function_digits | ( | struct rpt * | myrpt, | |
char * | digits, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 3411 of file app_rpt.c.
References function_table_tag::action, AST_APP_ARG, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_variable_browse(), rpt::cfg, DC_ERROR, DC_INDETERMINATE, rpt::dphone_functions, rpt::dphone_longestfunc, function_table, rpt::functions, rpt::link_functions, rpt::link_longestfunc, rpt::longestfunc, ast_variable::name, ast_variable::next, rpt::p, rpt::phone_functions, rpt::phone_longestfunc, S_OR, SOURCE_DPHONE, SOURCE_LNK, SOURCE_PHONE, and ast_variable::value.
Referenced by handle_link_data(), handle_link_phone_dtmf(), handle_remote_dtmf_digit(), and local_dtmf_helper().
03412 { 03413 int i; 03414 char *stringp, *functiondigits; 03415 char function_table_name[30] = ""; 03416 struct ast_variable *vp; 03417 AST_DECLARE_APP_ARGS(args, 03418 AST_APP_ARG(action); 03419 AST_APP_ARG(param); 03420 ); 03421 03422 ast_debug(1, "@@@@ Digits collected: %s, source: %d\n", digits, command_source); 03423 03424 if (command_source == SOURCE_DPHONE) { 03425 if (!myrpt->p.dphone_functions) 03426 return DC_INDETERMINATE; 03427 ast_copy_string(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name)); 03428 } else if (command_source == SOURCE_PHONE) { 03429 if (!myrpt->p.phone_functions) 03430 return DC_INDETERMINATE; 03431 ast_copy_string(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name)); 03432 } else if (command_source == SOURCE_LNK) 03433 ast_copy_string(function_table_name, myrpt->p.link_functions, sizeof(function_table_name)); 03434 else 03435 ast_copy_string(function_table_name, myrpt->p.functions, sizeof(function_table_name)); 03436 03437 for (vp = ast_variable_browse(myrpt->cfg, function_table_name); vp; vp = vp->next) { 03438 if (!strncasecmp(vp->name, digits, strlen(vp->name))) 03439 break; 03440 } 03441 if (!vp) { 03442 int n; 03443 03444 n = myrpt->longestfunc; 03445 if (command_source == SOURCE_LNK) 03446 n = myrpt->link_longestfunc; 03447 else if (command_source == SOURCE_PHONE) 03448 n = myrpt->phone_longestfunc; 03449 else if (command_source == SOURCE_DPHONE) 03450 n = myrpt->dphone_longestfunc; 03451 03452 if (strlen(digits) >= n) 03453 return DC_ERROR; 03454 else 03455 return DC_INDETERMINATE; 03456 } 03457 03458 /* Found a match, retrieve value part and parse */ 03459 stringp = ast_strdupa(vp->value); 03460 AST_STANDARD_APP_ARGS(args, stringp); 03461 03462 ast_debug(1, "@@@@ action: %s, param = %s\n", args.action, S_OR(args.param, "(null)")); 03463 /* Look up the action */ 03464 for (i = 0; i < (sizeof(function_table) / sizeof(struct function_table_tag)); i++) { 03465 if (!strncasecmp(args.action, function_table[i].action, strlen(args.action))) 03466 break; 03467 } 03468 ast_debug(1, "@@@@ table index i = %d\n", i); 03469 if (i == (sizeof(function_table) / sizeof(struct function_table_tag))) { 03470 /* Error, action not in table */ 03471 return DC_ERROR; 03472 } 03473 if (function_table[i].function == NULL) { 03474 /* Error, function undefined */ 03475 ast_debug(1, "@@@@ NULL for action: %s\n", args.action); 03476 return DC_ERROR; 03477 } 03478 functiondigits = digits + strlen(vp->name); 03479 return (*function_table[i].function)(myrpt, args.param, functiondigits, command_source, mylink); 03480 }
static void do_scheduler | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 5624 of file app_rpt.c.
References ast_localtime(), ast_log(), rpt::curtv, rpt::dailyexecdcommands, rpt::dailykerchunks, rpt::dailykeyups, rpt::dailytxtime, LOG_NOTICE, ast_tm::tm_hour, ast_tm::tm_min, and ast_tm::tm_sec.
Referenced by rpt().
05625 { 05626 int res; 05627 struct ast_tm tmnow; 05628 05629 memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval)); 05630 05631 if ( (res = gettimeofday(&myrpt->curtv, NULL)) < 0) 05632 ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res)); 05633 05634 /* Try to get close to a 1 second resolution */ 05635 05636 if (myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec) 05637 return; 05638 05639 ast_localtime(&myrpt->curtv, &tmnow, NULL); 05640 05641 /* If midnight, then reset all daily statistics */ 05642 05643 if ((tmnow.tm_hour == 0) && (tmnow.tm_min == 0) && (tmnow.tm_sec == 0)) { 05644 myrpt->dailykeyups = 0; 05645 myrpt->dailytxtime = 0; 05646 myrpt->dailykerchunks = 0; 05647 myrpt->dailyexecdcommands = 0; 05648 } 05649 }
static int function_autopatchdn | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 3226 of file app_rpt.c.
References ast_debug, rpt::callmode, DC_COMPLETE, DC_ERROR, rpt::enable, rpt::lock, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), and TERM.
03227 { 03228 if (!myrpt->enable) 03229 return DC_ERROR; 03230 03231 ast_debug(1, "@@@@ Autopatch down\n"); 03232 03233 rpt_mutex_lock(&myrpt->lock); 03234 03235 if (!myrpt->callmode) { 03236 rpt_mutex_unlock(&myrpt->lock); 03237 return DC_COMPLETE; 03238 } 03239 03240 myrpt->callmode = 0; 03241 rpt_mutex_unlock(&myrpt->lock); 03242 rpt_telemetry(myrpt, TERM, NULL); 03243 return DC_COMPLETE; 03244 }
static int function_autopatchup | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 3142 of file app_rpt.c.
References AST_APP_ARG, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, rpt::callmode, DC_ERROR, rpt::enable, matchkeyword(), rpt::ourcontext, rpt::p, rpt::patchcontext, rpt::patchdialtime, rpt::patchfarenddisconnect, rpt::patchnoct, rpt::patchquiet, and skipchars().
03143 { 03144 int i, index; 03145 char *value = NULL; 03146 AST_DECLARE_APP_ARGS(params, 03147 AST_APP_ARG(list)[20]; 03148 ); 03149 03150 static char *keywords[] = { 03151 "context", 03152 "dialtime", 03153 "farenddisconnect", 03154 "noct", 03155 "quiet", 03156 NULL 03157 }; 03158 03159 if (!myrpt->enable) 03160 return DC_ERROR; 03161 03162 ast_debug(1, "@@@@ Autopatch up\n"); 03163 03164 if (!myrpt->callmode) { 03165 /* Set defaults */ 03166 myrpt->patchnoct = 0; 03167 myrpt->patchdialtime = 0; 03168 myrpt->patchfarenddisconnect = 0; 03169 myrpt->patchquiet = 0; 03170 ast_copy_string(myrpt->patchcontext, myrpt->p.ourcontext, sizeof(myrpt->patchcontext)); 03171 03172 if (param) { 03173 /* Process parameter list */ 03174 char *tmp = ast_strdupa(param); 03175 AST_STANDARD_APP_ARGS(params, tmp); 03176 for (i = 0; i < params.argc; i++) { 03177 index = matchkeyword(params.list[i], &value, keywords); 03178 if (value) 03179 value = skipchars(value, "= "); 03180 switch (index) { 03181 case 1: /* context */ 03182 ast_copy_string(myrpt->patchcontext, value, sizeof(myrpt->patchcontext)) ; 03183 break; 03184 case 2: /* dialtime */ 03185 myrpt->patchdialtime = atoi(value); 03186 break; 03187 case 3: /* farenddisconnect */ 03188 myrpt->patchfarenddisconnect = atoi(value); 03189 break; 03190 case 4: /* noct */ 03191 myrpt->patchnoct = atoi(value); 03192 break; 03193 case 5: /* quiet */ 03194 myrpt->patchquiet = atoi(value); 03195 break; 03196 default: 03197 break; 03198 } 03199 } 03200 } 03201 } 03202 03203 rpt_mutex_lock(&myrpt->lock); 03204 03205 /* if on call, force * into current audio stream */ 03206 03207 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) { 03208 myrpt->mydtmf = myrpt->p.funcchar; 03209 } 03210 if (myrpt->callmode) { 03211 rpt_mutex_unlock(&myrpt->lock); 03212 return DC_COMPLETE; 03213 } 03214 myrpt->callmode = 1; 03215 myrpt->cidx = 0; 03216 myrpt->exten[myrpt->cidx] = 0; 03217 rpt_mutex_unlock(&myrpt->lock); 03218 ast_pthread_create_detached(&myrpt->rpt_call_thread, NULL, rpt_call, (void *) myrpt); 03219 return DC_COMPLETE; 03220 }
static int function_cop | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 3377 of file app_rpt.c.
References ARB_ALPHA, ast_cli_command(), DC_COMPLETE, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, rpt::disgorgetime, rpt::enable, myatoi(), rpt_telemetry(), SOURCE_PHONE, and TEST_TONE.
03378 { 03379 if (!param) 03380 return DC_ERROR; 03381 03382 switch(myatoi(param)) { 03383 case 1: /* System reset */ 03384 ast_cli_command(STDERR_FILENO, "restart now"); /* A little less drastic than what was previously here. */ 03385 return DC_COMPLETE; 03386 case 2: 03387 myrpt->enable = 1; 03388 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA"); 03389 return DC_COMPLETE; 03390 case 3: 03391 myrpt->enable = 0; 03392 return DC_COMPLETE; 03393 case 4: /* test tone on */ 03394 rpt_telemetry(myrpt, TEST_TONE, NULL); 03395 return DC_COMPLETE; 03396 case 5: /* Disgorge variables to log for debug purposes */ 03397 myrpt->disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */ 03398 return DC_COMPLETE; 03399 case 6: /* Simulate COR being activated (phone only) */ 03400 if (command_source != SOURCE_PHONE) 03401 return DC_INDETERMINATE; 03402 return DC_DOKEY; 03403 } 03404 return DC_INDETERMINATE; 03405 }
static int function_gosub | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 3329 of file app_rpt.c.
References ast_log(), ast_strlen_zero(), ast_variable_retrieve(), rpt::cfg, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt::enable, rpt::gosub, GOSUB_BUSY, GOSUB_NOTFOUND, rpt::gosubbuf, GOSUBTIME, rpt::gosubtimer, rpt::lock, LOG_DEBUG, rpt::p, rpt::remchannel, rpt::remote, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), and rpt::startupgosub.
03330 { 03331 03332 const char *val; 03333 int i; 03334 struct ast_channel *mychannel; 03335 03336 if ((!myrpt->remote) && (!myrpt->enable)) 03337 return DC_ERROR; 03338 03339 if (debug) 03340 ast_log(LOG_DEBUG, "@@@@ gosub param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf); 03341 03342 mychannel = myrpt->remchannel; 03343 03344 if (ast_strlen_zero(digitbuf)) /* needs 1 digit */ 03345 return DC_INDETERMINATE; 03346 03347 for (i = 0; i < digitbuf[i]; i++) { 03348 if ((digitbuf[i] < '0') || (digitbuf[i] > '9')) 03349 return DC_ERROR; 03350 } 03351 03352 if (*digitbuf == '0') 03353 val = myrpt->p.startupgosub; 03354 else 03355 val = ast_variable_retrieve(myrpt->cfg, myrpt->p.gosub, digitbuf); 03356 /* param was 1 for local buf */ 03357 if (!val) { 03358 rpt_telemetry(myrpt, GOSUB_NOTFOUND, NULL); 03359 return DC_COMPLETE; 03360 } 03361 rpt_mutex_lock(&myrpt->lock); 03362 if ((sizeof(myrpt->gosubbuf) - strlen(myrpt->gosubbuf)) < strlen(val)) { 03363 rpt_mutex_unlock(&myrpt->lock); 03364 rpt_telemetry(myrpt, GOSUB_BUSY, NULL); 03365 return DC_ERROR; 03366 } 03367 myrpt->gosubtimer = GOSUBTIME; 03368 strncat(myrpt->gosubbuf, val, sizeof(myrpt->gosubbuf) - strlen(myrpt->gosubbuf) - 1); 03369 rpt_mutex_unlock(&myrpt->lock); 03370 return DC_COMPLETE; 03371 }
static int function_ilink | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 2800 of file app_rpt.c.
References AST_APP_ARG, ast_call(), ast_calloc, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, AST_FORMAT_SLINEAR, AST_FRAME_TEXT, ast_free, ast_hangup(), ast_log(), ast_request(), ast_safe_sleep(), ast_set_read_format(), ast_set_write_format(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_STANDARD_APP_ARGS, ast_strdup, ast_strdupa, ast_true(), ast_variable_retrieve(), ast_verb, ast_write(), rpt::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, rpt::lastlinknode, LASTNODEKEY, rpt::links, rpt::lock, LOG_ERROR, LOG_WARNING, rpt::longestnode, ast_frame::mallocd, MAX_RETRIES, MAXNODESTR, rpt_link::mode, myatoi(), rpt::name, rpt_link::name, rpt_link::next, rpt::nodes, ast_frame::offset, rpt::p, rpt_link::reconnects, REMALREADY, REMGO, rpt_link::retries, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), s, S_OR, ast_frame::samples, SOURCE_DPHONE, SOURCE_PHONE, SOURCE_RPT, STATUS, and ast_frame::subclass.
02801 { 02802 const char *val; 02803 char *s, *tele; 02804 char deststr[300] = "", modechange = 0; 02805 char digitbuf[MAXNODESTR]; 02806 struct rpt_link *l; 02807 int reconnects = 0; 02808 struct dahdi_confinfo ci; /* conference info */ 02809 AST_DECLARE_APP_ARGS(args, 02810 AST_APP_ARG(s1); 02811 AST_APP_ARG(s2); /* XXX Never used. Scratch? XXX */ 02812 ); 02813 02814 if (!param) 02815 return DC_ERROR; 02816 02817 if (!myrpt->enable) 02818 return DC_ERROR; 02819 02820 ast_copy_string(digitbuf, digits, sizeof(digitbuf)); 02821 ast_debug(1, "@@@@ ilink param = %s, digitbuf = %s\n", S_OR(param, "(null)"), digitbuf); 02822 02823 switch (myatoi(param)) { 02824 case 1: /* Link off */ 02825 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0])) 02826 strcpy(digitbuf, myrpt->lastlinknode); 02827 val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf); 02828 if (!val) { 02829 if (strlen(digitbuf) >= myrpt->longestnode) 02830 return DC_ERROR; 02831 break; 02832 } 02833 rpt_mutex_lock(&myrpt->lock); 02834 l = myrpt->links.next; 02835 /* try to find this one in queue */ 02836 while (l != &myrpt->links) { 02837 if (l->name[0] == '0') { 02838 l = l->next; 02839 continue; 02840 } 02841 /* if found matching string */ 02842 if (!strcmp(l->name, digitbuf)) 02843 break; 02844 l = l->next; 02845 } 02846 if (l != &myrpt->links) { /* if found */ 02847 struct ast_frame wf; 02848 ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR); 02849 l->retries = MAX_RETRIES + 1; 02850 l->disced = 1; 02851 rpt_mutex_unlock(&myrpt->lock); 02852 wf.frametype = AST_FRAME_TEXT; 02853 wf.subclass = 0; 02854 wf.offset = 0; 02855 wf.mallocd = 1; 02856 wf.datalen = strlen(discstr) + 1; 02857 wf.samples = 0; 02858 wf.data = ast_strdup(discstr); 02859 if (l->chan) { 02860 ast_write(l->chan, &wf); 02861 if (ast_safe_sleep(l->chan, 250) == -1) 02862 return DC_ERROR; 02863 ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); 02864 } 02865 rpt_telemetry(myrpt, COMPLETE, NULL); 02866 return DC_COMPLETE; 02867 } 02868 rpt_mutex_unlock(&myrpt->lock); 02869 return DC_COMPLETE; 02870 case 2: /* Link Monitor */ 02871 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0])) 02872 strcpy(digitbuf, myrpt->lastlinknode); 02873 val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf); 02874 if (!val) { 02875 if (strlen(digitbuf) >= myrpt->longestnode) 02876 return DC_ERROR; 02877 break; 02878 } 02879 s = ast_strdupa(val); 02880 AST_STANDARD_APP_ARGS(args, s); 02881 rpt_mutex_lock(&myrpt->lock); 02882 l = myrpt->links.next; 02883 /* try to find this one in queue */ 02884 while (l != &myrpt->links) { 02885 if (l->name[0] == '0') { 02886 l = l->next; 02887 continue; 02888 } 02889 /* if found matching string */ 02890 if (!strcmp(l->name, digitbuf)) 02891 break; 02892 l = l->next; 02893 } 02894 /* if found */ 02895 if (l != &myrpt->links) { 02896 /* if already in this mode, just ignore */ 02897 if ((!l->mode) || (!l->chan)) { 02898 rpt_mutex_unlock(&myrpt->lock); 02899 rpt_telemetry(myrpt, REMALREADY, NULL); 02900 return DC_COMPLETE; 02901 } 02902 reconnects = l->reconnects; 02903 rpt_mutex_unlock(&myrpt->lock); 02904 if (l->chan) 02905 ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); 02906 l->retries = MAX_RETRIES + 1; 02907 l->disced = 2; 02908 modechange = 1; 02909 } else 02910 rpt_mutex_unlock(&myrpt->lock); 02911 ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR); 02912 /* establish call in monitor mode */ 02913 l = ast_calloc(1, sizeof(*l)); 02914 if (!l) { 02915 ast_log(LOG_WARNING, "Unable to malloc\n"); 02916 return DC_ERROR; 02917 } 02918 snprintf(deststr, sizeof(deststr), "IAX2/%s", args.s1); 02919 tele = strchr(deststr, '/'); 02920 if (!tele) { 02921 ast_log(LOG_ERROR, "link2:Dial number (%s) must be in format tech/number\n", deststr); 02922 return DC_ERROR; 02923 } 02924 *tele++ = 0; 02925 l->isremote = (s && ast_true(s)); 02926 ast_copy_string(l->name, digitbuf, MAXNODESTR); 02927 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele, NULL); 02928 if (modechange) 02929 l->connected = 1; 02930 if (l->chan) { 02931 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR); 02932 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR); 02933 l->chan->whentohangup = 0; 02934 l->chan->appl = "Apprpt"; 02935 l->chan->data = "(Remote Rx)"; 02936 ast_verb(3, "rpt (remote) initiating call to %s/%s on %s\n", 02937 deststr, tele, l->chan->name); 02938 if (l->chan->cid.cid_num) 02939 ast_free(l->chan->cid.cid_num); 02940 l->chan->cid.cid_num = ast_strdup(myrpt->name); 02941 ast_call(l->chan, tele, 0); 02942 } else { 02943 rpt_telemetry(myrpt, CONNFAIL, l); 02944 ast_free(l); 02945 ast_verb(3, "Unable to place call to %s/%s on %s\n", 02946 deststr, tele, l->chan->name); 02947 return DC_ERROR; 02948 } 02949 /* allocate a pseudo-channel thru asterisk */ 02950 l->pchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL); 02951 if (!l->pchan) { 02952 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n"); 02953 ast_hangup(l->chan); 02954 ast_free(l); 02955 return DC_ERROR; 02956 } 02957 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR); 02958 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR); 02959 /* make a conference for the pseudo-one */ 02960 ci.chan = 0; 02961 ci.confno = myrpt->conf; 02962 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER; 02963 /* first put the channel on the conference in proper mode */ 02964 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1) { 02965 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 02966 ast_hangup(l->chan); 02967 ast_hangup(l->pchan); 02968 ast_free(l); 02969 return DC_ERROR; 02970 } 02971 rpt_mutex_lock(&myrpt->lock); 02972 l->reconnects = reconnects; 02973 /* insert at end of queue */ 02974 insque((struct qelem *)l, (struct qelem *)myrpt->links.next); 02975 rpt_mutex_unlock(&myrpt->lock); 02976 rpt_telemetry(myrpt, COMPLETE, NULL); 02977 return DC_COMPLETE; 02978 case 3: /* Link transceive */ 02979 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0])) 02980 strcpy(digitbuf, myrpt->lastlinknode); 02981 val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf); 02982 if (!val) { 02983 if (strlen(digitbuf) >= myrpt->longestnode) 02984 return DC_ERROR; 02985 break; 02986 } 02987 s = ast_strdupa(val); 02988 AST_STANDARD_APP_ARGS(args, s); 02989 rpt_mutex_lock(&myrpt->lock); 02990 l = myrpt->links.next; 02991 /* try to find this one in queue */ 02992 while (l != &myrpt->links) { 02993 if (l->name[0] == '0') { 02994 l = l->next; 02995 continue; 02996 } 02997 /* if found matching string */ 02998 if (!strcmp(l->name, digitbuf)) 02999 break; 03000 l = l->next; 03001 } 03002 /* if found */ 03003 if (l != &myrpt->links) { 03004 /* if already in this mode, just ignore */ 03005 if ((l->mode) || (!l->chan)) { 03006 rpt_mutex_unlock(&myrpt->lock); 03007 rpt_telemetry(myrpt, REMALREADY, NULL); 03008 return DC_COMPLETE; 03009 } 03010 reconnects = l->reconnects; 03011 rpt_mutex_unlock(&myrpt->lock); 03012 if (l->chan) 03013 ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); 03014 l->retries = MAX_RETRIES + 1; 03015 l->disced = 2; 03016 modechange = 1; 03017 } else 03018 rpt_mutex_unlock(&myrpt->lock); 03019 ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR); 03020 /* establish call in tranceive mode */ 03021 l = ast_calloc(1, sizeof(*l)); 03022 if (!l) { 03023 ast_log(LOG_WARNING, "Unable to malloc\n"); 03024 return DC_ERROR; 03025 } 03026 l->mode = 1; 03027 l->outbound = 1; 03028 ast_copy_string(l->name, digitbuf, MAXNODESTR); 03029 l->isremote = (s && ast_true(s)); 03030 if (modechange) 03031 l->connected = 1; 03032 snprintf(deststr, sizeof(deststr), "IAX2/%s", args.s1); 03033 tele = strchr(deststr, '/'); 03034 if (!tele) { 03035 ast_log(LOG_ERROR, "link3:Dial number (%s) must be in format tech/number\n", deststr); 03036 ast_free(l); 03037 return DC_ERROR; 03038 } 03039 *tele++ = 0; 03040 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele, NULL); 03041 if (l->chan) { 03042 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR); 03043 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR); 03044 l->chan->whentohangup = 0; 03045 l->chan->appl = "Apprpt"; 03046 l->chan->data = "(Remote Rx)"; 03047 ast_verb(3, "rpt (remote) initiating call to %s/%s on %s\n", 03048 deststr, tele, l->chan->name); 03049 if (l->chan->cid.cid_num) 03050 ast_free(l->chan->cid.cid_num); 03051 l->chan->cid.cid_num = ast_strdup(myrpt->name); 03052 ast_call(l->chan, tele, 999); 03053 } else { 03054 rpt_telemetry(myrpt, CONNFAIL, l); 03055 ast_free(l); 03056 ast_verb(3, "Unable to place call to %s/%s on %s\n", 03057 deststr, tele, l->chan->name); 03058 return DC_ERROR; 03059 } 03060 /* allocate a pseudo-channel thru asterisk */ 03061 l->pchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL); 03062 if (!l->pchan) { 03063 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n"); 03064 ast_hangup(l->chan); 03065 ast_free(l); 03066 return DC_ERROR; 03067 } 03068 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR); 03069 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR); 03070 /* make a conference for the tx */ 03071 ci.chan = 0; 03072 ci.confno = myrpt->conf; 03073 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER; 03074 /* first put the channel on the conference in proper mode */ 03075 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1) { 03076 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 03077 ast_hangup(l->chan); 03078 ast_hangup(l->pchan); 03079 ast_free(l); 03080 return DC_ERROR; 03081 } 03082 rpt_mutex_lock(&myrpt->lock); 03083 l->reconnects = reconnects; 03084 /* insert at end of queue */ 03085 insque((struct qelem *)l, (struct qelem *)myrpt->links.next); 03086 rpt_mutex_unlock(&myrpt->lock); 03087 rpt_telemetry(myrpt, COMPLETE, NULL); 03088 return DC_COMPLETE; 03089 case 4: /* Enter Command Mode */ 03090 /* if doesnt allow link cmd, or no links active, return */ 03091 if (((command_source != SOURCE_RPT) && 03092 (command_source != SOURCE_PHONE) && 03093 (command_source != SOURCE_DPHONE)) || 03094 (myrpt->links.next == &myrpt->links)) 03095 return DC_COMPLETE; 03096 /* if already in cmd mode, or selected self, fughetabahtit */ 03097 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))) { 03098 rpt_telemetry(myrpt, REMALREADY, NULL); 03099 return DC_COMPLETE; 03100 } 03101 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0])) 03102 strcpy(digitbuf, myrpt->lastlinknode); 03103 /* node must at least exist in list */ 03104 val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf); 03105 if (!val) { 03106 if (strlen(digitbuf) >= myrpt->longestnode) 03107 return DC_ERROR; 03108 break; 03109 } 03110 rpt_mutex_lock(&myrpt->lock); 03111 strcpy(myrpt->lastlinknode, digitbuf); 03112 ast_copy_string(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode)); 03113 rpt_mutex_unlock(&myrpt->lock); 03114 rpt_telemetry(myrpt, REMGO, NULL); 03115 return DC_COMPLETE; 03116 case 5: /* Status */ 03117 rpt_telemetry(myrpt, STATUS, NULL); 03118 return DC_COMPLETE; 03119 case 6: /* All Links Off */ 03120 l = myrpt->links.next; 03121 while (l != &myrpt->links) { /* This code is broke and needs to be changed to work with the reconnect kludge */ 03122 if (l->chan) 03123 ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); /* Hang 'em up */ 03124 l = l->next; 03125 } 03126 rpt_telemetry(myrpt, COMPLETE, NULL); 03127 break; 03128 case 7: /* Identify last node which keyed us up */ 03129 rpt_telemetry(myrpt, LASTNODEKEY, NULL); 03130 break; 03131 default: 03132 return DC_ERROR; 03133 } 03134 03135 return DC_INDETERMINATE; 03136 }
static int function_macro | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 3282 of file app_rpt.c.
References ast_debug, ast_strlen_zero(), ast_variable_retrieve(), rpt::cfg, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt::enable, rpt::lock, rpt::macro, MACRO_BUSY, MACRO_NOTFOUND, rpt::macrobuf, MACROTIME, rpt::macrotimer, rpt::p, rpt::remchannel, rpt::remote, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), and rpt::startupmacro.
03283 { 03284 03285 const char *val; 03286 int i; 03287 struct ast_channel *mychannel; 03288 03289 if ((!myrpt->remote) && (!myrpt->enable)) 03290 return DC_ERROR; 03291 03292 ast_debug(1, "@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf); 03293 03294 mychannel = myrpt->remchannel; 03295 03296 if (ast_strlen_zero(digitbuf)) /* needs 1 digit */ 03297 return DC_INDETERMINATE; 03298 03299 for (i = 0; i < digitbuf[i]; i++) { 03300 if ((digitbuf[i] < '0') || (digitbuf[i] > '9')) 03301 return DC_ERROR; 03302 } 03303 03304 if (*digitbuf == '0') 03305 val = myrpt->p.startupmacro; 03306 else 03307 val = ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf); 03308 /* param was 1 for local buf */ 03309 if (!val) { 03310 rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL); 03311 return DC_COMPLETE; 03312 } 03313 rpt_mutex_lock(&myrpt->lock); 03314 if ((sizeof(myrpt->macrobuf) - strlen(myrpt->macrobuf)) < strlen(val)) { 03315 rpt_mutex_unlock(&myrpt->lock); 03316 rpt_telemetry(myrpt, MACRO_BUSY, NULL); 03317 return DC_ERROR; 03318 } 03319 myrpt->macrotimer = MACROTIME; 03320 strncat(myrpt->macrobuf, val, sizeof(myrpt->macrobuf) - strlen(myrpt->macrobuf) - 1); 03321 rpt_mutex_unlock(&myrpt->lock); 03322 return DC_COMPLETE; 03323 }
static int function_remote | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 4632 of file app_rpt.c.
References AST_APP_ARG, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_indicate(), AST_NONSTANDARD_APP_ARGS, ast_safe_sleep(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_variable_retrieve(), rpt::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, rpt::memory, multimode_bump_freq(), multimode_capable(), myatoi(), rpt::name, rpt::offset, rpt::p, rpt::powerlevel, REM_HIPWR, REM_LOWPWR, REM_MEDPWR, REM_MINUS, REM_MODE_AM, REM_MODE_FM, REM_MODE_LSB, REM_MODE_USB, REM_PLUS, REM_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(), saydigits(), sayfile(), saynum(), rpt::scantimer, setrem(), SOURCE_LNK, SOURCE_RPT, split_freq, rpt::tunerequest, rpt::txchannel, rpt::txpl, and rpt::txplon.
04633 { 04634 char *s, *modestr; 04635 const char *val; 04636 int i, j, ht, k, l, ls2, res, offset, offsave, modesave, defmode = 0; 04637 char multimode = 0; 04638 char oc; 04639 char tmp[20], freq[20] = "", savestr[20] = ""; 04640 int mhz = 0, decimals = 0; 04641 struct ast_channel *mychannel; 04642 AST_DECLARE_APP_ARGS(args1, 04643 AST_APP_ARG(freq); 04644 AST_APP_ARG(xpl); 04645 AST_APP_ARG(mode); 04646 ); 04647 AST_DECLARE_APP_ARGS(args, 04648 AST_APP_ARG(s1); 04649 AST_APP_ARG(s2); 04650 ); 04651 04652 if ((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK)) 04653 return DC_ERROR; 04654 04655 multimode = multimode_capable(myrpt); 04656 mychannel = myrpt->remchannel; 04657 04658 switch (myatoi(param)) { 04659 case 1: /* retrieve memory */ 04660 if (strlen(digitbuf) < 2) /* needs 2 digits */ 04661 break; 04662 04663 for (i = 0 ; i < 2 ; i++) { 04664 if ((digitbuf[i] < '0') || (digitbuf[i] > '9')) 04665 return DC_ERROR; 04666 } 04667 04668 val = ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, digitbuf); 04669 if (!val) { 04670 if (ast_safe_sleep(mychannel, 1000) == -1) 04671 return DC_ERROR; 04672 sayfile(mychannel, "rpt/memory_notfound"); 04673 return DC_COMPLETE; 04674 } 04675 s = ast_strdupa(val); 04676 AST_STANDARD_APP_ARGS(args1, s); 04677 if (args1.argc < 3) 04678 return DC_ERROR; 04679 ast_copy_string(myrpt->freq, args1.freq, sizeof(myrpt->freq)); 04680 ast_copy_string(myrpt->rxpl, args1.xpl, sizeof(myrpt->rxpl)); 04681 ast_copy_string(myrpt->txpl, args1.xpl, sizeof(myrpt->rxpl)); 04682 myrpt->remmode = REM_MODE_FM; 04683 myrpt->offset = REM_SIMPLEX; 04684 myrpt->powerlevel = REM_MEDPWR; 04685 myrpt->txplon = myrpt->rxplon = 0; 04686 modestr = args1.mode; 04687 while (*modestr) { 04688 switch (*modestr++) { 04689 case 'A': 04690 case 'a': 04691 strcpy(myrpt->rxpl, "100.0"); 04692 strcpy(myrpt->txpl, "100.0"); 04693 myrpt->remmode = REM_MODE_AM; 04694 break; 04695 04696 case 'B': 04697 case 'b': 04698 strcpy(myrpt->rxpl, "100.0"); 04699 strcpy(myrpt->txpl, "100.0"); 04700 myrpt->remmode = REM_MODE_LSB; 04701 break; 04702 04703 case 'F': 04704 myrpt->remmode = REM_MODE_FM; 04705 break; 04706 04707 case 'L': 04708 case 'l': 04709 myrpt->powerlevel = REM_LOWPWR; 04710 break; 04711 case 'H': 04712 case 'h': 04713 myrpt->powerlevel = REM_HIPWR; 04714 break; 04715 04716 case 'M': 04717 case 'm': 04718 myrpt->powerlevel = REM_MEDPWR; 04719 break; 04720 04721 case '-': 04722 myrpt->offset = REM_MINUS; 04723 break; 04724 04725 case '+': 04726 myrpt->offset = REM_PLUS; 04727 break; 04728 04729 case 'S': 04730 case 's': 04731 myrpt->offset = REM_SIMPLEX; 04732 break; 04733 04734 case 'T': 04735 case 't': 04736 myrpt->txplon = 1; 04737 break; 04738 04739 case 'R': 04740 case 'r': 04741 myrpt->rxplon = 1; 04742 break; 04743 04744 case 'U': 04745 case 'u': 04746 strcpy(myrpt->rxpl, "100.0"); 04747 strcpy(myrpt->txpl, "100.0"); 04748 myrpt->remmode = REM_MODE_USB; 04749 break; 04750 } 04751 } 04752 04753 if (setrem(myrpt) == -1) 04754 return DC_ERROR; 04755 04756 return DC_COMPLETE; 04757 04758 case 2: /* set freq and offset */ 04759 for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for M+*K+*O or M+*H+* depending on mode */ 04760 if (digitbuf[i] == '*') { 04761 j++; 04762 continue; 04763 } 04764 if ((digitbuf[i] < '0') || (digitbuf[i] > '9')) 04765 goto invalid_freq; 04766 else { 04767 if (j == 0) 04768 l++; /* # of digits before first * */ 04769 if (j == 1) 04770 k++; /* # of digits after first * */ 04771 } 04772 } 04773 04774 i = strlen(digitbuf) - 1; 04775 if (multimode) { 04776 if ((j > 2) || (l > 3) || (k > 6)) 04777 goto invalid_freq; /* &^@#! */ 04778 } else { 04779 if ((j > 2) || (l > 4) || (k > 3)) 04780 goto invalid_freq; /* &^@#! */ 04781 } 04782 04783 /* Wait for M+*K+* */ 04784 04785 if (j < 2) 04786 break; /* Not yet */ 04787 04788 /* We have a frequency */ 04789 04790 s = ast_strdupa(digitbuf); 04791 AST_NONSTANDARD_APP_ARGS(args, s, '*'); 04792 ls2 = strlen(args.s2); 04793 04794 switch (ls2) { /* Allow partial entry of khz and hz digits for laziness support */ 04795 case 1: 04796 ht = 0; 04797 k = 100 * atoi(args.s2); 04798 break; 04799 case 2: 04800 ht = 0; 04801 k = 10 * atoi(args.s2); 04802 break; 04803 case 3: 04804 if (!multimode) { 04805 if ((args.s2[2] != '0') && (args.s2[2] != '5')) 04806 goto invalid_freq; 04807 } 04808 ht = 0; 04809 k = atoi(args.s2); 04810 break; 04811 case 4: 04812 k = atoi(args.s2) / 10; 04813 ht = 10 * (atoi(args.s2 + (ls2 - 1))); 04814 break; 04815 case 5: 04816 k = atoi(args.s2) / 100; 04817 ht = (atoi(args.s2 + (ls2 - 2))); 04818 break; 04819 default: 04820 goto invalid_freq; 04821 } 04822 04823 /* Check frequency for validity and establish a default mode */ 04824 04825 snprintf(freq, sizeof(freq), "%s.%03d%02d", args.s1, k, ht); 04826 ast_debug(1, "New frequency: %s\n", freq); 04827 04828 split_freq(&mhz, &decimals, freq); 04829 04830 if (check_freq(myrpt, mhz, decimals, &defmode)) /* Check to see if frequency entered is legit */ 04831 goto invalid_freq; 04832 04833 if ((defmode == REM_MODE_FM) && (digitbuf[i] == '*')) /* If FM, user must enter and additional offset digit */ 04834 break; /* Not yet */ 04835 04836 offset = REM_SIMPLEX; /* Assume simplex */ 04837 04838 if (defmode == REM_MODE_FM) { 04839 oc = *s; /* Pick off offset */ 04840 if (oc) { 04841 switch (oc) { 04842 case '1': 04843 offset = REM_MINUS; 04844 break; 04845 case '2': 04846 offset = REM_SIMPLEX; 04847 break; 04848 case '3': 04849 offset = REM_PLUS; 04850 break; 04851 default: 04852 goto invalid_freq; 04853 } 04854 } 04855 } 04856 offsave = myrpt->offset; 04857 modesave = myrpt->remmode; 04858 ast_copy_string(savestr, myrpt->freq, sizeof(savestr)); 04859 ast_copy_string(myrpt->freq, freq, sizeof(myrpt->freq)); 04860 myrpt->offset = offset; 04861 myrpt->remmode = defmode; 04862 04863 if (setrem(myrpt) == -1) { 04864 myrpt->offset = offsave; 04865 myrpt->remmode = modesave; 04866 ast_copy_string(myrpt->freq, savestr, sizeof(myrpt->freq)); 04867 goto invalid_freq; 04868 } 04869 04870 return DC_COMPLETE; 04871 04872 invalid_freq: 04873 rmt_sayfile(myrpt, mychannel, 1000, "rpt/invalid-freq"); 04874 04875 return DC_ERROR; 04876 04877 case 3: /* set rx PL tone */ 04878 04879 for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for N+*N */ 04880 if (digitbuf[i] == '*') { 04881 j++; 04882 continue; 04883 } 04884 if ((digitbuf[i] < '0') || (digitbuf[i] > '9')) 04885 return DC_ERROR; 04886 else { 04887 if (j) 04888 l++; 04889 else 04890 k++; 04891 } 04892 } 04893 if ((j > 1) || (k > 3) || (l > 1)) 04894 return DC_ERROR; /* &$@^! */ 04895 i = strlen(digitbuf) - 1; 04896 if ((j != 1) || (k < 2)|| (l != 1)) 04897 break; /* Not yet */ 04898 ast_debug(1, "PL digits entered %s\n", digitbuf); 04899 04900 ast_copy_string(tmp, digitbuf, sizeof(tmp)); 04901 /* see if we have at least 1 */ 04902 s = strchr(tmp, '*'); 04903 if (s) 04904 *s = '.'; 04905 ast_copy_string(savestr, myrpt->rxpl, sizeof(savestr)); 04906 ast_copy_string(myrpt->rxpl, tmp, sizeof(myrpt->rxpl)); 04907 04908 if (setrem(myrpt) == -1) { 04909 ast_copy_string(myrpt->rxpl, savestr, sizeof(myrpt->rxpl)); 04910 return DC_ERROR; 04911 } 04912 04913 return DC_COMPLETE; 04914 case 4: /* set tx PL tone */ 04915 for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for N+*N */ 04916 if (digitbuf[i] == '*') { 04917 j++; 04918 continue; 04919 } 04920 if ((digitbuf[i] < '0') || (digitbuf[i] > '9')) 04921 return DC_ERROR; 04922 else { 04923 if (j) 04924 l++; 04925 else 04926 k++; 04927 } 04928 } 04929 if ((j > 1) || (k > 3) || (l > 1)) 04930 return DC_ERROR; /* &$@^! */ 04931 i = strlen(digitbuf) - 1; 04932 if ((j != 1) || (k < 2)|| (l != 1)) 04933 break; /* Not yet */ 04934 ast_debug(1, "PL digits entered %s\n", digitbuf); 04935 04936 ast_copy_string(tmp, digitbuf, sizeof(tmp)); 04937 /* see if we have at least 1 */ 04938 s = strchr(tmp, '*'); 04939 if (s) 04940 *s = '.'; 04941 ast_copy_string(savestr, myrpt->txpl, sizeof(savestr)); 04942 ast_copy_string(myrpt->txpl, tmp, sizeof(myrpt->txpl)); 04943 04944 if (setrem(myrpt) == -1) { 04945 ast_copy_string(myrpt->txpl, savestr, sizeof(myrpt->txpl)); 04946 return DC_ERROR; 04947 } 04948 04949 return DC_COMPLETE; 04950 04951 case 6: /* MODE (FM,USB,LSB,AM) */ 04952 if (strlen(digitbuf) < 1) 04953 break; 04954 04955 if (!multimode) 04956 return DC_ERROR; /* Multimode radios only */ 04957 04958 switch (*digitbuf) { 04959 case '1': 04960 split_freq(&mhz, &decimals, myrpt->freq); 04961 if (mhz < 29) /* No FM allowed below 29MHz! */ 04962 return DC_ERROR; 04963 myrpt->remmode = REM_MODE_FM; 04964 res = rmt_saycharstr(myrpt, mychannel, 1000, "FM"); 04965 break; 04966 04967 case '2': 04968 myrpt->remmode = REM_MODE_USB; 04969 res = rmt_saycharstr(myrpt, mychannel, 1000, "USB"); 04970 break; 04971 04972 case '3': 04973 myrpt->remmode = REM_MODE_LSB; 04974 res = rmt_saycharstr(myrpt, mychannel, 1000, "LSB"); 04975 break; 04976 04977 case '4': 04978 myrpt->remmode = REM_MODE_AM; 04979 res = rmt_saycharstr(myrpt, mychannel, 1000, "AM"); 04980 break; 04981 04982 default: 04983 return DC_ERROR; 04984 } 04985 if (res) 04986 return DC_ERROR; 04987 04988 if (setrem(myrpt)) 04989 return DC_ERROR; 04990 return DC_COMPLETE; 04991 04992 case 100: /* other stuff */ 04993 case 101: 04994 case 102: 04995 case 103: 04996 case 104: 04997 case 105: 04998 case 106: 04999 res = rmt_telem_start(myrpt, mychannel, 1000); 05000 switch (myatoi(param)) { /* Quick commands requiring a setrem call */ 05001 case 100: /* RX PL Off */ 05002 myrpt->rxplon = 0; 05003 if (!res) 05004 res = sayfile(mychannel, "rpt/rxpl"); 05005 if (!res) 05006 sayfile(mychannel, "rpt/off"); 05007 break; 05008 05009 case 101: /* RX PL On */ 05010 myrpt->rxplon = 1; 05011 if (!res) 05012 res = sayfile(mychannel, "rpt/rxpl"); 05013 if (!res) 05014 sayfile(mychannel, "rpt/on"); 05015 break; 05016 05017 case 102: /* TX PL Off */ 05018 myrpt->txplon = 0; 05019 if (!res) 05020 res = sayfile(mychannel, "rpt/txpl"); 05021 if (!res) 05022 sayfile(mychannel, "rpt/off"); 05023 break; 05024 05025 case 103: /* TX PL On */ 05026 myrpt->txplon = 1; 05027 if (!res) 05028 res = sayfile(mychannel, "rpt/txpl"); 05029 if (!res) 05030 sayfile(mychannel, "rpt/on"); 05031 break; 05032 05033 case 104: /* Low Power */ 05034 myrpt->powerlevel = REM_LOWPWR; 05035 if (!res) 05036 res = sayfile(mychannel, "rpt/lopwr"); 05037 break; 05038 05039 case 105: /* Medium Power */ 05040 myrpt->powerlevel = REM_MEDPWR; 05041 if (!res) 05042 res = sayfile(mychannel, "rpt/medpwr"); 05043 break; 05044 05045 case 106: /* Hi Power */ 05046 myrpt->powerlevel = REM_HIPWR; 05047 if (!res) 05048 res = sayfile(mychannel, "rpt/hipwr"); 05049 break; 05050 05051 default: 05052 if (!res) 05053 rmt_telem_finish(myrpt, mychannel); 05054 return DC_ERROR; 05055 } 05056 if (!res) 05057 res = rmt_telem_finish(myrpt, mychannel); 05058 if (res) 05059 return DC_ERROR; 05060 05061 if (setrem(myrpt) == -1) 05062 return DC_ERROR; 05063 return DC_COMPLETE; 05064 05065 case 107: /* Bump down 20Hz */ 05066 multimode_bump_freq(myrpt, -20); 05067 return DC_COMPLETE; 05068 05069 case 108: /* Bump down 100Hz */ 05070 multimode_bump_freq(myrpt, -100); 05071 return DC_COMPLETE; 05072 05073 case 109: /* Bump down 500Hz */ 05074 multimode_bump_freq(myrpt, -500); 05075 return DC_COMPLETE; 05076 05077 case 110: /* Bump up 20Hz */ 05078 multimode_bump_freq(myrpt, 20); 05079 return DC_COMPLETE; 05080 05081 case 111: /* Bump up 100Hz */ 05082 multimode_bump_freq(myrpt, 100); 05083 return DC_COMPLETE; 05084 05085 case 112: /* Bump up 500Hz */ 05086 multimode_bump_freq(myrpt, 500); 05087 return DC_COMPLETE; 05088 05089 case 113: 05090 case 114: 05091 case 115: 05092 case 116: 05093 case 117: 05094 case 118: 05095 myrpt->remotetx = 0; 05096 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY); 05097 if (!myrpt->remoterx) 05098 ast_indicate(mychannel, AST_CONTROL_RADIO_KEY); 05099 if (ast_safe_sleep(mychannel, 1000) == -1) 05100 return DC_ERROR; 05101 05102 switch (myatoi(param)) { 05103 case 113: /* Scan down slow */ 05104 res = sayfile(mychannel, "rpt/down"); 05105 if (!res) 05106 res = sayfile(mychannel, "rpt/slow"); 05107 if (!res) { 05108 myrpt->scantimer = REM_SCANTIME; 05109 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW; 05110 } 05111 break; 05112 05113 case 114: /* Scan down quick */ 05114 res = sayfile(mychannel, "rpt/down"); 05115 if (!res) 05116 res = sayfile(mychannel, "rpt/quick"); 05117 if (!res) { 05118 myrpt->scantimer = REM_SCANTIME; 05119 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK; 05120 } 05121 break; 05122 05123 case 115: /* Scan down fast */ 05124 res = sayfile(mychannel, "rpt/down"); 05125 if (!res) 05126 res = sayfile(mychannel, "rpt/fast"); 05127 if (!res) { 05128 myrpt->scantimer = REM_SCANTIME; 05129 myrpt->hfscanmode = HF_SCAN_DOWN_FAST; 05130 } 05131 break; 05132 05133 case 116: /* Scan up slow */ 05134 res = sayfile(mychannel, "rpt/up"); 05135 if (!res) 05136 res = sayfile(mychannel, "rpt/slow"); 05137 if (!res) { 05138 myrpt->scantimer = REM_SCANTIME; 05139 myrpt->hfscanmode = HF_SCAN_UP_SLOW; 05140 } 05141 break; 05142 05143 case 117: /* Scan up quick */ 05144 res = sayfile(mychannel, "rpt/up"); 05145 if (!res) 05146 res = sayfile(mychannel, "rpt/quick"); 05147 if (!res) { 05148 myrpt->scantimer = REM_SCANTIME; 05149 myrpt->hfscanmode = HF_SCAN_UP_QUICK; 05150 } 05151 break; 05152 05153 case 118: /* Scan up fast */ 05154 res = sayfile(mychannel, "rpt/up"); 05155 if (!res) 05156 res = sayfile(mychannel, "rpt/fast"); 05157 if (!res) { 05158 myrpt->scantimer = REM_SCANTIME; 05159 myrpt->hfscanmode = HF_SCAN_UP_FAST; 05160 } 05161 break; 05162 } 05163 rmt_telem_finish(myrpt, mychannel); 05164 return DC_COMPLETE; 05165 05166 05167 case 119: /* Tune Request */ 05168 myrpt->tunerequest = 1; 05169 return DC_COMPLETE; 05170 05171 case 5: /* Long Status */ 05172 case 140: /* Short Status */ 05173 res = rmt_telem_start(myrpt, mychannel, 1000); 05174 05175 res = sayfile(mychannel, "rpt/node"); 05176 if (!res) 05177 res = saycharstr(mychannel, myrpt->name); 05178 if (!res) 05179 res = sayfile(mychannel, "rpt/frequency"); 05180 if (!res) 05181 res = split_freq(&mhz, &decimals, myrpt->freq); 05182 if (!res) { 05183 if (mhz < 100) 05184 res = saynum(mychannel, mhz); 05185 else 05186 res = saydigits(mychannel, mhz); 05187 } 05188 if (!res) 05189 res = sayfile(mychannel, "letters/dot"); 05190 if (!res) 05191 res = saydigits(mychannel, decimals); 05192 05193 if (res) { 05194 rmt_telem_finish(myrpt, mychannel); 05195 return DC_ERROR; 05196 } 05197 if (myrpt->remmode == REM_MODE_FM) { /* Mode FM? */ 05198 switch (myrpt->offset) { 05199 case REM_MINUS: 05200 res = sayfile(mychannel, "rpt/minus"); 05201 break; 05202 05203 case REM_SIMPLEX: 05204 res = sayfile(mychannel, "rpt/simplex"); 05205 break; 05206 05207 case REM_PLUS: 05208 res = sayfile(mychannel, "rpt/plus"); 05209 break; 05210 05211 default: 05212 return DC_ERROR; 05213 05214 } 05215 } else { /* Must be USB, LSB, or AM */ 05216 switch (myrpt->remmode) { 05217 case REM_MODE_USB: 05218 res = saycharstr(mychannel, "USB"); 05219 break; 05220 case REM_MODE_LSB: 05221 res = saycharstr(mychannel, "LSB"); 05222 break; 05223 case REM_MODE_AM: 05224 res = saycharstr(mychannel, "AM"); 05225 break; 05226 default: 05227 return DC_ERROR; 05228 } 05229 } 05230 05231 if (res == -1) { 05232 rmt_telem_finish(myrpt, mychannel); 05233 return DC_ERROR; 05234 } 05235 05236 if (myatoi(param) == 140) { /* Short status? */ 05237 if (!res) 05238 res = rmt_telem_finish(myrpt, mychannel); 05239 if (res) 05240 return DC_ERROR; 05241 return DC_COMPLETE; 05242 } 05243 05244 switch (myrpt->powerlevel) { 05245 case REM_LOWPWR: 05246 res = sayfile(mychannel, "rpt/lopwr") ; 05247 break; 05248 case REM_MEDPWR: 05249 res = sayfile(mychannel, "rpt/medpwr"); 05250 break; 05251 case REM_HIPWR: 05252 res = sayfile(mychannel, "rpt/hipwr"); 05253 break; 05254 } 05255 if (res || (sayfile(mychannel, "rpt/rxpl") == -1) || 05256 (sayfile(mychannel, "rpt/frequency") == -1) || 05257 (saycharstr(mychannel, myrpt->rxpl) == -1) || 05258 (sayfile(mychannel, "rpt/txpl") == -1) || 05259 (sayfile(mychannel, "rpt/frequency") == -1) || 05260 (saycharstr(mychannel, myrpt->txpl) == -1) || 05261 (sayfile(mychannel, "rpt/txpl") == -1) || 05262 (sayfile(mychannel, ((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1) || 05263 (sayfile(mychannel, "rpt/rxpl") == -1) || 05264 (sayfile(mychannel, ((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1)) 05265 { 05266 rmt_telem_finish(myrpt, mychannel); 05267 return DC_ERROR; 05268 } 05269 if (!res) 05270 res = rmt_telem_finish(myrpt, mychannel); 05271 if (res) 05272 return DC_ERROR; 05273 05274 return DC_COMPLETE; 05275 default: 05276 return DC_ERROR; 05277 } 05278 05279 return DC_INDETERMINATE; 05280 }
static int function_status | ( | struct rpt * | myrpt, | |
char * | param, | |||
char * | digitbuf, | |||
int | command_source, | |||
struct rpt_link * | mylink | |||
) | [static] |
Definition at line 3250 of file app_rpt.c.
References ast_debug, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, rpt::enable, ID1, myatoi(), rpt_telemetry(), STATS_TIME, and STATS_VERSION.
03251 { 03252 03253 if (!param) 03254 return DC_ERROR; 03255 03256 if (!myrpt->enable) 03257 return DC_ERROR; 03258 03259 ast_debug(1, "@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf); 03260 03261 switch (myatoi(param)) { 03262 case 1: /* System ID */ 03263 rpt_telemetry(myrpt, ID1, NULL); 03264 return DC_COMPLETE; 03265 case 2: /* System Time */ 03266 rpt_telemetry(myrpt, STATS_TIME, NULL); 03267 return DC_COMPLETE; 03268 case 3: /* app_rpt.c version */ 03269 rpt_telemetry(myrpt, STATS_VERSION, NULL); 03270 default: 03271 return DC_ERROR; 03272 } 03273 03274 /* Never reached */ 03275 return DC_INDETERMINATE; 03276 }
static int get_wait_interval | ( | struct rpt * | myrpt, | |
int | type | |||
) | [static] |
Definition at line 1843 of file app_rpt.c.
References ast_variable_retrieve(), rpt::cfg, DLY_CALLTERM, DLY_ID, DLY_TELEM, DLY_UNKEY, rpt::name, and retrieve_astcfgint().
Referenced by rpt_tele_thread(), and wait_interval().
01844 { 01845 int interval = 1000; 01846 const char *wait_times = ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times"); 01847 01848 switch (type) { 01849 case DLY_TELEM: 01850 if (wait_times) 01851 interval = retrieve_astcfgint(myrpt, wait_times, "telemwait", 500, 5000, 1000); 01852 break; 01853 case DLY_ID: 01854 if (wait_times) 01855 interval = retrieve_astcfgint(myrpt, wait_times, "idwait", 250, 5000, 500); 01856 else 01857 interval = 500; 01858 break; 01859 case DLY_UNKEY: 01860 if (wait_times) 01861 interval = retrieve_astcfgint(myrpt, wait_times, "unkeywait", 500, 5000, 1000); 01862 break; 01863 case DLY_CALLTERM: 01864 if (wait_times) 01865 interval = retrieve_astcfgint(myrpt, wait_times, "calltermwait", 500, 5000, 1500); 01866 break; 01867 default: 01868 return 0; 01869 } 01870 return interval; 01871 }
static char * handle_cli_rpt_debug_level | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1075 of file app_rpt.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, myatoi(), and ast_cli_entry::usage.
01076 { 01077 int newlevel; 01078 01079 switch (cmd) { 01080 case CLI_INIT: 01081 e->command = "rpt debug level"; 01082 e->usage = 01083 "Usage: rpt debug level {0-7}\n" 01084 " Enables debug messages in app_rpt\n"; 01085 return NULL; 01086 case CLI_GENERATE: 01087 return NULL; 01088 } 01089 if (a->argc != e->args) 01090 return CLI_SHOWUSAGE; 01091 newlevel = myatoi(a->argv[3]); 01092 if ((newlevel < 0) || (newlevel > 7)) 01093 return CLI_SHOWUSAGE; 01094 if (newlevel) 01095 ast_cli(a->fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel); 01096 else 01097 ast_cli(a->fd, "app_rpt Debugging disabled\n"); 01098 01099 debug = newlevel; 01100 01101 return CLI_SUCCESS; 01102 }
static char * handle_cli_rpt_dump | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1107 of file app_rpt.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, rpt::disgorgetime, ast_cli_args::fd, rpt::name, rpt_vars, and ast_cli_entry::usage.
01108 { 01109 int i; 01110 01111 switch (cmd) { 01112 case CLI_INIT: 01113 e->command = "rpt dump"; 01114 e->usage = 01115 "Usage: rpt dump <nodename>\n" 01116 " Dumps struct debug info to log\n"; 01117 return NULL; 01118 case CLI_GENERATE: 01119 return NULL; 01120 } 01121 01122 if (a->argc != 3) 01123 return CLI_SHOWUSAGE; 01124 01125 for (i = 0; i < nrpts; i++) { 01126 if (!strcmp(a->argv[2], rpt_vars[i].name)) { 01127 rpt_vars[i].disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */ 01128 ast_cli(a->fd, "app_rpt struct dump requested for node %s\n", a->argv[2]); 01129 return CLI_SUCCESS; 01130 } 01131 } 01132 return CLI_FAILURE; 01133 }
static char * handle_cli_rpt_lstats | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1327 of file app_rpt.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_calloc, ast_copy_string(), ast_log(), rpt_link::chan, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, rpt_link::connecttime, rpt::links, rpt::lock, LOG_ERROR, MAXPEERSTR, MAXREMSTR, rpt_link::mode, rpt_link::name, rpt::name, rpt_link::next, rpt_lstat::next, rpt_link::outbound, pbx_substitute_variables_helper(), rpt_lstat::prev, rpt_link::reconnects, rpt_mutex_lock, rpt_mutex_unlock, rpt_vars, s, and ast_cli_entry::usage.
01328 { 01329 int i, j; 01330 struct rpt *myrpt; 01331 struct rpt_link *l; 01332 struct rpt_lstat *s, *t; 01333 struct rpt_lstat s_head; 01334 01335 switch (cmd) { 01336 case CLI_INIT: 01337 e->command = "rpt lstats"; 01338 e->usage = 01339 "Usage: rpt lstats <nodename>\n" 01340 " Dumps link statistics to console\n"; 01341 return NULL; 01342 case CLI_GENERATE: 01343 return NULL; 01344 } 01345 01346 if (a->argc != 3) 01347 return CLI_SHOWUSAGE; 01348 01349 s = NULL; 01350 s_head.next = &s_head; 01351 s_head.prev = &s_head; 01352 01353 for (i = 0; i < nrpts; i++) { 01354 if (!strcmp(a->argv[2], rpt_vars[i].name)) { 01355 /* Make a copy of all stat variables while locked */ 01356 myrpt = &rpt_vars[i]; 01357 rpt_mutex_lock(&myrpt->lock); /* LOCK */ 01358 /* Traverse the list of connected nodes */ 01359 j = 0; 01360 l = myrpt->links.next; 01361 while (l != &myrpt->links) { 01362 if (l->name[0] == '0') { /* Skip '0' nodes */ 01363 l = l->next; 01364 continue; 01365 } 01366 if ((s = ast_calloc(1, sizeof(*s))) == NULL) { 01367 ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n"); 01368 rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */ 01369 return CLI_FAILURE; 01370 } 01371 ast_copy_string(s->name, l->name, MAXREMSTR); 01372 pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1); 01373 s->mode = l->mode; 01374 s->outbound = l->outbound; 01375 s->reconnects = l->reconnects; 01376 s->connecttime = l->connecttime; 01377 insque((struct qelem *) s, (struct qelem *) s_head.next); 01378 l = l->next; 01379 } 01380 rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */ 01381 ast_cli(a->fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME\n"); 01382 ast_cli(a->fd, "---- ---- ---------- --------- ------------\n"); 01383 01384 for (s = s_head.next; s != &s_head; s = s->next) { 01385 int hours, minutes, seconds; 01386 long long connecttime = s->connecttime; 01387 char conntime[31]; 01388 hours = (int) connecttime/3600000; 01389 connecttime %= 3600000; 01390 minutes = (int) connecttime/60000; 01391 connecttime %= 60000; 01392 seconds = (int) connecttime/1000; 01393 connecttime %= 1000; 01394 snprintf(conntime, sizeof(conntime), "%02d:%02d:%02d.%d", 01395 hours, minutes, seconds, (int) connecttime); 01396 ast_cli(a->fd, "%-10s%-20s%-12d%-11s%-30s\n", 01397 s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime); 01398 } 01399 /* destroy our local link queue */ 01400 s = s_head.next; 01401 while (s != &s_head) { 01402 t = s; 01403 s = s->next; 01404 remque((struct qelem *)t); 01405 ast_free(t); 01406 } 01407 return CLI_SUCCESS; 01408 } 01409 } 01410 01411 return CLI_FAILURE; 01412 }
static char * handle_cli_rpt_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1417 of file app_rpt.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, reload, rpt_vars, and ast_cli_entry::usage.
01418 { 01419 int n; 01420 01421 switch (cmd) { 01422 case CLI_INIT: 01423 e->command = "rpt reload"; 01424 e->usage = 01425 "Usage: rpt reload\n" 01426 " Reloads app_rpt running config parameters\n"; 01427 return NULL; 01428 case CLI_GENERATE: 01429 return NULL; 01430 } 01431 01432 if (a->argc > 2) 01433 return CLI_SHOWUSAGE; 01434 01435 for (n = 0; n < nrpts; n++) 01436 rpt_vars[n].reload = 1; 01437 01438 return CLI_SUCCESS; 01439 }
static char * handle_cli_rpt_restart | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1444 of file app_rpt.c.
References ast_cli_args::argc, ast_softhangup(), AST_SOFTHANGUP_DEV, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, rpt_vars, and ast_cli_entry::usage.
01445 { 01446 int i; 01447 01448 switch (cmd) { 01449 case CLI_INIT: 01450 e->command = "rpt restart"; 01451 e->usage = 01452 "Usage: rpt restart\n" 01453 " Restarts app_rpt\n"; 01454 return NULL; 01455 case CLI_GENERATE: 01456 return NULL; 01457 } 01458 01459 if (a->argc > 2) 01460 return CLI_SHOWUSAGE; 01461 for (i = 0; i < nrpts; i++) { 01462 if (rpt_vars[i].rxchannel) 01463 ast_softhangup(rpt_vars[i].rxchannel, AST_SOFTHANGUP_DEV); 01464 } 01465 return CLI_SUCCESS; 01466 }
static char * handle_cli_rpt_stats | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1138 of file app_rpt.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_strdupa, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, rpt::dailyexecdcommands, rpt::dailykerchunks, rpt::dailykeyups, rpt::dailytxtime, rpt::links, rpt::lock, MAX_STAT_LINKS, rpt_link::name, rpt::name, rpt_link::next, rpt_mutex_lock, rpt_vars, rpt::timeouts, rpt::totalexecdcommands, rpt::totalkerchunks, rpt::totalkeyups, rpt::totaltxtime, and ast_cli_entry::usage.
01139 { 01140 int i, j; 01141 int dailytxtime, dailykerchunks; 01142 int totalkerchunks, dailykeyups, totalkeyups, timeouts; 01143 int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds; 01144 long long totaltxtime; 01145 struct rpt_link *l; 01146 char *listoflinks[MAX_STAT_LINKS]; 01147 char *lastnodewhichkeyedusup, *lastdtmfcommand; 01148 char *tot_state, *ider_state, *patch_state; 01149 char *reverse_patch_state, *enable_state, *input_signal, *called_number; 01150 struct rpt *myrpt; 01151 01152 static char *not_applicable = "N/A"; 01153 01154 switch (cmd) { 01155 case CLI_INIT: 01156 e->command = "rpt stats"; 01157 e->usage = 01158 "Usage: rpt stats <nodename>\n" 01159 " Dumps node statistics to console\n"; 01160 return NULL; 01161 case CLI_GENERATE: 01162 return NULL; 01163 } 01164 01165 if (a->argc != 3) 01166 return CLI_SHOWUSAGE; 01167 01168 for (i = 0 ; i <= MAX_STAT_LINKS; i++) 01169 listoflinks[i] = NULL; 01170 01171 tot_state = ider_state = 01172 patch_state = reverse_patch_state = 01173 input_signal = called_number = 01174 lastdtmfcommand = not_applicable; 01175 01176 for (i = 0; i < nrpts; i++) { 01177 if (!strcmp(a->argv[2], rpt_vars[i].name)) { 01178 /* Make a copy of all stat variables while locked */ 01179 myrpt = &rpt_vars[i]; 01180 rpt_mutex_lock(&myrpt->lock); /* LOCK */ 01181 01182 dailytxtime = myrpt->dailytxtime; 01183 totaltxtime = myrpt->totaltxtime; 01184 dailykeyups = myrpt->dailykeyups; 01185 totalkeyups = myrpt->totalkeyups; 01186 dailykerchunks = myrpt->dailykerchunks; 01187 totalkerchunks = myrpt->totalkerchunks; 01188 dailyexecdcommands = myrpt->dailyexecdcommands; 01189 totalexecdcommands = myrpt->totalexecdcommands; 01190 timeouts = myrpt->timeouts; 01191 01192 /* Traverse the list of connected nodes */ 01193 reverse_patch_state = "DOWN"; 01194 j = 0; 01195 l = myrpt->links.next; 01196 while (l != &myrpt->links) { 01197 if (l->name[0] == '0') { /* Skip '0' nodes */ 01198 reverse_patch_state = "UP"; 01199 l = l->next; 01200 continue; 01201 } 01202 listoflinks[j] = ast_strdupa(l->name); 01203 if (listoflinks[j]) 01204 j++; 01205 l = l->next; 01206 } 01207 01208 lastnodewhichkeyedusup = ast_strdupa(myrpt->lastnodewhichkeyedusup); 01209 if ((!lastnodewhichkeyedusup) || (ast_strlen_zero(lastnodewhichkeyedusup))) 01210 lastnodewhichkeyedusup = not_applicable; 01211 01212 if (myrpt->keyed) 01213 input_signal = "YES"; 01214 else 01215 input_signal = "NO"; 01216 01217 if (myrpt->enable) 01218 enable_state = "YES"; 01219 else 01220 enable_state = "NO"; 01221 01222 if (!myrpt->totimer) 01223 tot_state = "TIMED OUT!"; 01224 else if (myrpt->totimer != myrpt->p.totime) 01225 tot_state = "ARMED"; 01226 else 01227 tot_state = "RESET"; 01228 01229 if (myrpt->tailid) 01230 ider_state = "QUEUED IN TAIL"; 01231 else if (myrpt->mustid) 01232 ider_state = "QUEUED FOR CLEANUP"; 01233 else 01234 ider_state = "CLEAN"; 01235 01236 switch (myrpt->callmode) { 01237 case 1: 01238 patch_state = "DIALING"; 01239 break; 01240 case 2: 01241 patch_state = "CONNECTING"; 01242 break; 01243 case 3: 01244 patch_state = "UP"; 01245 break; 01246 case 4: 01247 patch_state = "CALL FAILED"; 01248 break; 01249 default: 01250 patch_state = "DOWN"; 01251 } 01252 01253 if (!ast_strlen_zero(myrpt->exten)) 01254 called_number = ast_strdupa(myrpt->exten); 01255 01256 if (!ast_strlen_zero(myrpt->lastdtmfcommand)) 01257 lastdtmfcommand = ast_strdupa(myrpt->lastdtmfcommand); 01258 01259 rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */ 01260 01261 ast_cli(a->fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name); 01262 ast_cli(a->fd, "Signal on input..................................: %s\n", input_signal); 01263 ast_cli(a->fd, "Transmitter enabled..............................: %s\n", enable_state); 01264 ast_cli(a->fd, "Time out timer state.............................: %s\n", tot_state); 01265 ast_cli(a->fd, "Time outs since system initialization............: %d\n", timeouts); 01266 ast_cli(a->fd, "Identifier state.................................: %s\n", ider_state); 01267 ast_cli(a->fd, "Kerchunks today..................................: %d\n", dailykerchunks); 01268 ast_cli(a->fd, "Kerchunks since system initialization............: %d\n", totalkerchunks); 01269 ast_cli(a->fd, "Keyups today.....................................: %d\n", dailykeyups); 01270 ast_cli(a->fd, "Keyups since system initialization...............: %d\n", totalkeyups); 01271 ast_cli(a->fd, "DTMF commands today..............................: %d\n", dailyexecdcommands); 01272 ast_cli(a->fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands); 01273 ast_cli(a->fd, "Last DTMF command executed.......................: %s\n", lastdtmfcommand); 01274 01275 hours = dailytxtime / 3600000; 01276 dailytxtime %= 3600000; 01277 minutes = dailytxtime / 60000; 01278 dailytxtime %= 60000; 01279 seconds = dailytxtime / 1000; 01280 dailytxtime %= 1000; 01281 01282 ast_cli(a->fd, "TX time today ...................................: %02d:%02d:%02d.%d\n", 01283 hours, minutes, seconds, dailytxtime); 01284 01285 hours = (int) totaltxtime / 3600000; 01286 totaltxtime %= 3600000; 01287 minutes = (int) totaltxtime / 60000; 01288 totaltxtime %= 60000; 01289 seconds = (int) totaltxtime / 1000; 01290 totaltxtime %= 1000; 01291 01292 ast_cli(a->fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n", 01293 hours, minutes, seconds, (int) totaltxtime); 01294 ast_cli(a->fd, "Nodes currently connected to us..................: "); 01295 for (j = 0;; j++) { 01296 if (!listoflinks[j]) { 01297 if (!j) { 01298 ast_cli(a->fd, "<NONE>"); 01299 } 01300 break; 01301 } 01302 ast_cli(a->fd, "%s", listoflinks[j]); 01303 if (j % 4 == 3) { 01304 ast_cli(a->fd, "\n"); 01305 ast_cli(a->fd, " : "); 01306 } else { 01307 if (listoflinks[j + 1]) 01308 ast_cli(a->fd, ", "); 01309 } 01310 } 01311 ast_cli(a->fd, "\n"); 01312 01313 ast_cli(a->fd, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup); 01314 ast_cli(a->fd, "Autopatch state..................................: %s\n", patch_state); 01315 ast_cli(a->fd, "Autopatch called number..........................: %s\n", called_number); 01316 ast_cli(a->fd, "Reverse patch/IAXRPT connected...................: %s\n\n", reverse_patch_state); 01317 01318 return CLI_SUCCESS; 01319 } 01320 } 01321 return CLI_FAILURE; 01322 }
Definition at line 3483 of file app_rpt.c.
References ast_canmatch_extension(), ast_copy_string(), ast_exists_extension(), AST_FRAME_TEXT, ast_log(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_strdup, ast_write(), rpt::callmode, rpt_link::chan, rpt::cidx, collect_function_digits(), rpt::dailyexecdcommands, 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::lastdtmfcommand, 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::p, rpt::patchcontext, rpt::patchquiet, rpt::pchannel, PROC, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, rpt_link::retries, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), ast_frame::samples, seq, SOURCE_LNK, rpt::stopgen, ast_frame::subclass, and rpt::totalexecdcommands.
Referenced by rpt().
03484 { 03485 char cmd[300] = "", dest[300], src[300], c; 03486 int seq, res; 03487 struct rpt_link *l; 03488 struct ast_frame wf; 03489 03490 wf.frametype = AST_FRAME_TEXT; 03491 wf.subclass = 0; 03492 wf.offset = 0; 03493 wf.mallocd = 1; 03494 wf.datalen = strlen(str) + 1; 03495 wf.samples = 0; 03496 if (!strcmp(str, discstr)) { 03497 mylink->disced = 1; 03498 mylink->retries = MAX_RETRIES + 1; 03499 ast_softhangup(mylink->chan, AST_SOFTHANGUP_DEV); 03500 return; 03501 } 03502 if (sscanf(str, "%s %s %s %d %c", cmd, dest, src, &seq, &c) != 5) { 03503 ast_log(LOG_WARNING, "Unable to parse link string %s\n", str); 03504 return; 03505 } 03506 if (strcmp(cmd, "D")) { 03507 ast_log(LOG_WARNING, "Unable to parse link string %s\n", str); 03508 return; 03509 } 03510 03511 if (dest[0] == '0') { 03512 strcpy(dest, myrpt->name); 03513 } 03514 03515 /* if not for me, redistribute to all links */ 03516 if (strcmp(dest, myrpt->name)) { 03517 l = myrpt->links.next; 03518 /* see if this is one in list */ 03519 while (l != &myrpt->links) { 03520 if (l->name[0] == '0') { 03521 l = l->next; 03522 continue; 03523 } 03524 /* dont send back from where it came */ 03525 if ((l == mylink) || (!strcmp(l->name, mylink->name))) { 03526 l = l->next; 03527 continue; 03528 } 03529 /* if it is, send it and we're done */ 03530 if (!strcmp(l->name, dest)) { 03531 /* send, but not to src */ 03532 if (strcmp(l->name, src)) { 03533 wf.data = ast_strdup(str); 03534 if (l->chan) 03535 ast_write(l->chan, &wf); 03536 } 03537 return; 03538 } 03539 l = l->next; 03540 } 03541 l = myrpt->links.next; 03542 /* otherwise, send it to all of em */ 03543 while (l != &myrpt->links) { 03544 if (l->name[0] == '0') { 03545 l = l->next; 03546 continue; 03547 } 03548 /* dont send back from where it came */ 03549 if ((l == mylink) || (!strcmp(l->name, mylink->name))) { 03550 l = l->next; 03551 continue; 03552 } 03553 /* send, but not to src */ 03554 if (strcmp(l->name, src)) { 03555 wf.data = ast_strdup(str); 03556 if (l->chan) 03557 ast_write(l->chan, &wf); 03558 } 03559 l = l->next; 03560 } 03561 return; 03562 } 03563 rpt_mutex_lock(&myrpt->lock); 03564 if (c == myrpt->p.endchar) 03565 myrpt->stopgen = 1; 03566 if (myrpt->callmode == 1) { 03567 myrpt->exten[myrpt->cidx++] = c; 03568 myrpt->exten[myrpt->cidx] = 0; 03569 /* if this exists */ 03570 if (ast_exists_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) { 03571 myrpt->callmode = 2; 03572 if (!myrpt->patchquiet) { 03573 rpt_mutex_unlock(&myrpt->lock); 03574 rpt_telemetry(myrpt, PROC, NULL); 03575 rpt_mutex_lock(&myrpt->lock); 03576 } 03577 } 03578 /* if can continue, do so */ 03579 if (!ast_canmatch_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) { 03580 /* call has failed, inform user */ 03581 myrpt->callmode = 4; 03582 } 03583 } 03584 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) { 03585 myrpt->mydtmf = c; 03586 } 03587 if (c == myrpt->p.funcchar) { 03588 myrpt->rem_dtmfidx = 0; 03589 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0; 03590 time(&myrpt->rem_dtmf_time); 03591 rpt_mutex_unlock(&myrpt->lock); 03592 return; 03593 } else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0)) { 03594 time(&myrpt->rem_dtmf_time); 03595 if (myrpt->rem_dtmfidx < MAXDTMF) { 03596 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c; 03597 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0; 03598 03599 rpt_mutex_unlock(&myrpt->lock); 03600 ast_copy_string(cmd, myrpt->rem_dtmfbuf, sizeof(cmd)); 03601 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink); 03602 rpt_mutex_lock(&myrpt->lock); 03603 03604 switch (res) { 03605 case DC_INDETERMINATE: 03606 break; 03607 case DC_REQ_FLUSH: 03608 myrpt->rem_dtmfidx = 0; 03609 myrpt->rem_dtmfbuf[0] = 0; 03610 break; 03611 case DC_COMPLETE: 03612 myrpt->totalexecdcommands++; 03613 myrpt->dailyexecdcommands++; 03614 ast_copy_string(myrpt->lastdtmfcommand, cmd, MAXDTMF); 03615 myrpt->lastdtmfcommand[MAXDTMF-1] = '\0'; 03616 myrpt->rem_dtmfbuf[0] = 0; 03617 myrpt->rem_dtmfidx = -1; 03618 myrpt->rem_dtmf_time = 0; 03619 break; 03620 case DC_ERROR: 03621 default: 03622 myrpt->rem_dtmfbuf[0] = 0; 03623 myrpt->rem_dtmfidx = -1; 03624 myrpt->rem_dtmf_time = 0; 03625 break; 03626 } 03627 } 03628 03629 } 03630 rpt_mutex_unlock(&myrpt->lock); 03631 return; 03632 }
static void handle_link_phone_dtmf | ( | struct rpt * | myrpt, | |
struct rpt_link * | mylink, | |||
char | c | |||
) | [static] |
Definition at line 3634 of file app_rpt.c.
References ast_canmatch_extension(), ast_copy_string(), ast_exists_extension(), rpt::callmode, rpt::cidx, rpt::cmdnode, collect_function_digits(), COMPLETE, rpt::dailyexecdcommands, DC_COMPLETE, DC_DOKEY, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, rpt::dtmfbuf, rpt::dtmfidx, rpt::endchar, rpt::exten, rpt::funcchar, rpt::lastdtmfcommand, rpt_link::lastrx, rpt::lock, MAXDTMF, rpt::mydtmf, rpt::p, rpt::patchcontext, rpt::patchquiet, rpt::pchannel, rpt_link::phonemode, PROC, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), send_link_dtmf(), SOURCE_DPHONE, SOURCE_LNK, SOURCE_PHONE, rpt::stopgen, and rpt::totalexecdcommands.
Referenced by rpt().
03635 { 03636 char cmd[300]; 03637 int res; 03638 03639 rpt_mutex_lock(&myrpt->lock); 03640 if (c == myrpt->p.endchar) { 03641 if (mylink->lastrx) { 03642 mylink->lastrx = 0; 03643 rpt_mutex_unlock(&myrpt->lock); 03644 return; 03645 } 03646 myrpt->stopgen = 1; 03647 if (myrpt->cmdnode[0]) { 03648 myrpt->cmdnode[0] = 0; 03649 myrpt->dtmfidx = -1; 03650 myrpt->dtmfbuf[0] = 0; 03651 rpt_mutex_unlock(&myrpt->lock); 03652 rpt_telemetry(myrpt, COMPLETE, NULL); 03653 return; 03654 } 03655 } 03656 if (myrpt->cmdnode[0]) { 03657 rpt_mutex_unlock(&myrpt->lock); 03658 send_link_dtmf(myrpt, c); 03659 return; 03660 } 03661 if (myrpt->callmode == 1) { 03662 myrpt->exten[myrpt->cidx++] = c; 03663 myrpt->exten[myrpt->cidx] = 0; 03664 /* if this exists */ 03665 if (ast_exists_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) { 03666 myrpt->callmode = 2; 03667 if (!myrpt->patchquiet) { 03668 rpt_mutex_unlock(&myrpt->lock); 03669 rpt_telemetry(myrpt, PROC, NULL); 03670 rpt_mutex_lock(&myrpt->lock); 03671 } 03672 } 03673 /* if can continue, do so */ 03674 if (!ast_canmatch_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) { 03675 /* call has failed, inform user */ 03676 myrpt->callmode = 4; 03677 } 03678 } 03679 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) { 03680 myrpt->mydtmf = c; 03681 } 03682 if (c == myrpt->p.funcchar) { 03683 myrpt->rem_dtmfidx = 0; 03684 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0; 03685 time(&myrpt->rem_dtmf_time); 03686 rpt_mutex_unlock(&myrpt->lock); 03687 return; 03688 } else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0)) { 03689 time(&myrpt->rem_dtmf_time); 03690 if (myrpt->rem_dtmfidx < MAXDTMF) { 03691 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c; 03692 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0; 03693 03694 rpt_mutex_unlock(&myrpt->lock); 03695 ast_copy_string(cmd, myrpt->rem_dtmfbuf, sizeof(cmd)); 03696 switch(mylink->phonemode) { 03697 case 1: 03698 res = collect_function_digits(myrpt, cmd, 03699 SOURCE_PHONE, mylink); 03700 break; 03701 case 2: 03702 res = collect_function_digits(myrpt, cmd, 03703 SOURCE_DPHONE, mylink); 03704 break; 03705 default: 03706 res = collect_function_digits(myrpt, cmd, 03707 SOURCE_LNK, mylink); 03708 break; 03709 } 03710 03711 rpt_mutex_lock(&myrpt->lock); 03712 03713 switch(res) { 03714 case DC_INDETERMINATE: 03715 break; 03716 case DC_DOKEY: 03717 mylink->lastrx = 1; 03718 break; 03719 case DC_REQ_FLUSH: 03720 myrpt->rem_dtmfidx = 0; 03721 myrpt->rem_dtmfbuf[0] = 0; 03722 break; 03723 case DC_COMPLETE: 03724 myrpt->totalexecdcommands++; 03725 myrpt->dailyexecdcommands++; 03726 ast_copy_string(myrpt->lastdtmfcommand, cmd, MAXDTMF); 03727 myrpt->rem_dtmfbuf[0] = 0; 03728 myrpt->rem_dtmfidx = -1; 03729 myrpt->rem_dtmf_time = 0; 03730 break; 03731 case DC_ERROR: 03732 default: 03733 myrpt->rem_dtmfbuf[0] = 0; 03734 myrpt->rem_dtmfidx = -1; 03735 myrpt->rem_dtmf_time = 0; 03736 break; 03737 } 03738 } 03739 03740 } 03741 rpt_mutex_unlock(&myrpt->lock); 03742 return; 03743 }
static int handle_remote_data | ( | struct rpt * | myrpt, | |
char * | str | |||
) | [static] |
Definition at line 5371 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.
05372 { 05373 char cmd[300], dest[300], src[300], c; 05374 int seq, res; 05375 05376 if (!strcmp(str, discstr)) 05377 return 0; 05378 if (sscanf(str, "%s %s %s %d %c", cmd, dest, src, &seq, &c) != 5) { 05379 ast_log(LOG_WARNING, "Unable to parse link string %s\n", str); 05380 return 0; 05381 } 05382 if (strcmp(cmd, "D")) { 05383 ast_log(LOG_WARNING, "Unable to parse link string %s\n", str); 05384 return 0; 05385 } 05386 /* if not for me, ignore */ 05387 if (strcmp(dest, myrpt->name)) 05388 return 0; 05389 res = handle_remote_dtmf_digit(myrpt, c, NULL, 0); 05390 if (res != 1) 05391 return res; 05392 myrpt->remotetx = 0; 05393 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY); 05394 if (!myrpt->remoterx) { 05395 ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_KEY); 05396 } 05397 if (ast_safe_sleep(myrpt->remchannel, 1000) == -1) 05398 return -1; 05399 res = telem_lookup(myrpt, myrpt->remchannel, myrpt->name, "functcomplete"); 05400 rmt_telem_finish(myrpt, myrpt->remchannel); 05401 return res; 05402 }
static int handle_remote_dtmf_digit | ( | struct rpt * | myrpt, | |
char | c, | |||
char * | keyed, | |||
int | phonemode | |||
) | [static] |
Definition at line 5282 of file app_rpt.c.
References ast_copy_string(), collect_function_digits(), rpt::dailyexecdcommands, 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, rpt::lastdtmfcommand, MAXDTMF, rpt::p, SOURCE_DPHONE, SOURCE_PHONE, SOURCE_RMT, stop_scan(), and rpt::totalexecdcommands.
Referenced by handle_remote_data(), and handle_remote_phone_dtmf().
05283 { 05284 time_t now; 05285 int ret, res = 0, src; 05286 05287 /* Stop scan mode if in scan mode */ 05288 if (myrpt->hfscanmode) { 05289 stop_scan(myrpt, 0); 05290 return 0; 05291 } 05292 05293 time(&now); 05294 /* if timed-out */ 05295 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now) { 05296 myrpt->dtmfidx = -1; 05297 myrpt->dtmfbuf[0] = 0; 05298 myrpt->dtmf_time_rem = 0; 05299 } 05300 /* if decode not active */ 05301 if (myrpt->dtmfidx == -1) { 05302 /* if not lead-in digit, dont worry */ 05303 if (c != myrpt->p.funcchar) 05304 return 0; 05305 myrpt->dtmfidx = 0; 05306 myrpt->dtmfbuf[0] = 0; 05307 myrpt->dtmf_time_rem = now; 05308 return 0; 05309 } 05310 /* if too many in buffer, start over */ 05311 if (myrpt->dtmfidx >= MAXDTMF) { 05312 myrpt->dtmfidx = 0; 05313 myrpt->dtmfbuf[0] = 0; 05314 myrpt->dtmf_time_rem = now; 05315 } 05316 if (c == myrpt->p.funcchar) { 05317 /* if star at beginning, or 2 together, erase buffer */ 05318 if ((myrpt->dtmfidx < 1) || (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar)) { 05319 myrpt->dtmfidx = 0; 05320 myrpt->dtmfbuf[0] = 0; 05321 myrpt->dtmf_time_rem = now; 05322 return 0; 05323 } 05324 } 05325 myrpt->dtmfbuf[myrpt->dtmfidx++] = c; 05326 myrpt->dtmfbuf[myrpt->dtmfidx] = 0; 05327 myrpt->dtmf_time_rem = now; 05328 05329 05330 src = SOURCE_RMT; 05331 if (phonemode > 1) 05332 src = SOURCE_DPHONE; 05333 else if (phonemode) 05334 src = SOURCE_PHONE; 05335 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL); 05336 05337 switch(ret) { 05338 case DC_INDETERMINATE: 05339 res = 0; 05340 break; 05341 case DC_DOKEY: 05342 if (keyed) 05343 *keyed = 1; 05344 res = 0; 05345 break; 05346 case DC_REQ_FLUSH: 05347 myrpt->dtmfidx = 0; 05348 myrpt->dtmfbuf[0] = 0; 05349 res = 0; 05350 break; 05351 case DC_COMPLETE: 05352 myrpt->totalexecdcommands++; 05353 myrpt->dailyexecdcommands++; 05354 ast_copy_string(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF); 05355 myrpt->dtmfbuf[0] = 0; 05356 myrpt->dtmfidx = -1; 05357 myrpt->dtmf_time_rem = 0; 05358 res = 1; 05359 break; 05360 case DC_ERROR: 05361 default: 05362 myrpt->dtmfbuf[0] = 0; 05363 myrpt->dtmfidx = -1; 05364 myrpt->dtmf_time_rem = 0; 05365 res = 0; 05366 } 05367 05368 return res; 05369 }
static int handle_remote_phone_dtmf | ( | struct rpt * | myrpt, | |
char | c, | |||
char * | keyed, | |||
int | phonemode | |||
) | [static] |
Definition at line 5404 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::p, rpt::remchannel, rpt::remoterx, rpt::remotetx, rmt_telem_finish(), telem_lookup(), and rpt::txchannel.
05405 { 05406 int res; 05407 05408 if (keyed && *keyed && (c == myrpt->p.endchar)) { 05409 *keyed = 0; 05410 return DC_INDETERMINATE; 05411 } 05412 05413 res = handle_remote_dtmf_digit(myrpt, c, keyed, phonemode); 05414 if (res != 1) 05415 return res; 05416 myrpt->remotetx = 0; 05417 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY); 05418 if (!myrpt->remoterx) { 05419 ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_KEY); 05420 } 05421 if (ast_safe_sleep(myrpt->remchannel, 1000) == -1) 05422 return -1; 05423 res = telem_lookup(myrpt, myrpt->remchannel, myrpt->name, "functcomplete"); 05424 rmt_telem_finish(myrpt, myrpt->remchannel); 05425 return res; 05426 }
static int load_module | ( | void | ) | [static] |
Definition at line 7449 of file app_rpt.c.
References ast_cli_register_multiple(), ast_config_load, ast_log(), AST_MODULE_LOAD_DECLINE, ast_pthread_create, ast_register_application, cli_rpt, CONFIG_FLAG_NOCACHE, LOG_WARNING, rpt_exec(), and rpt_master().
07450 { 07451 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; 07452 struct ast_config *cfg = ast_config_load("rpt.conf", config_flags); 07453 if (!cfg) { 07454 ast_log(LOG_WARNING, "No such configuration file rpt.conf\n"); 07455 return AST_MODULE_LOAD_DECLINE; 07456 } 07457 ast_pthread_create(&rpt_master_thread, NULL, rpt_master, cfg); 07458 07459 /* Register cli extensions */ 07460 ast_cli_register_multiple(cli_rpt, sizeof(cli_rpt) / sizeof(struct ast_cli_entry)); 07461 07462 return ast_register_application(app, rpt_exec, synopsis, descrip); 07463 }
static void load_rpt_vars | ( | int | n, | |
int | init | |||
) | [static] |
Definition at line 862 of file app_rpt.c.
References AST_APP_ARG, ast_config_destroy(), ast_config_load, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_variable_browse(), ast_verb, rpt::cfg, CONFIG_FLAG_NOCACHE, DEFAULT_IOBASE, rpt::duplex, ENDCHAR, rpt::endchar, FUNCCHAR, rpt::funcchar, FUNCTIONS, rpt::functions, GOSUB, rpt::gosub, HANGTIME, rpt::hangtime, IDTIME, rpt::idtime, rpt::iobase, lock, LOG_NOTICE, MACRO, rpt::macro, MEMORY, rpt::memory, rpt::name, name, NODES, rpt::nodes, rpt::ourcallerid, rpt::ourcontext, rpt::p, POLITEID, rpt::politeid, rpt_vars, rpt::simple, str, rpt::tailmsgbuf, TOTIME, rpt::totime, typeof(), and var.
Referenced by rpt(), and rpt_master().
00863 { 00864 int j; 00865 struct ast_variable *vp, *var; 00866 struct ast_config *cfg; 00867 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; 00868 #ifdef __RPT_NOTCH 00869 AST_DECLARE_APP_ARGS(strs, 00870 AST_APP_ARG(str)[100]; 00871 ); 00872 #endif 00873 00874 ast_verb(3, "%s config for repeater %s\n", 00875 (init) ? "Loading initial" : "Re-Loading", rpt_vars[n].name); 00876 ast_mutex_lock(&rpt_vars[n].lock); 00877 if (rpt_vars[n].cfg) 00878 ast_config_destroy(rpt_vars[n].cfg); 00879 cfg = ast_config_load("rpt.conf", config_flags); 00880 if (!cfg) { 00881 ast_mutex_unlock(&rpt_vars[n].lock); 00882 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n"); 00883 pthread_exit(NULL); 00884 } 00885 rpt_vars[n].cfg = cfg; 00886 /* Free previously malloc'ed buffer */ 00887 if (!init && rpt_vars[n].p.tailmsgbuf) 00888 ast_free(rpt_vars[n].p.tailmsgbuf); 00889 memset(&rpt_vars[n].p, 0, sizeof(rpt_vars[n].p)); 00890 if (init) { 00891 /* clear all the fields in the structure after 'p' */ 00892 memset(&rpt_vars[n].p + sizeof(rpt_vars[0].p), 0, sizeof(rpt_vars[0]) - sizeof(rpt_vars[0].p) - offsetof(typeof(rpt_vars[0]), p)); 00893 rpt_vars[n].tele.next = &rpt_vars[n].tele; 00894 rpt_vars[n].tele.prev = &rpt_vars[n].tele; 00895 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL; 00896 rpt_vars[n].tailmessagen = 0; 00897 } 00898 #ifdef __RPT_NOTCH 00899 /* zot out filters stuff */ 00900 memset(&rpt_vars[n].filters, 0, sizeof(rpt_vars[n].filters)); 00901 #endif 00902 00903 /* Defaults */ 00904 ast_copy_string(rpt_vars[n].p.ourcontext, rpt_vars[n].name, sizeof(rpt_vars[n].p.ourcontext)); 00905 rpt_vars[n].p.hangtime = HANGTIME; 00906 rpt_vars[n].p.totime = TOTIME; 00907 rpt_vars[n].p.duplex = 2; 00908 rpt_vars[n].p.idtime = IDTIME; 00909 rpt_vars[n].p.politeid = POLITEID; 00910 ast_copy_string(rpt_vars[n].p.memory, MEMORY, sizeof(rpt_vars[n].p.memory)); 00911 ast_copy_string(rpt_vars[n].p.macro, MACRO, sizeof(rpt_vars[n].p.macro)); 00912 ast_copy_string(rpt_vars[n].p.gosub, GOSUB, sizeof(rpt_vars[n].p.gosub)); 00913 rpt_vars[n].p.iobase = DEFAULT_IOBASE; 00914 ast_copy_string(rpt_vars[n].p.functions, FUNCTIONS, sizeof(rpt_vars[n].p.functions)); 00915 rpt_vars[n].p.simple = 1; 00916 rpt_vars[n].p.funcchar = FUNCCHAR; 00917 rpt_vars[n].p.endchar = ENDCHAR; 00918 ast_copy_string(rpt_vars[n].p.nodes, NODES, sizeof(rpt_vars[n].p.nodes)); 00919 00920 for (var = ast_variable_browse(cfg, rpt_vars[n].name); var; var = var->next) { 00921 if (!strcmp(var->name, "context")) { 00922 ast_copy_string(rpt_vars[n].p.ourcontext, var->value, sizeof(rpt_vars[n].p.ourcontext)); 00923 } else if (!strcmp(var->name, "callerid")) { 00924 ast_copy_string(rpt_vars[n].p.ourcallerid, var->value, sizeof(rpt_vars[n].p.ourcallerid)); 00925 } else if (!strcmp(var->name, "accountcode")) { 00926 ast_copy_string(rpt_vars[n].p.acctcode, var->value, sizeof(rpt_vars[n].p.acctcode)); 00927 } else if (!strcmp(var->name, "idrecording")) { 00928 ast_copy_string(rpt_vars[n].p.ident, var->value, sizeof(rpt_vars[n].p.ident)); 00929 } else if (!strcmp(var->name, "hangtime")) { 00930 rpt_vars[n].p.hangtime = atoi(var->value); 00931 } else if (!strcmp(var->name, "totime")) { 00932 rpt_vars[n].p.totime = atoi(var->value); 00933 } else if (!strcmp(var->name, "tailmessagetime")) { 00934 rpt_vars[n].p.tailmessagetime = atoi(var->value); 00935 if (rpt_vars[n].p.tailmessagetime < 0) 00936 rpt_vars[n].p.tailmessagetime = 0; 00937 else if (rpt_vars[n].p.tailmessagetime > 2400000) 00938 rpt_vars[n].p.tailmessagetime = 2400000; 00939 } else if (!strcmp(var->name, "tailsquashedtime")) { 00940 rpt_vars[n].p.tailsquashedtime = atoi(var->value); 00941 if (rpt_vars[n].p.tailsquashedtime < 0) 00942 rpt_vars[n].p.tailsquashedtime = 0; 00943 else if (rpt_vars[n].p.tailsquashedtime > 2400000) 00944 rpt_vars[n].p.tailsquashedtime = 2400000; 00945 } else if (!strcmp(var->name, "duplex")) { 00946 rpt_vars[n].p.duplex = atoi(var->value); 00947 if (rpt_vars[n].p.duplex < 0) 00948 rpt_vars[n].p.duplex = 0; 00949 else if (rpt_vars[n].p.duplex > 4) 00950 rpt_vars[n].p.duplex = 4; 00951 } else if (!strcmp(var->name, "idtime")) { 00952 rpt_vars[n].p.idtime = atoi(var->value); 00953 if (rpt_vars[n].p.idtime < 60000) 00954 rpt_vars[n].p.idtime = 60000; 00955 else if (rpt_vars[n].p.idtime > 2400000) 00956 rpt_vars[n].p.idtime = 2400000; 00957 } else if (!strcmp(var->name, "politeid")) { 00958 rpt_vars[n].p.politeid = atoi(var->value); 00959 if (rpt_vars[n].p.politeid < 30000) 00960 rpt_vars[n].p.politeid = 30000; 00961 else if (rpt_vars[n].p.politeid > 300000) 00962 rpt_vars[n].p.politeid = 300000; 00963 } else if (!strcmp(var->name, "tonezone")) { 00964 ast_copy_string(rpt_vars[n].p.tonezone, var->value, sizeof(rpt_vars[n].p.tonezone)); 00965 } else if (!strcmp(var->name, "tailmessagelist")) { 00966 rpt_vars[n].p.tailmsgbuf = ast_strdup(var->value); 00967 AST_STANDARD_APP_ARGS(rpt_vars[n].p.tailmsg, rpt_vars[n].p.tailmsgbuf); 00968 } else if (!strcmp(var->name, "memory")) { 00969 ast_copy_string(rpt_vars[n].p.memory, var->value, sizeof(rpt_vars[n].p.memory)); 00970 } else if (!strcmp(var->name, "macro")) { 00971 ast_copy_string(rpt_vars[n].p.macro, var->value, sizeof(rpt_vars[n].p.macro)); 00972 } else if (!strcmp(var->name, "gosub")) { 00973 ast_copy_string(rpt_vars[n].p.gosub, var->value, sizeof(rpt_vars[n].p.gosub)); 00974 } else if (!strcmp(var->name, "startup_macro")) { 00975 ast_copy_string(rpt_vars[n].p.startupmacro, var->value, sizeof(rpt_vars[n].p.startupmacro)); 00976 } else if (!strcmp(var->name, "startup_gosub")) { 00977 ast_copy_string(rpt_vars[n].p.startupgosub, var->value, sizeof(rpt_vars[n].p.startupgosub)); 00978 } else if (!strcmp(var->name, "iobase")) { 00979 /* do not use atoi() here, we need to be able to have 00980 the input specified in hex or decimal so we use 00981 sscanf with a %i */ 00982 if (sscanf(var->value, "%i", &rpt_vars[n].p.iobase) != 1) 00983 rpt_vars[n].p.iobase = DEFAULT_IOBASE; 00984 } else if (!strcmp(var->name, "functions")) { 00985 rpt_vars[n].p.simple = 0; 00986 ast_copy_string(rpt_vars[n].p.functions, var->value, sizeof(rpt_vars[n].p.functions)); 00987 } else if (!strcmp(var->name, "link_functions")) { 00988 ast_copy_string(rpt_vars[n].p.link_functions, var->value, sizeof(rpt_vars[n].p.link_functions)); 00989 } else if (!strcmp(var->name, "phone_functions")) { 00990 ast_copy_string(rpt_vars[n].p.phone_functions, var->value, sizeof(rpt_vars[n].p.phone_functions)); 00991 } else if (!strcmp(var->name, "dphone_functions")) { 00992 ast_copy_string(rpt_vars[n].p.dphone_functions, var->value, sizeof(rpt_vars[n].p.dphone_functions)); 00993 } else if (!strcmp(var->name, "funcchar")) { 00994 rpt_vars[n].p.funcchar = *var->value; 00995 } else if (!strcmp(var->name, "endchar")) { 00996 rpt_vars[n].p.endchar = *var->value; 00997 } else if (!strcmp(var->name, "nobusyout")) { 00998 rpt_vars[n].p.nobusyout = ast_true(var->value); 00999 } else if (!strcmp(var->name, "nodes")) { 01000 ast_copy_string(rpt_vars[n].p.nodes, var->value, sizeof(rpt_vars[n].p.nodes)); 01001 #ifdef __RPT_NOTCH 01002 } else if (!strcmp(var->name, "rxnotch")) { 01003 char *tmp = ast_strdupa(val); 01004 AST_STANDARD_APP_ARGS(strs, tmp); 01005 strs.argc &= ~1; /* force an even number, rounded down */ 01006 if (strs.argc >= 2) { 01007 for (j = 0; j < strs.argc; j += 2) { 01008 rpt_mknotch(atof(strs.str[j]), atof(strs.str[j + 1]), 01009 &rpt_vars[n].filters[j >> 1].gain, 01010 &rpt_vars[n].filters[j >> 1].const0, 01011 &rpt_vars[n].filters[j >> 1].const1, 01012 &rpt_vars[n].filters[j >> 1].const2); 01013 sprintf(rpt_vars[n].filters[j >> 1].desc, "%s Hz, BW = %s", 01014 strs.str[j], strs.str[j + 1]); 01015 } 01016 } 01017 #endif 01018 } 01019 } 01020 01021 /* If these aren't specified, copy them from the functions property. */ 01022 if (ast_strlen_zero(rpt_vars[n].p.link_functions)) 01023 ast_copy_string(rpt_vars[n].p.link_functions, rpt_vars[n].p.functions, sizeof(rpt_vars[n].p.link_functions)); 01024 01025 rpt_vars[n].longestnode = 0; 01026 for (vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes); vp; vp = vp->next) { 01027 if ((j = strlen(vp->name)) > rpt_vars[n].longestnode) 01028 rpt_vars[n].longestnode = j; 01029 } 01030 01031 /* 01032 * For this repeater, Determine the length of the longest function 01033 */ 01034 rpt_vars[n].longestfunc = 0; 01035 for (vp = ast_variable_browse(cfg, rpt_vars[n].p.functions); vp; vp = vp->next) { 01036 if ((j = strlen(vp->name)) > rpt_vars[n].longestfunc) 01037 rpt_vars[n].longestfunc = j; 01038 } 01039 01040 rpt_vars[n].link_longestfunc = 0; 01041 for (vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions); vp; vp = vp->next) { 01042 if ((j = strlen(vp->name)) > rpt_vars[n].link_longestfunc) 01043 rpt_vars[n].link_longestfunc = j; 01044 } 01045 01046 rpt_vars[n].phone_longestfunc = 0; 01047 for (vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions); vp; vp = vp->next) { 01048 if ((j = strlen(vp->name)) > rpt_vars[n].phone_longestfunc) 01049 rpt_vars[n].phone_longestfunc = j; 01050 } 01051 01052 rpt_vars[n].dphone_longestfunc = 0; 01053 for (vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions); vp; vp = vp->next) { 01054 if ((j = strlen(vp->name)) > rpt_vars[n].dphone_longestfunc) 01055 rpt_vars[n].dphone_longestfunc = j; 01056 } 01057 01058 rpt_vars[n].macro_longest = 1; 01059 for (vp = ast_variable_browse(cfg, rpt_vars[n].p.macro); vp; vp = vp->next) { 01060 if ((j = strlen(vp->name)) > rpt_vars[n].macro_longest) 01061 rpt_vars[n].macro_longest = j; 01062 } 01063 01064 rpt_vars[n].gosub_longest = 1; 01065 for (vp = ast_variable_browse(cfg, rpt_vars[n].p.gosub); vp; vp = vp->next) { 01066 if ((j = strlen(vp->name)) > rpt_vars[n].gosub_longest) 01067 rpt_vars[n].gosub_longest = j; 01068 } 01069 ast_mutex_unlock(&rpt_vars[n].lock); 01070 }
static void local_dtmf_helper | ( | struct rpt * | myrpt, | |
char | c | |||
) | [static] |
Definition at line 5489 of file app_rpt.c.
References ast_canmatch_extension(), ast_copy_string(), ast_exists_extension(), ast_pthread_create_detached, rpt::callmode, rpt::cidx, rpt::cmdnode, collect_function_digits(), COMPLETE, rpt::dailyexecdcommands, DC_COMPLETE, DC_ERROR, DC_INDETERMINATE, DC_REQ_FLUSH, rpt::dtmf_time, rpt::dtmfbuf, rpt::dtmfidx, rpt::endchar, rpt::exten, rpt::funcchar, rpt::lastdtmfcommand, rpt::lock, MAXDTMF, rpt::mydtmf, rpt::ourcontext, rpt::p, rpt::patchcontext, rpt::patchdialtime, rpt::patchfarenddisconnect, rpt::patchnoct, rpt::patchquiet, rpt::pchannel, PROC, rpt_call(), rpt::rpt_call_thread, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), send_link_dtmf(), rpt::simple, SOURCE_RPT, rpt::stopgen, TERM, and rpt::totalexecdcommands.
Referenced by rpt().
05490 { 05491 int res; 05492 char cmd[MAXDTMF+1] = ""; 05493 05494 if (c == myrpt->p.endchar) { 05495 /* if in simple mode, kill autopatch */ 05496 if (myrpt->p.simple && myrpt->callmode) { 05497 rpt_mutex_lock(&myrpt->lock); 05498 myrpt->callmode = 0; 05499 rpt_mutex_unlock(&myrpt->lock); 05500 rpt_telemetry(myrpt, TERM, NULL); 05501 return; 05502 } 05503 rpt_mutex_lock(&myrpt->lock); 05504 myrpt->stopgen = 1; 05505 if (myrpt->cmdnode[0]) { 05506 myrpt->cmdnode[0] = 0; 05507 myrpt->dtmfidx = -1; 05508 myrpt->dtmfbuf[0] = 0; 05509 rpt_mutex_unlock(&myrpt->lock); 05510 rpt_telemetry(myrpt, COMPLETE, NULL); 05511 } else 05512 rpt_mutex_unlock(&myrpt->lock); 05513 return; 05514 } 05515 rpt_mutex_lock(&myrpt->lock); 05516 if (myrpt->cmdnode[0]) { 05517 rpt_mutex_unlock(&myrpt->lock); 05518 send_link_dtmf(myrpt, c); 05519 return; 05520 } 05521 if (!myrpt->p.simple) { 05522 if (c == myrpt->p.funcchar) { 05523 myrpt->dtmfidx = 0; 05524 myrpt->dtmfbuf[myrpt->dtmfidx] = 0; 05525 rpt_mutex_unlock(&myrpt->lock); 05526 time(&myrpt->dtmf_time); 05527 return; 05528 } else if ((c != myrpt->p.endchar) && (myrpt->dtmfidx >= 0)) { 05529 time(&myrpt->dtmf_time); 05530 05531 if (myrpt->dtmfidx < MAXDTMF) { 05532 myrpt->dtmfbuf[myrpt->dtmfidx++] = c; 05533 myrpt->dtmfbuf[myrpt->dtmfidx] = 0; 05534 05535 ast_copy_string(cmd, myrpt->dtmfbuf, sizeof(cmd)); 05536 05537 rpt_mutex_unlock(&myrpt->lock); 05538 res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL); 05539 rpt_mutex_lock(&myrpt->lock); 05540 switch(res) { 05541 case DC_INDETERMINATE: 05542 break; 05543 case DC_REQ_FLUSH: 05544 myrpt->dtmfidx = 0; 05545 myrpt->dtmfbuf[0] = 0; 05546 break; 05547 case DC_COMPLETE: 05548 myrpt->totalexecdcommands++; 05549 myrpt->dailyexecdcommands++; 05550 ast_copy_string(myrpt->lastdtmfcommand, cmd, MAXDTMF); 05551 myrpt->dtmfbuf[0] = 0; 05552 myrpt->dtmfidx = -1; 05553 myrpt->dtmf_time = 0; 05554 break; 05555 05556 case DC_ERROR: 05557 default: 05558 myrpt->dtmfbuf[0] = 0; 05559 myrpt->dtmfidx = -1; 05560 myrpt->dtmf_time = 0; 05561 break; 05562 } 05563 if (res != DC_INDETERMINATE) { 05564 rpt_mutex_unlock(&myrpt->lock); 05565 return; 05566 } 05567 } 05568 } 05569 } else /* if simple */ { 05570 if ((!myrpt->callmode) && (c == myrpt->p.funcchar)) { 05571 myrpt->callmode = 1; 05572 myrpt->patchnoct = 0; 05573 myrpt->patchquiet = 0; 05574 myrpt->patchfarenddisconnect = 0; 05575 myrpt->patchdialtime = 0; 05576 ast_copy_string(myrpt->patchcontext, myrpt->p.ourcontext, sizeof(myrpt->patchcontext)); 05577 myrpt->cidx = 0; 05578 myrpt->exten[myrpt->cidx] = 0; 05579 rpt_mutex_unlock(&myrpt->lock); 05580 ast_pthread_create_detached(&myrpt->rpt_call_thread, NULL, rpt_call, (void *)myrpt); 05581 return; 05582 } 05583 } 05584 if (myrpt->callmode == 1) { 05585 myrpt->exten[myrpt->cidx++] = c; 05586 myrpt->exten[myrpt->cidx] = 0; 05587 /* if this exists */ 05588 if (ast_exists_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) { 05589 myrpt->callmode = 2; 05590 rpt_mutex_unlock(&myrpt->lock); 05591 if (!myrpt->patchquiet) 05592 rpt_telemetry(myrpt, PROC, NULL); 05593 return; 05594 } 05595 /* if can continue, do so */ 05596 if (!ast_canmatch_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) { 05597 /* call has failed, inform user */ 05598 myrpt->callmode = 4; 05599 } 05600 rpt_mutex_unlock(&myrpt->lock); 05601 return; 05602 } 05603 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) { 05604 myrpt->mydtmf = c; 05605 } 05606 rpt_mutex_unlock(&myrpt->lock); 05607 return; 05608 }
static int matchkeyword | ( | char * | string, | |
char ** | param, | |||
char * | keywords[] | |||
) | [static] |
Definition at line 764 of file app_rpt.c.
Referenced by function_autopatchup().
00765 { 00766 int i, ls; 00767 for (i = 0; keywords[i]; i++) { 00768 ls = strlen(keywords[i]); 00769 if (!ls) { 00770 *param = NULL; 00771 return 0; 00772 } 00773 if (!strncmp(string, keywords[i], ls)) { 00774 if (param) 00775 *param = string + ls; 00776 return i + 1; 00777 } 00778 } 00779 param = NULL; 00780 return 0; 00781 }
static int multimode_bump_freq | ( | struct rpt * | myrpt, | |
int | interval | |||
) | [static] |
Definition at line 4484 of file app_rpt.c.
References multimode_bump_freq_ft897(), and rpt::remote.
Referenced by function_remote(), and service_scan().
04485 { 04486 if (!strcmp(myrpt->remote, remote_rig_ft897)) 04487 return multimode_bump_freq_ft897(myrpt, interval); 04488 else 04489 return -1; 04490 }
static int multimode_bump_freq_ft897 | ( | struct rpt * | myrpt, | |
int | interval | |||
) | [static] |
Definition at line 4400 of file app_rpt.c.
References ast_debug, check_freq_ft897(), rpt::freq, MAXREMSTR, set_freq_ft897(), and split_freq.
Referenced by multimode_bump_freq().
04401 { 04402 int m, d; 04403 04404 ast_debug(1, "Before bump: %s\n", myrpt->freq); 04405 04406 if (split_freq(&m, &d, myrpt->freq)) 04407 return -1; 04408 04409 d += (interval / 10); /* 10Hz resolution */ 04410 if (d < 0) { 04411 m--; 04412 d += 100000; 04413 } else if (d >= 100000) { 04414 m++; 04415 d -= 100000; 04416 } 04417 04418 if (check_freq_ft897(m, d, NULL)) { 04419 ast_debug(1, "Bump freq invalid\n"); 04420 return -1; 04421 } 04422 04423 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d); 04424 ast_debug(1, "After bump: %s\n", myrpt->freq); 04425 04426 return set_freq_ft897(myrpt, myrpt->freq); 04427 }
static int multimode_capable | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 4473 of file app_rpt.c.
References rpt::remote.
Referenced by function_remote().
04474 { 04475 if (!strcmp(myrpt->remote, remote_rig_ft897)) 04476 return 1; 04477 return 0; 04478 }
static int myatoi | ( | const char * | str | ) | [static] |
Definition at line 806 of file app_rpt.c.
Referenced by function_cop(), function_ilink(), function_remote(), function_status(), handle_cli_rpt_debug_level(), and retrieve_astcfgint().
00807 { 00808 int ret; 00809 00810 if (str == NULL) 00811 return -1; 00812 /* leave this %i alone, non-base-10 input is useful here */ 00813 if (sscanf(str, "%i", &ret) != 1) 00814 return -1; 00815 return ret; 00816 }
static int play_silence | ( | struct ast_channel * | chan, | |
int | duration | |||
) | [static] |
Definition at line 1488 of file app_rpt.c.
References chan, and play_tone_pair().
Referenced by send_morse().
01489 { 01490 return play_tone_pair(chan, 0, 0, duration, 0); 01491 }
static int play_tone | ( | struct ast_channel * | chan, | |
int | freq, | |||
int | duration, | |||
int | amplitude | |||
) | [static] |
Definition at line 1483 of file app_rpt.c.
References chan, and play_tone_pair().
Referenced by send_morse().
01484 { 01485 return play_tone_pair(chan, freq, 0, duration, amplitude); 01486 }
static int play_tone_pair | ( | struct ast_channel * | chan, | |
int | f1, | |||
int | f2, | |||
int | duration, | |||
int | amplitude | |||
) | [static] |
Definition at line 1468 of file app_rpt.c.
References ast_safe_sleep(), ast_tonepair_start(), chan, and ast_channel::generatordata.
Referenced by play_silence(), play_tone(), and send_tone_telemetry().
01469 { 01470 int res; 01471 01472 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude))) 01473 return res; 01474 01475 while (chan->generatordata) { 01476 if (ast_safe_sleep(chan, 1)) 01477 return -1; 01478 } 01479 01480 return 0; 01481 }
static void queue_id | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 5613 of file app_rpt.c.
References ID, rpt::idtime, rpt::idtimer, rpt::lock, rpt::mustid, rpt::p, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), and rpt::tailid.
Referenced by rpt().
05614 { 05615 myrpt->mustid = myrpt->tailid = 0; 05616 myrpt->idtimer = myrpt->p.idtime; /* Reset our ID timer */ 05617 rpt_mutex_unlock(&myrpt->lock); 05618 rpt_telemetry(myrpt, ID, NULL); 05619 rpt_mutex_lock(&myrpt->lock); 05620 }
static int rbi_mhztoband | ( | char * | str | ) | [static] |
Definition at line 3776 of file app_rpt.c.
Referenced by setrbi().
03777 { 03778 int i; 03779 03780 i = atoi(str) / 10; /* get the 10's of mhz */ 03781 switch (i) { 03782 case 2: 03783 return 10; 03784 case 5: 03785 return 11; 03786 case 14: 03787 return 2; 03788 case 22: 03789 return 3; 03790 case 44: 03791 return 4; 03792 case 124: 03793 return 0; 03794 case 125: 03795 return 1; 03796 case 126: 03797 return 8; 03798 case 127: 03799 return 5; 03800 case 128: 03801 return 6; 03802 case 129: 03803 return 7; 03804 default: 03805 break; 03806 } 03807 return -1; 03808 }
static void rbi_out | ( | struct rpt * | myrpt, | |
unsigned char * | data | |||
) | [static] |
Definition at line 3928 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().
03929 { 03930 struct dahdi_radio_param r = { 0, }; 03931 03932 r.radpar = DAHDI_RADPAR_REMMODE; 03933 r.data = DAHDI_RADPAR_REM_RBI1; 03934 /* if setparam ioctl fails, its probably not a pciradio card */ 03935 if (ioctl(myrpt->rxchannel->fds[0], DAHDI_RADIO_SETPARAM, &r) == -1) { 03936 rbi_out_parallel(myrpt, data); 03937 return; 03938 } 03939 r.radpar = DAHDI_RADPAR_REMCOMMAND; 03940 memcpy(&r.data, data, 5); 03941 if (ioctl(myrpt->rxchannel->fds[0], DAHDI_RADIO_SETPARAM, &r) == -1) { 03942 ast_log(LOG_WARNING, "Cannot send RBI command for channel %s\n", myrpt->rxchannel->name); 03943 return; 03944 } 03945 }
static void rbi_out_parallel | ( | struct rpt * | myrpt, | |
unsigned char * | data | |||
) | [static] |
Definition at line 3906 of file app_rpt.c.
References rpt::iobase, and rpt::p.
Referenced by rbi_out().
03907 { 03908 int i, j; 03909 unsigned char od, d; 03910 03911 for (i = 0; i < 5; i++) { 03912 od = *data++; 03913 for (j = 0; j < 8; j++) { 03914 d = od & 1; 03915 outb(d, myrpt->p.iobase); 03916 usleep(15); 03917 od >>= 1; 03918 outb(d | 2, myrpt->p.iobase); 03919 usleep(30); 03920 outb(d, myrpt->p.iobase); 03921 usleep(10); 03922 } 03923 } 03924 /* >= 50 us */ 03925 usleep(50); 03926 }
static int rbi_pltocode | ( | char * | str | ) | [static] |
Definition at line 3811 of file app_rpt.c.
References s.
Referenced by setrbi().
03812 { 03813 int i; 03814 char *s; 03815 03816 s = strchr(str, '.'); 03817 i = 0; 03818 if (s) 03819 i = atoi(s + 1); 03820 i += atoi(str) * 10; 03821 switch(i) { 03822 case 670: 03823 return 0; 03824 case 719: 03825 return 1; 03826 case 744: 03827 return 2; 03828 case 770: 03829 return 3; 03830 case 797: 03831 return 4; 03832 case 825: 03833 return 5; 03834 case 854: 03835 return 6; 03836 case 885: 03837 return 7; 03838 case 915: 03839 return 8; 03840 case 948: 03841 return 9; 03842 case 974: 03843 return 10; 03844 case 1000: 03845 return 11; 03846 case 1035: 03847 return 12; 03848 case 1072: 03849 return 13; 03850 case 1109: 03851 return 14; 03852 case 1148: 03853 return 15; 03854 case 1188: 03855 return 16; 03856 case 1230: 03857 return 17; 03858 case 1273: 03859 return 18; 03860 case 1318: 03861 return 19; 03862 case 1365: 03863 return 20; 03864 case 1413: 03865 return 21; 03866 case 1462: 03867 return 22; 03868 case 1514: 03869 return 23; 03870 case 1567: 03871 return 24; 03872 case 1622: 03873 return 25; 03874 case 1679: 03875 return 26; 03876 case 1738: 03877 return 27; 03878 case 1799: 03879 return 28; 03880 case 1862: 03881 return 29; 03882 case 1928: 03883 return 30; 03884 case 2035: 03885 return 31; 03886 case 2107: 03887 return 32; 03888 case 2181: 03889 return 33; 03890 case 2257: 03891 return 34; 03892 case 2336: 03893 return 35; 03894 case 2418: 03895 return 36; 03896 case 2503: 03897 return 37; 03898 } 03899 return -1; 03900 }
static int reload | ( | void | ) | [static] |
static int retrieve_astcfgint | ( | struct rpt * | myrpt, | |
const char * | category, | |||
const char * | name, | |||
int | min, | |||
int | max, | |||
int | defl | |||
) | [static] |
Definition at line 845 of file app_rpt.c.
References ast_variable_retrieve(), rpt::cfg, myatoi(), and var.
Referenced by get_wait_interval(), and telem_any().
00846 { 00847 const char *var = ast_variable_retrieve(myrpt->cfg, category, name); 00848 int ret; 00849 00850 if (var) { 00851 ret = myatoi(var); 00852 if (ret < min) 00853 ret = min; 00854 else if (ret > max) 00855 ret = max; 00856 } else 00857 ret = defl; 00858 return ret; 00859 }
static int rmt_saycharstr | ( | struct rpt * | myrpt, | |
struct ast_channel * | chan, | |||
int | delay, | |||
char * | charstr | |||
) | [static] |
Definition at line 4614 of file app_rpt.c.
References chan, rmt_telem_finish(), rmt_telem_start(), and saycharstr().
Referenced by function_remote().
04615 { 04616 int res; 04617 04618 res = rmt_telem_start(myrpt, chan, delay); 04619 04620 if (!res) 04621 res = saycharstr(chan, charstr); 04622 04623 if (!res) 04624 res = rmt_telem_finish(myrpt, chan); 04625 return res; 04626 }
static int rmt_sayfile | ( | struct rpt * | myrpt, | |
struct ast_channel * | chan, | |||
int | delay, | |||
char * | filename | |||
) | [static] |
Definition at line 4600 of file app_rpt.c.
References chan, rmt_telem_finish(), rmt_telem_start(), and sayfile().
Referenced by function_remote().
04601 { 04602 int res; 04603 04604 res = rmt_telem_start(myrpt, chan, delay); 04605 04606 if (!res) 04607 res = sayfile(chan, filename); 04608 04609 if (!res) 04610 res = rmt_telem_finish(myrpt, chan); 04611 return res; 04612 }
static int rmt_telem_finish | ( | struct rpt * | myrpt, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 4582 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().
04583 { 04584 struct dahdi_params par; 04585 04586 if (ioctl(myrpt->txchannel->fds[0], DAHDI_GET_PARAMS, &par) == -1) { 04587 return -1; 04588 04589 } 04590 if (!par.rxisoffhook) { 04591 ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_UNKEY); 04592 myrpt->remoterx = 0; 04593 } else { 04594 myrpt->remoterx = 1; 04595 } 04596 return 0; 04597 }
static int rmt_telem_start | ( | struct rpt * | myrpt, | |
struct ast_channel * | chan, | |||
int | delay | |||
) | [static] |
Definition at line 4570 of file app_rpt.c.
References AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_indicate(), ast_safe_sleep(), chan, rpt::remoterx, rpt::remotetx, and rpt::txchannel.
Referenced by function_remote(), rmt_saycharstr(), and rmt_sayfile().
04571 { 04572 myrpt->remotetx = 0; 04573 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY); 04574 if (!myrpt->remoterx) 04575 ast_indicate(chan, AST_CONTROL_RADIO_KEY); 04576 if (ast_safe_sleep(chan, delay) == -1) 04577 return -1; 04578 return 0; 04579 }
static void* rpt | ( | void * | this | ) | [static] |
Definition at line 5653 of file app_rpt.c.
References ast_channel::_state, ast_channel::appl, ast_call(), ast_channel_setoption(), ast_check_hangup(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, ast_copy_string(), ast_debug, AST_FORMAT_SLINEAR, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_free, ast_frfree, ast_hangup(), ast_indicate(), ast_log(), AST_OPTION_RELAXDTMF, AST_OPTION_TONE_VERIFY, 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_verb, ast_waitfor_n(), ast_write(), attempt_reconnect(), rpt::callmode, rpt::cfg, rpt_link::chan, rpt_tele::chan, rpt::cmdnode, rpt::conf, CONNECTED, rpt_link::connected, rpt_link::connecttime, CONNFAIL, rpt::dailyexecdcommands, rpt::dailykerchunks, rpt::dailykeyups, rpt::dailytxtime, ast_channel::data, DISC_TIME, rpt_link::disced, rpt_link::disctime, rpt::disgorgetime, do_scheduler(), rpt::dtmf_time, DTMF_TIMEOUT, rpt::dtmfbuf, rpt::dtmfidx, rpt::duplex, rpt_link::elaptime, rpt::enable, rpt::exten, rpt::exttx, f, ast_channel::fds, rpt::gosubbuf, GOSUBPTIME, GOSUBTIME, rpt::gosubtimer, handle_link_data(), handle_link_phone_dtmf(), rpt::hangtime, rpt_link::hasconnected, ID, IDTALKOVER, rpt::idtimer, rpt_link::isremote, rpt::keyed, rpt_link::killme, rpt::lastdtmfcommand, rpt::lastnodewhichkeyedusup, rpt_link::lastrx, rpt_link::lasttx, rpt::links, load_rpt_vars(), local_dtmf_helper(), rpt::localtx, rpt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, rpt::macrobuf, MACROPTIME, MACROTIME, rpt::macrotimer, MAX_RETRIES, MAXCONNECTTIME, rpt_link::mode, rpt_tele::mode, MSWAIT, rpt::mustid, rpt_link::name, rpt::name, ast_channel::name, rpt_link::next, rpt_tele::next, rpt_link::outbound, rpt::p, rpt_link::pchan, rpt::pchannel, rpt::politeid, rpt_link::prev, queue_id(), rpt_link::reconnects, REDUNDANT_TX_TIME, rpt::reload, rpt::rem_dtmf_time, rpt::rem_dtmfbuf, rpt::rem_dtmfidx, REMDISC, rpt_link::retries, RETRY_TIMER_MS, rpt_link::retrytimer, rpt_link::retxtimer, rpt::retxtimer, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), rpt::rpt_thread, rpt_vars, rpt::rxchanname, rpt::rxchannel, rpt::skedtimer, rpt::startupgosub, rpt::startupmacro, rpt::tailevent, rpt::tailid, rpt::tailmessagetime, rpt::tailmsg, TAILMSG, rpt::tailtimer, rpt::tele, TIMEOUT, rpt::timeouts, rpt::tmsgtimer, rpt::tonotify, rpt::totalexecdcommands, rpt::totalkerchunks, rpt::totalkeyups, rpt::totaltxtime, rpt::totime, rpt::totimer, rpt::tounkeyed, rpt::txchanname, rpt::txchannel, rpt::txconf, rpt::txpchannel, UNKEY, and ast_channel::whentohangup.
05654 { 05655 struct rpt *myrpt = (struct rpt *)this; 05656 char *tele, c; 05657 const char *idtalkover; 05658 int ms = MSWAIT, i, lasttx=0, val, remrx=0, identqueued, othertelemqueued, tailmessagequeued, ctqueued; 05659 struct ast_channel *who; 05660 struct dahdi_confinfo ci; /* conference info */ 05661 time_t t; 05662 struct rpt_link *l, *m; 05663 struct rpt_tele *telem; 05664 char tmpstr[300]; 05665 05666 rpt_mutex_lock(&myrpt->lock); 05667 05668 telem = myrpt->tele.next; 05669 while (telem != &myrpt->tele) { 05670 ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); 05671 telem = telem->next; 05672 } 05673 rpt_mutex_unlock(&myrpt->lock); 05674 /* find our index, and load the vars initially */ 05675 for (i = 0; i < nrpts; i++) { 05676 if (&rpt_vars[i] == myrpt) { 05677 load_rpt_vars(i, 0); 05678 break; 05679 } 05680 } 05681 rpt_mutex_lock(&myrpt->lock); 05682 ast_copy_string(tmpstr, myrpt->rxchanname, sizeof(tmpstr)); 05683 tele = strchr(tmpstr, '/'); 05684 if (!tele) { 05685 ast_log(LOG_ERROR, "rpt:Rxchannel Dial number (%s) must be in format tech/number\n", myrpt->rxchanname); 05686 rpt_mutex_unlock(&myrpt->lock); 05687 myrpt->rpt_thread = AST_PTHREADT_STOP; 05688 pthread_exit(NULL); 05689 } 05690 *tele++ = 0; 05691 myrpt->rxchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, tele, NULL); 05692 if (myrpt->rxchannel) { 05693 if (myrpt->rxchannel->_state == AST_STATE_BUSY) { 05694 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Rx channel\n"); 05695 rpt_mutex_unlock(&myrpt->lock); 05696 ast_hangup(myrpt->rxchannel); 05697 myrpt->rpt_thread = AST_PTHREADT_STOP; 05698 pthread_exit(NULL); 05699 } 05700 ast_set_read_format(myrpt->rxchannel, AST_FORMAT_SLINEAR); 05701 ast_set_write_format(myrpt->rxchannel, AST_FORMAT_SLINEAR); 05702 myrpt->rxchannel->whentohangup = 0; 05703 myrpt->rxchannel->appl = "Apprpt"; 05704 myrpt->rxchannel->data = "(Repeater Rx)"; 05705 ast_verb(3, "rpt (Rx) initiating call to %s/%s on %s\n", 05706 tmpstr, tele, myrpt->rxchannel->name); 05707 ast_call(myrpt->rxchannel, tele, 999); 05708 if (myrpt->rxchannel->_state != AST_STATE_UP) { 05709 rpt_mutex_unlock(&myrpt->lock); 05710 ast_hangup(myrpt->rxchannel); 05711 myrpt->rpt_thread = AST_PTHREADT_STOP; 05712 pthread_exit(NULL); 05713 } 05714 } else { 05715 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Rx channel\n"); 05716 rpt_mutex_unlock(&myrpt->lock); 05717 myrpt->rpt_thread = AST_PTHREADT_STOP; 05718 pthread_exit(NULL); 05719 } 05720 if (myrpt->txchanname) { 05721 ast_copy_string(tmpstr, myrpt->txchanname, sizeof(tmpstr)); 05722 tele = strchr(tmpstr, '/'); 05723 if (!tele) { 05724 ast_log(LOG_ERROR, "rpt:Txchannel Dial number (%s) must be in format tech/number\n", myrpt->txchanname); 05725 rpt_mutex_unlock(&myrpt->lock); 05726 ast_hangup(myrpt->rxchannel); 05727 myrpt->rpt_thread = AST_PTHREADT_STOP; 05728 pthread_exit(NULL); 05729 } 05730 *tele++ = 0; 05731 myrpt->txchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, tele, NULL); 05732 if (myrpt->txchannel) { 05733 if (myrpt->txchannel->_state == AST_STATE_BUSY) { 05734 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n"); 05735 rpt_mutex_unlock(&myrpt->lock); 05736 ast_hangup(myrpt->txchannel); 05737 ast_hangup(myrpt->rxchannel); 05738 myrpt->rpt_thread = AST_PTHREADT_STOP; 05739 pthread_exit(NULL); 05740 } 05741 ast_set_read_format(myrpt->txchannel, AST_FORMAT_SLINEAR); 05742 ast_set_write_format(myrpt->txchannel, AST_FORMAT_SLINEAR); 05743 myrpt->txchannel->whentohangup = 0; 05744 myrpt->txchannel->appl = "Apprpt"; 05745 myrpt->txchannel->data = "(Repeater Tx)"; 05746 ast_verb(3, "rpt (Tx) initiating call to %s/%s on %s\n", 05747 tmpstr, tele, myrpt->txchannel->name); 05748 ast_call(myrpt->txchannel, tele, 999); 05749 if (myrpt->rxchannel->_state != AST_STATE_UP) { 05750 rpt_mutex_unlock(&myrpt->lock); 05751 ast_hangup(myrpt->rxchannel); 05752 ast_hangup(myrpt->txchannel); 05753 myrpt->rpt_thread = AST_PTHREADT_STOP; 05754 pthread_exit(NULL); 05755 } 05756 } else { 05757 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n"); 05758 rpt_mutex_unlock(&myrpt->lock); 05759 ast_hangup(myrpt->rxchannel); 05760 myrpt->rpt_thread = AST_PTHREADT_STOP; 05761 pthread_exit(NULL); 05762 } 05763 } else { 05764 myrpt->txchannel = myrpt->rxchannel; 05765 } 05766 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_KEY); 05767 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY); 05768 /* allocate a pseudo-channel thru asterisk */ 05769 myrpt->pchannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL); 05770 if (!myrpt->pchannel) { 05771 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n"); 05772 rpt_mutex_unlock(&myrpt->lock); 05773 if (myrpt->txchannel != myrpt->rxchannel) 05774 ast_hangup(myrpt->txchannel); 05775 ast_hangup(myrpt->rxchannel); 05776 myrpt->rpt_thread = AST_PTHREADT_STOP; 05777 pthread_exit(NULL); 05778 } 05779 /* make a conference for the tx */ 05780 ci.chan = 0; 05781 ci.confno = -1; /* make a new conf */ 05782 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER; 05783 /* first put the channel on the conference in proper mode */ 05784 if (ioctl(myrpt->txchannel->fds[0], DAHDI_SETCONF, &ci) == -1) { 05785 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 05786 rpt_mutex_unlock(&myrpt->lock); 05787 ast_hangup(myrpt->pchannel); 05788 if (myrpt->txchannel != myrpt->rxchannel) 05789 ast_hangup(myrpt->txchannel); 05790 ast_hangup(myrpt->rxchannel); 05791 myrpt->rpt_thread = AST_PTHREADT_STOP; 05792 pthread_exit(NULL); 05793 } 05794 /* save tx conference number */ 05795 myrpt->txconf = ci.confno; 05796 /* make a conference for the pseudo */ 05797 ci.chan = 0; 05798 ci.confno = -1; /* make a new conf */ 05799 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON : 05800 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER); 05801 /* first put the channel on the conference in announce mode */ 05802 if (ioctl(myrpt->pchannel->fds[0], DAHDI_SETCONF, &ci) == -1) { 05803 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 05804 rpt_mutex_unlock(&myrpt->lock); 05805 ast_hangup(myrpt->pchannel); 05806 if (myrpt->txchannel != myrpt->rxchannel) 05807 ast_hangup(myrpt->txchannel); 05808 ast_hangup(myrpt->rxchannel); 05809 myrpt->rpt_thread = AST_PTHREADT_STOP; 05810 pthread_exit(NULL); 05811 } 05812 /* save pseudo channel conference number */ 05813 myrpt->conf = ci.confno; 05814 /* allocate a pseudo-channel thru asterisk */ 05815 myrpt->txpchannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL); 05816 if (!myrpt->txpchannel) { 05817 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n"); 05818 rpt_mutex_unlock(&myrpt->lock); 05819 ast_hangup(myrpt->pchannel); 05820 if (myrpt->txchannel != myrpt->rxchannel) 05821 ast_hangup(myrpt->txchannel); 05822 ast_hangup(myrpt->rxchannel); 05823 myrpt->rpt_thread = AST_PTHREADT_STOP; 05824 pthread_exit(NULL); 05825 } 05826 /* make a conference for the tx */ 05827 ci.chan = 0; 05828 ci.confno = myrpt->txconf; 05829 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ; 05830 /* first put the channel on the conference in proper mode */ 05831 if (ioctl(myrpt->txpchannel->fds[0], DAHDI_SETCONF, &ci) == -1) { 05832 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 05833 rpt_mutex_unlock(&myrpt->lock); 05834 ast_hangup(myrpt->txpchannel); 05835 ast_hangup(myrpt->pchannel); 05836 if (myrpt->txchannel != myrpt->rxchannel) 05837 ast_hangup(myrpt->txchannel); 05838 ast_hangup(myrpt->rxchannel); 05839 myrpt->rpt_thread = AST_PTHREADT_STOP; 05840 pthread_exit(NULL); 05841 } 05842 /* Now, the idea here is to copy from the physical rx channel buffer 05843 into the pseudo tx buffer, and from the pseudo rx buffer into the 05844 tx channel buffer */ 05845 myrpt->links.next = &myrpt->links; 05846 myrpt->links.prev = &myrpt->links; 05847 myrpt->tailtimer = 0; 05848 myrpt->totimer = 0; 05849 myrpt->tmsgtimer = myrpt->p.tailmessagetime; 05850 myrpt->idtimer = myrpt->p.politeid; 05851 myrpt->mustid = myrpt->tailid = 0; 05852 myrpt->callmode = 0; 05853 myrpt->tounkeyed = 0; 05854 myrpt->tonotify = 0; 05855 myrpt->retxtimer = 0; 05856 myrpt->skedtimer = 0; 05857 myrpt->tailevent = 0; 05858 lasttx = 0; 05859 myrpt->keyed = 0; 05860 idtalkover = ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover"); 05861 myrpt->dtmfidx = -1; 05862 myrpt->dtmfbuf[0] = 0; 05863 myrpt->rem_dtmfidx = -1; 05864 myrpt->rem_dtmfbuf[0] = 0; 05865 myrpt->dtmf_time = 0; 05866 myrpt->rem_dtmf_time = 0; 05867 myrpt->enable = 1; 05868 myrpt->disgorgetime = 0; 05869 myrpt->lastnodewhichkeyedusup[0] = '\0'; 05870 myrpt->dailytxtime = 0; 05871 myrpt->totaltxtime = 0; 05872 myrpt->dailykeyups = 0; 05873 myrpt->totalkeyups = 0; 05874 myrpt->dailykerchunks = 0; 05875 myrpt->totalkerchunks = 0; 05876 myrpt->dailyexecdcommands = 0; 05877 myrpt->totalexecdcommands = 0; 05878 myrpt->timeouts = 0; 05879 myrpt->exten[0] = '\0'; 05880 myrpt->lastdtmfcommand[0] = '\0'; 05881 if (myrpt->p.startupmacro) { 05882 snprintf(myrpt->macrobuf, sizeof(myrpt->macrobuf), "PPPP%s", myrpt->p.startupmacro); 05883 } 05884 if (myrpt->p.startupgosub) { 05885 snprintf(myrpt->gosubbuf, sizeof(myrpt->gosubbuf), "PPPP%s", myrpt->p.startupgosub); 05886 } 05887 rpt_mutex_unlock(&myrpt->lock); 05888 val = 0; 05889 ast_channel_setoption(myrpt->rxchannel, AST_OPTION_TONE_VERIFY, &val, sizeof(char), 0); 05890 val = 1; 05891 ast_channel_setoption(myrpt->rxchannel, AST_OPTION_RELAXDTMF, &val, sizeof(char), 0); 05892 while (ms >= 0) { 05893 struct ast_frame *f; 05894 struct ast_channel *cs[300]; 05895 int totx=0, elap=0, n, toexit = 0; 05896 05897 /* DEBUG Dump */ 05898 if ((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)) { 05899 struct rpt_link *zl; 05900 struct rpt_tele *zt; 05901 05902 myrpt->disgorgetime = 0; 05903 ast_log(LOG_NOTICE, "********** Variable Dump Start (app_rpt) **********\n"); 05904 ast_log(LOG_NOTICE, "totx = %d\n", totx); 05905 ast_log(LOG_NOTICE, "remrx = %d\n", remrx); 05906 ast_log(LOG_NOTICE, "lasttx = %d\n", lasttx); 05907 ast_log(LOG_NOTICE, "elap = %d\n", elap); 05908 ast_log(LOG_NOTICE, "toexit = %d\n", toexit); 05909 05910 ast_log(LOG_NOTICE, "myrpt->keyed = %d\n", myrpt->keyed); 05911 ast_log(LOG_NOTICE, "myrpt->localtx = %d\n", myrpt->localtx); 05912 ast_log(LOG_NOTICE, "myrpt->callmode = %d\n", myrpt->callmode); 05913 ast_log(LOG_NOTICE, "myrpt->enable = %d\n", myrpt->enable); 05914 ast_log(LOG_NOTICE, "myrpt->mustid = %d\n", myrpt->mustid); 05915 ast_log(LOG_NOTICE, "myrpt->tounkeyed = %d\n", myrpt->tounkeyed); 05916 ast_log(LOG_NOTICE, "myrpt->tonotify = %d\n", myrpt->tonotify); 05917 ast_log(LOG_NOTICE, "myrpt->retxtimer = %ld\n", myrpt->retxtimer); 05918 ast_log(LOG_NOTICE, "myrpt->totimer = %d\n", myrpt->totimer); 05919 ast_log(LOG_NOTICE, "myrpt->tailtimer = %d\n", myrpt->tailtimer); 05920 ast_log(LOG_NOTICE, "myrpt->tailevent = %d\n", myrpt->tailevent); 05921 05922 zl = myrpt->links.next; 05923 while (zl != &myrpt->links) { 05924 ast_log(LOG_NOTICE, "*** Link Name: %s ***\n", zl->name); 05925 ast_log(LOG_NOTICE, " link->lasttx %d\n", zl->lasttx); 05926 ast_log(LOG_NOTICE, " link->lastrx %d\n", zl->lastrx); 05927 ast_log(LOG_NOTICE, " link->connected %d\n", zl->connected); 05928 ast_log(LOG_NOTICE, " link->hasconnected %d\n", zl->hasconnected); 05929 ast_log(LOG_NOTICE, " link->outbound %d\n", zl->outbound); 05930 ast_log(LOG_NOTICE, " link->disced %d\n", zl->disced); 05931 ast_log(LOG_NOTICE, " link->killme %d\n", zl->killme); 05932 ast_log(LOG_NOTICE, " link->disctime %ld\n", zl->disctime); 05933 ast_log(LOG_NOTICE, " link->retrytimer %ld\n", zl->retrytimer); 05934 ast_log(LOG_NOTICE, " link->retries = %d\n", zl->retries); 05935 ast_log(LOG_NOTICE, " link->reconnects = %d\n", zl->reconnects); 05936 zl = zl->next; 05937 } 05938 05939 zt = myrpt->tele.next; 05940 if (zt != &myrpt->tele) 05941 ast_log(LOG_NOTICE, "*** Telemetry Queue ***\n"); 05942 while (zt != &myrpt->tele) { 05943 ast_log(LOG_NOTICE, " Telemetry mode: %d\n", zt->mode); 05944 zt = zt->next; 05945 } 05946 ast_log(LOG_NOTICE, "******* Variable Dump End (app_rpt) *******\n"); 05947 } 05948 05949 if (myrpt->reload) { 05950 struct rpt_tele *telem; 05951 05952 rpt_mutex_lock(&myrpt->lock); 05953 telem = myrpt->tele.next; 05954 while (telem != &myrpt->tele) { 05955 ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); 05956 telem = telem->next; 05957 } 05958 myrpt->reload = 0; 05959 rpt_mutex_unlock(&myrpt->lock); 05960 usleep(10000); 05961 /* find our index, and load the vars */ 05962 for (i = 0; i < nrpts; i++) { 05963 if (&rpt_vars[i] == myrpt) { 05964 load_rpt_vars(i, 0); 05965 break; 05966 } 05967 } 05968 } 05969 05970 rpt_mutex_lock(&myrpt->lock); 05971 if (ast_check_hangup(myrpt->rxchannel)) break; 05972 if (ast_check_hangup(myrpt->txchannel)) break; 05973 if (ast_check_hangup(myrpt->pchannel)) break; 05974 if (ast_check_hangup(myrpt->txpchannel)) break; 05975 05976 /* Update local tx with keyed if not parsing a command */ 05977 myrpt->localtx = myrpt->keyed && (myrpt->dtmfidx == -1) && (!myrpt->cmdnode[0]); 05978 /* If someone's connected, and they're transmitting from their end to us, set remrx true */ 05979 l = myrpt->links.next; 05980 remrx = 0; 05981 while (l != &myrpt->links) { 05982 if (l->lastrx) { 05983 remrx = 1; 05984 if (l->name[0] != '0') /* Ignore '0' nodes */ 05985 strcpy(myrpt->lastnodewhichkeyedusup, l->name); /* Note the node which is doing the key up */ 05986 } 05987 l = l->next; 05988 } 05989 /* Create a "must_id" flag for the cleanup ID */ 05990 myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ; 05991 /* Build a fresh totx from myrpt->keyed and autopatch activated */ 05992 totx = myrpt->callmode; 05993 /* If full duplex, add local tx to totx */ 05994 if (myrpt->p.duplex > 1) totx = totx || myrpt->localtx; 05995 /* Traverse the telemetry list to see what's queued */ 05996 identqueued = 0; 05997 othertelemqueued = 0; 05998 tailmessagequeued = 0; 05999 ctqueued = 0; 06000 telem = myrpt->tele.next; 06001 while (telem != &myrpt->tele) { 06002 if ((telem->mode == ID) || (telem->mode == IDTALKOVER)) { 06003 identqueued = 1; /* Identification telemetry */ 06004 } else if (telem->mode == TAILMSG) { 06005 tailmessagequeued = 1; /* Tail message telemetry */ 06006 } else { 06007 if (telem->mode != UNKEY) 06008 othertelemqueued = 1; /* Other telemetry */ 06009 else 06010 ctqueued = 1; /* Courtesy tone telemetry */ 06011 } 06012 telem = telem->next; 06013 } 06014 06015 /* Add in any "other" telemetry, if 3/4 or full duplex */ 06016 if (myrpt->p.duplex > 0) 06017 totx = totx || othertelemqueued; 06018 /* Update external (to links) transmitter PTT state with everything but ID, CT, and tailmessage telemetry */ 06019 myrpt->exttx = totx; 06020 /* If half or 3/4 duplex, add localtx to external link tx */ 06021 if (myrpt->p.duplex < 2) 06022 myrpt->exttx = myrpt->exttx || myrpt->localtx; 06023 /* Add in ID telemetry to local transmitter */ 06024 totx = totx || remrx; 06025 /* If 3/4 or full duplex, add in ident and CT telemetry */ 06026 if (myrpt->p.duplex > 0) 06027 totx = totx || identqueued || ctqueued; 06028 /* Reset time out timer variables if there is no activity */ 06029 if (!totx) { 06030 myrpt->totimer = myrpt->p.totime; 06031 myrpt->tounkeyed = 0; 06032 myrpt->tonotify = 0; 06033 } else 06034 myrpt->tailtimer = myrpt->p.hangtime; /* Initialize tail timer */ 06035 /* Disable the local transmitter if we are timed out */ 06036 totx = totx && myrpt->totimer; 06037 /* if timed-out and not said already, say it */ 06038 if ((!myrpt->totimer) && (!myrpt->tonotify)) { 06039 myrpt->tonotify = 1; 06040 myrpt->timeouts++; 06041 rpt_mutex_unlock(&myrpt->lock); 06042 rpt_telemetry(myrpt, TIMEOUT, NULL); 06043 rpt_mutex_lock(&myrpt->lock); 06044 } 06045 06046 /* If unkey and re-key, reset time out timer */ 06047 if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed)) { 06048 myrpt->tounkeyed = 1; 06049 } 06050 if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed) { 06051 myrpt->totimer = myrpt->p.totime; 06052 myrpt->tounkeyed = 0; 06053 myrpt->tonotify = 0; 06054 rpt_mutex_unlock(&myrpt->lock); 06055 continue; 06056 } 06057 /* if timed-out and in circuit busy after call */ 06058 if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4)) { 06059 myrpt->callmode = 0; 06060 } 06061 /* get rid of tail if timed out */ 06062 if (!myrpt->totimer) 06063 myrpt->tailtimer = 0; 06064 /* if not timed-out, add in tail */ 06065 if (myrpt->totimer) 06066 totx = totx || myrpt->tailtimer; 06067 /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */ 06068 /* If tail message, kill the message if someone keys up over it */ 06069 if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) { 06070 int hasid = 0, hastalkover = 0; 06071 06072 telem = myrpt->tele.next; 06073 while (telem != &myrpt->tele) { 06074 if (telem->mode == ID) { 06075 if (telem->chan) 06076 ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */ 06077 hasid = 1; 06078 } 06079 if (telem->mode == TAILMSG) { 06080 if (telem->chan) 06081 ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */ 06082 } 06083 if (telem->mode == IDTALKOVER) 06084 hastalkover = 1; 06085 telem = telem->next; 06086 } 06087 rpt_mutex_unlock(&myrpt->lock); 06088 if (hasid && (!hastalkover)) 06089 rpt_telemetry(myrpt, IDTALKOVER, NULL); /* Start Talkover ID */ 06090 rpt_mutex_lock(&myrpt->lock); 06091 } 06092 /* Try to be polite */ 06093 /* If the repeater has been inactive for longer than the ID time, do an initial ID in the tail*/ 06094 /* If within 30 seconds of the time to ID, try do it in the tail */ 06095 /* else if at ID time limit, do it right over the top of them */ 06096 /* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */ 06097 if (myrpt->mustid && (!myrpt->idtimer)) 06098 queue_id(myrpt); 06099 06100 if ((totx && (!myrpt->exttx) && 06101 (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer)) { 06102 myrpt->tailid = 1; 06103 } 06104 06105 /* If tail timer expires, then check for tail messages */ 06106 06107 if (myrpt->tailevent) { 06108 myrpt->tailevent = 0; 06109 if (myrpt->tailid) { 06110 totx = 1; 06111 queue_id(myrpt); 06112 } 06113 else if ((myrpt->p.tailmsg.msgs[0]) && 06114 (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)) { 06115 totx = 1; 06116 myrpt->tmsgtimer = myrpt->p.tailmessagetime; 06117 rpt_mutex_unlock(&myrpt->lock); 06118 rpt_telemetry(myrpt, TAILMSG, NULL); 06119 rpt_mutex_lock(&myrpt->lock); 06120 } 06121 } 06122 06123 /* Main TX control */ 06124 06125 /* let telemetry transmit anyway (regardless of timeout) */ 06126 if (myrpt->p.duplex > 0) 06127 totx = totx || (myrpt->tele.next != &myrpt->tele); 06128 if (totx && (!lasttx)) { 06129 lasttx = 1; 06130 myrpt->dailykeyups++; 06131 myrpt->totalkeyups++; 06132 rpt_mutex_unlock(&myrpt->lock); 06133 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_KEY); 06134 rpt_mutex_lock(&myrpt->lock); 06135 } 06136 totx = totx && myrpt->enable; 06137 if ((!totx) && lasttx) { 06138 lasttx = 0; 06139 rpt_mutex_unlock(&myrpt->lock); 06140 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY); 06141 rpt_mutex_lock(&myrpt->lock); 06142 } 06143 time(&t); 06144 /* if DTMF timeout */ 06145 if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t)) { 06146 myrpt->dtmfidx = -1; 06147 myrpt->dtmfbuf[0] = 0; 06148 } 06149 /* if remote DTMF timeout */ 06150 if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t)) { 06151 myrpt->rem_dtmfidx = -1; 06152 myrpt->rem_dtmfbuf[0] = 0; 06153 } 06154 06155 /* Reconnect */ 06156 06157 l = myrpt->links.next; 06158 while (l != &myrpt->links) { 06159 if (l->killme) { 06160 /* remove from queue */ 06161 remque((struct qelem *) l); 06162 if (!strcmp(myrpt->cmdnode, l->name)) 06163 myrpt->cmdnode[0] = 0; 06164 rpt_mutex_unlock(&myrpt->lock); 06165 /* hang-up on call to device */ 06166 if (l->chan) 06167 ast_hangup(l->chan); 06168 ast_hangup(l->pchan); 06169 ast_free(l); 06170 rpt_mutex_lock(&myrpt->lock); 06171 /* re-start link traversal */ 06172 l = myrpt->links.next; 06173 continue; 06174 } 06175 l = l->next; 06176 } 06177 n = 0; 06178 cs[n++] = myrpt->rxchannel; 06179 cs[n++] = myrpt->pchannel; 06180 cs[n++] = myrpt->txpchannel; 06181 if (myrpt->txchannel != myrpt->rxchannel) 06182 cs[n++] = myrpt->txchannel; 06183 l = myrpt->links.next; 06184 while (l != &myrpt->links) { 06185 if ((!l->killme) && (!l->disctime) && l->chan) { 06186 cs[n++] = l->chan; 06187 cs[n++] = l->pchan; 06188 } 06189 l = l->next; 06190 } 06191 rpt_mutex_unlock(&myrpt->lock); 06192 ms = MSWAIT; 06193 who = ast_waitfor_n(cs, n, &ms); 06194 if (who == NULL) 06195 ms = 0; 06196 elap = MSWAIT - ms; 06197 rpt_mutex_lock(&myrpt->lock); 06198 l = myrpt->links.next; 06199 while (l != &myrpt->links) { 06200 if (!l->lasttx) { 06201 if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME) { 06202 l->retxtimer = 0; 06203 if (l->chan) 06204 ast_indicate(l->chan, AST_CONTROL_RADIO_UNKEY); 06205 } 06206 } else 06207 l->retxtimer = 0; 06208 if (l->disctime) { /* Disconnect timer active on a channel ? */ 06209 l->disctime -= elap; 06210 if (l->disctime <= 0) /* Disconnect timer expired on inbound channel ? */ 06211 l->disctime = 0; /* Yep */ 06212 } 06213 06214 if (l->retrytimer) { 06215 l->retrytimer -= elap; 06216 if (l->retrytimer < 0) 06217 l->retrytimer = 0; 06218 } 06219 06220 /* Tally connect time */ 06221 l->connecttime += elap; 06222 06223 /* ignore non-timing channels */ 06224 if (l->elaptime < 0) { 06225 l = l->next; 06226 continue; 06227 } 06228 l->elaptime += elap; 06229 /* if connection has taken too long */ 06230 if ((l->elaptime > MAXCONNECTTIME) && 06231 ((!l->chan) || (l->chan->_state != AST_STATE_UP))) { 06232 l->elaptime = 0; 06233 rpt_mutex_unlock(&myrpt->lock); 06234 if (l->chan) 06235 ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); 06236 rpt_mutex_lock(&myrpt->lock); 06237 break; 06238 } 06239 if ((!l->chan) && (!l->retrytimer) && l->outbound && 06240 (l->retries++ < MAX_RETRIES) && (l->hasconnected)) { 06241 if (l->chan) 06242 ast_hangup(l->chan); 06243 rpt_mutex_unlock(&myrpt->lock); 06244 if ((l->name[0] != '0') && (!l->isremote)) { 06245 l->retrytimer = MAX_RETRIES + 1; 06246 } else { 06247 if (attempt_reconnect(myrpt, l) == -1) { 06248 l->retrytimer = RETRY_TIMER_MS; 06249 } 06250 } 06251 rpt_mutex_lock(&myrpt->lock); 06252 break; 06253 } 06254 if ((!l->chan) && (!l->retrytimer) && l->outbound && (l->retries >= MAX_RETRIES)) { 06255 /* remove from queue */ 06256 remque((struct qelem *) l); 06257 if (!strcmp(myrpt->cmdnode, l->name)) 06258 myrpt->cmdnode[0] = 0; 06259 rpt_mutex_unlock(&myrpt->lock); 06260 if (l->name[0] != '0') { 06261 if (!l->hasconnected) 06262 rpt_telemetry(myrpt, CONNFAIL, l); 06263 else 06264 rpt_telemetry(myrpt, REMDISC, l); 06265 } 06266 /* hang-up on call to device */ 06267 ast_hangup(l->pchan); 06268 ast_free(l); 06269 rpt_mutex_lock(&myrpt->lock); 06270 break; 06271 } 06272 if ((!l->chan) && (!l->disctime) && (!l->outbound)) { 06273 /* remove from queue */ 06274 remque((struct qelem *) l); 06275 if (!strcmp(myrpt->cmdnode, l->name)) 06276 myrpt->cmdnode[0] = 0; 06277 rpt_mutex_unlock(&myrpt->lock); 06278 if (l->name[0] != '0') { 06279 rpt_telemetry(myrpt, REMDISC, l); 06280 } 06281 /* hang-up on call to device */ 06282 ast_hangup(l->pchan); 06283 ast_free(l); 06284 rpt_mutex_lock(&myrpt->lock); 06285 break; 06286 } 06287 l = l->next; 06288 } 06289 if (totx) { 06290 myrpt->dailytxtime += elap; 06291 myrpt->totaltxtime += elap; 06292 } 06293 i = myrpt->tailtimer; 06294 if (myrpt->tailtimer) 06295 myrpt->tailtimer -= elap; 06296 if (myrpt->tailtimer < 0) 06297 myrpt->tailtimer = 0; 06298 if ((i) && (myrpt->tailtimer == 0)) 06299 myrpt->tailevent = 1; 06300 if (myrpt->totimer) 06301 myrpt->totimer -= elap; 06302 if (myrpt->totimer < 0) 06303 myrpt->totimer = 0; 06304 if (myrpt->idtimer) 06305 myrpt->idtimer -= elap; 06306 if (myrpt->idtimer < 0) 06307 myrpt->idtimer = 0; 06308 if (myrpt->tmsgtimer) 06309 myrpt->tmsgtimer -= elap; 06310 if (myrpt->tmsgtimer < 0) 06311 myrpt->tmsgtimer = 0; 06312 /* do macro timers */ 06313 if (myrpt->macrotimer) 06314 myrpt->macrotimer -= elap; 06315 if (myrpt->macrotimer < 0) 06316 myrpt->macrotimer = 0; 06317 /* do gosub timers */ 06318 if (myrpt->gosubtimer) 06319 myrpt->gosubtimer -= elap; 06320 if (myrpt->gosubtimer < 0) 06321 myrpt->gosubtimer = 0; 06322 /* Execute scheduler appx. every 2 tenths of a second */ 06323 if (myrpt->skedtimer <= 0) { 06324 myrpt->skedtimer = 200; 06325 do_scheduler(myrpt); 06326 } else 06327 myrpt->skedtimer -= elap; 06328 if (!ms) { 06329 rpt_mutex_unlock(&myrpt->lock); 06330 continue; 06331 } 06332 c = myrpt->macrobuf[0]; 06333 if (c && (!myrpt->macrotimer)) { 06334 myrpt->macrotimer = MACROTIME; 06335 memmove(myrpt->macrobuf, myrpt->macrobuf + 1, sizeof(myrpt->macrobuf) - 1); 06336 if ((c == 'p') || (c == 'P')) 06337 myrpt->macrotimer = MACROPTIME; 06338 rpt_mutex_unlock(&myrpt->lock); 06339 local_dtmf_helper(myrpt, c); 06340 } else 06341 rpt_mutex_unlock(&myrpt->lock); 06342 c = myrpt->gosubbuf[0]; 06343 if (c && (!myrpt->gosubtimer)) { 06344 myrpt->gosubtimer = GOSUBTIME; 06345 memmove(myrpt->gosubbuf, myrpt->gosubbuf + 1, sizeof(myrpt->gosubbuf) - 1); 06346 if ((c == 'p') || (c == 'P')) 06347 myrpt->gosubtimer = GOSUBPTIME; 06348 rpt_mutex_unlock(&myrpt->lock); 06349 local_dtmf_helper(myrpt, c); 06350 } else 06351 rpt_mutex_unlock(&myrpt->lock); 06352 if (who == myrpt->rxchannel) { /* if it was a read from rx */ 06353 f = ast_read(myrpt->rxchannel); 06354 if (!f) { 06355 ast_debug(1, "@@@@ rpt:Hung Up\n"); 06356 break; 06357 } 06358 if (f->frametype == AST_FRAME_VOICE) { 06359 #ifdef _MDC_DECODE_H_ 06360 unsigned char ubuf[2560]; 06361 short *sp; 06362 int n; 06363 #endif 06364 06365 if (!myrpt->localtx) { 06366 memset(f->data, 0, f->datalen); 06367 } 06368 06369 #ifdef _MDC_DECODE_H_ 06370 sp = (short *) f->data; 06371 /* convert block to unsigned char */ 06372 for (n = 0; n < f->datalen / 2; n++) { 06373 ubuf[n] = (*sp++ >> 8) + 128; 06374 } 06375 n = mdc_decoder_process_samples(myrpt->mdc, ubuf, f->datalen / 2); 06376 if (n == 1) { 06377 unsigned char op, arg; 06378 unsigned short unitID; 06379 06380 mdc_decoder_get_packet(myrpt->mdc, &op, &arg, &unitID); 06381 if (debug > 2) { 06382 ast_log(LOG_NOTICE, "Got (single-length) packet:\n"); 06383 ast_log(LOG_NOTICE, "op: %02x, arg: %02x, UnitID: %04x\n", op & 255, arg & 255, unitID); 06384 } 06385 if ((op == 1) && (arg == 0)) { 06386 myrpt->lastunit = unitID; 06387 } 06388 } 06389 if ((debug > 2) && (i == 2)) { 06390 unsigned char op, arg, ex1, ex2, ex3, ex4; 06391 unsigned short unitID; 06392 06393 mdc_decoder_get_double_packet(myrpt->mdc, &op, &arg, &unitID, &ex1, &ex2, &ex3, &ex4); 06394 ast_log(LOG_NOTICE, "Got (double-length) packet:\n"); 06395 ast_log(LOG_NOTICE, "op: %02x, arg: %02x, UnitID: %04x\n", op & 255, arg & 255, unitID); 06396 ast_log(LOG_NOTICE, "ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n", 06397 ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255); 06398 } 06399 #endif 06400 #ifdef __RPT_NOTCH 06401 /* apply inbound filters, if any */ 06402 rpt_filter(myrpt, f->data, f->datalen / 2); 06403 #endif 06404 ast_write(myrpt->pchannel, f); 06405 } else if (f->frametype == AST_FRAME_DTMF) { 06406 c = (char) f->subclass; /* get DTMF char */ 06407 ast_frfree(f); 06408 if (!myrpt->keyed) 06409 continue; 06410 local_dtmf_helper(myrpt, c); 06411 continue; 06412 } else if (f->frametype == AST_FRAME_CONTROL) { 06413 if (f->subclass == AST_CONTROL_HANGUP) { 06414 ast_debug(1, "@@@@ rpt:Hung Up\n"); 06415 ast_frfree(f); 06416 break; 06417 } 06418 /* if RX key */ 06419 if (f->subclass == AST_CONTROL_RADIO_KEY) { 06420 if ((!lasttx) || (myrpt->p.duplex > 1)) { 06421 ast_debug(8, "@@@@ rx key\n"); 06422 myrpt->keyed = 1; 06423 } 06424 } 06425 /* if RX un-key */ 06426 if (f->subclass == AST_CONTROL_RADIO_UNKEY) { 06427 if ((!lasttx) || (myrpt->p.duplex > 1)) { 06428 ast_debug(8, "@@@@ rx un-key\n"); 06429 if (myrpt->keyed) { 06430 rpt_telemetry(myrpt, UNKEY, NULL); 06431 } 06432 myrpt->keyed = 0; 06433 } 06434 } 06435 } 06436 ast_frfree(f); 06437 continue; 06438 } 06439 if (who == myrpt->pchannel) { /* if it was a read from pseudo */ 06440 f = ast_read(myrpt->pchannel); 06441 if (!f) { 06442 ast_debug(1, "@@@@ rpt:Hung Up\n"); 06443 break; 06444 } 06445 if (f->frametype == AST_FRAME_VOICE) { 06446 ast_write(myrpt->txpchannel, f); 06447 } 06448 if (f->frametype == AST_FRAME_CONTROL) { 06449 if (f->subclass == AST_CONTROL_HANGUP) { 06450 ast_debug(1, "@@@@ rpt:Hung Up\n"); 06451 ast_frfree(f); 06452 break; 06453 } 06454 } 06455 ast_frfree(f); 06456 continue; 06457 } 06458 if (who == myrpt->txchannel) { /* if it was a read from tx */ 06459 f = ast_read(myrpt->txchannel); 06460 if (!f) { 06461 ast_debug(1, "@@@@ rpt:Hung Up\n"); 06462 break; 06463 } 06464 if (f->frametype == AST_FRAME_CONTROL) { 06465 if (f->subclass == AST_CONTROL_HANGUP) { 06466 ast_debug(1, "@@@@ rpt:Hung Up\n"); 06467 ast_frfree(f); 06468 break; 06469 } 06470 } 06471 ast_frfree(f); 06472 continue; 06473 } 06474 toexit = 0; 06475 rpt_mutex_lock(&myrpt->lock); 06476 l = myrpt->links.next; 06477 while (l != &myrpt->links) { 06478 if (l->disctime) { 06479 l = l->next; 06480 continue; 06481 } 06482 if (who == l->chan) { /* if it was a read from rx */ 06483 remrx = 0; 06484 /* see if any other links are receiving */ 06485 m = myrpt->links.next; 06486 while (m != &myrpt->links) { 06487 /* if not us, count it */ 06488 if ((m != l) && (m->lastrx)) 06489 remrx = 1; 06490 m = m->next; 06491 } 06492 rpt_mutex_unlock(&myrpt->lock); 06493 totx = (((l->isremote) ? myrpt->localtx : 06494 myrpt->exttx) || remrx) && l->mode; 06495 if (l->chan && (l->lasttx != totx)) { 06496 if (totx) { 06497 ast_indicate(l->chan, AST_CONTROL_RADIO_KEY); 06498 } else { 06499 ast_indicate(l->chan, AST_CONTROL_RADIO_UNKEY); 06500 } 06501 } 06502 l->lasttx = totx; 06503 f = ast_read(l->chan); 06504 if (!f) { 06505 if ((!l->disced) && (!l->outbound)) { 06506 if ((l->name[0] == '0') || l->isremote) 06507 l->disctime = 1; 06508 else 06509 l->disctime = DISC_TIME; 06510 rpt_mutex_lock(&myrpt->lock); 06511 ast_hangup(l->chan); 06512 l->chan = 0; 06513 break; 06514 } 06515 06516 if (l->retrytimer) { 06517 rpt_mutex_lock(&myrpt->lock); 06518 break; 06519 } 06520 if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected)) { 06521 rpt_mutex_lock(&myrpt->lock); 06522 ast_hangup(l->chan); 06523 l->chan = 0; 06524 rpt_mutex_unlock(&myrpt->lock); 06525 if (attempt_reconnect(myrpt, l) == -1) { 06526 l->retrytimer = RETRY_TIMER_MS; 06527 } 06528 rpt_mutex_lock(&myrpt->lock); 06529 break; 06530 } 06531 rpt_mutex_lock(&myrpt->lock); 06532 /* remove from queue */ 06533 remque((struct qelem *) l); 06534 if (!strcmp(myrpt->cmdnode, l->name)) 06535 myrpt->cmdnode[0] = 0; 06536 rpt_mutex_unlock(&myrpt->lock); 06537 if (!l->hasconnected) 06538 rpt_telemetry(myrpt, CONNFAIL, l); 06539 else if (l->disced != 2) 06540 rpt_telemetry(myrpt, REMDISC, l); 06541 /* hang-up on call to device */ 06542 ast_hangup(l->chan); 06543 ast_hangup(l->pchan); 06544 ast_free(l); 06545 rpt_mutex_lock(&myrpt->lock); 06546 break; 06547 } 06548 if (f->frametype == AST_FRAME_VOICE) { 06549 if (!l->lastrx) { 06550 memset(f->data, 0, f->datalen); 06551 } 06552 ast_write(l->pchan, f); 06553 } 06554 if (f->frametype == AST_FRAME_TEXT) { 06555 handle_link_data(myrpt, l, f->data); 06556 } 06557 if (f->frametype == AST_FRAME_DTMF) { 06558 handle_link_phone_dtmf(myrpt, l, f->subclass); 06559 } 06560 if (f->frametype == AST_FRAME_CONTROL) { 06561 if (f->subclass == AST_CONTROL_ANSWER) { 06562 char lconnected = l->connected; 06563 l->connected = 1; 06564 l->hasconnected = 1; 06565 l->elaptime = -1; 06566 l->retries = 0; 06567 if (!lconnected) 06568 rpt_telemetry(myrpt, CONNECTED, l); 06569 else 06570 l->reconnects++; 06571 } 06572 /* if RX key */ 06573 if (f->subclass == AST_CONTROL_RADIO_KEY) { 06574 ast_debug(8, "@@@@ rx key\n"); 06575 l->lastrx = 1; 06576 } 06577 /* if RX un-key */ 06578 if (f->subclass == AST_CONTROL_RADIO_UNKEY) { 06579 ast_debug(8, "@@@@ rx un-key\n"); 06580 l->lastrx = 0; 06581 } 06582 if (f->subclass == AST_CONTROL_HANGUP) { 06583 ast_frfree(f); 06584 if ((!l->outbound) && (!l->disced)) { 06585 if ((l->name[0] == '0') || l->isremote) 06586 l->disctime = 1; 06587 else 06588 l->disctime = DISC_TIME; 06589 rpt_mutex_lock(&myrpt->lock); 06590 ast_hangup(l->chan); 06591 l->chan = 0; 06592 break; 06593 } 06594 if (l->retrytimer) { 06595 rpt_mutex_lock(&myrpt->lock); 06596 break; 06597 } 06598 if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected)) { 06599 rpt_mutex_lock(&myrpt->lock); 06600 ast_hangup(l->chan); 06601 l->chan = 0; 06602 rpt_mutex_unlock(&myrpt->lock); 06603 if (attempt_reconnect(myrpt, l) == -1) { 06604 l->retrytimer = RETRY_TIMER_MS; 06605 } 06606 rpt_mutex_lock(&myrpt->lock); 06607 break; 06608 } 06609 rpt_mutex_lock(&myrpt->lock); 06610 /* remove from queue */ 06611 remque((struct qelem *) l); 06612 if (!strcmp(myrpt->cmdnode, l->name)) 06613 myrpt->cmdnode[0] = 0; 06614 rpt_mutex_unlock(&myrpt->lock); 06615 if (!l->hasconnected) 06616 rpt_telemetry(myrpt, CONNFAIL, l); 06617 else if (l->disced != 2) 06618 rpt_telemetry(myrpt, REMDISC, l); 06619 /* hang-up on call to device */ 06620 ast_hangup(l->chan); 06621 ast_hangup(l->pchan); 06622 ast_free(l); 06623 rpt_mutex_lock(&myrpt->lock); 06624 break; 06625 } 06626 } 06627 ast_frfree(f); 06628 rpt_mutex_lock(&myrpt->lock); 06629 break; 06630 } 06631 if (who == l->pchan) { 06632 rpt_mutex_unlock(&myrpt->lock); 06633 f = ast_read(l->pchan); 06634 if (!f) { 06635 ast_debug(1, "@@@@ rpt:Hung Up\n"); 06636 toexit = 1; 06637 rpt_mutex_lock(&myrpt->lock); 06638 break; 06639 } 06640 if (f->frametype == AST_FRAME_VOICE) { 06641 if (l->chan) 06642 ast_write(l->chan, f); 06643 } 06644 if (f->frametype == AST_FRAME_CONTROL) { 06645 if (f->subclass == AST_CONTROL_HANGUP) { 06646 ast_debug(1, "@@@@ rpt:Hung Up\n"); 06647 ast_frfree(f); 06648 toexit = 1; 06649 rpt_mutex_lock(&myrpt->lock); 06650 break; 06651 } 06652 } 06653 ast_frfree(f); 06654 rpt_mutex_lock(&myrpt->lock); 06655 break; 06656 } 06657 l = l->next; 06658 } 06659 rpt_mutex_unlock(&myrpt->lock); 06660 if (toexit) 06661 break; 06662 if (who == myrpt->txpchannel) { /* if it was a read from remote tx */ 06663 f = ast_read(myrpt->txpchannel); 06664 if (!f) { 06665 ast_debug(1, "@@@@ rpt:Hung Up\n"); 06666 break; 06667 } 06668 if (f->frametype == AST_FRAME_CONTROL) { 06669 if (f->subclass == AST_CONTROL_HANGUP) { 06670 ast_debug(1, "@@@@ rpt:Hung Up\n"); 06671 ast_frfree(f); 06672 break; 06673 } 06674 } 06675 ast_frfree(f); 06676 continue; 06677 } 06678 } 06679 usleep(100000); 06680 ast_hangup(myrpt->pchannel); 06681 ast_hangup(myrpt->txpchannel); 06682 if (myrpt->txchannel != myrpt->rxchannel) 06683 ast_hangup(myrpt->txchannel); 06684 ast_hangup(myrpt->rxchannel); 06685 rpt_mutex_lock(&myrpt->lock); 06686 l = myrpt->links.next; 06687 while (l != &myrpt->links) { 06688 struct rpt_link *ll = l; 06689 /* remove from queue */ 06690 remque((struct qelem *) l); 06691 /* hang-up on call to device */ 06692 if (l->chan) 06693 ast_hangup(l->chan); 06694 ast_hangup(l->pchan); 06695 l = l->next; 06696 ast_free(ll); 06697 } 06698 rpt_mutex_unlock(&myrpt->lock); 06699 ast_debug(1, "@@@@ rpt:Hung up channel\n"); 06700 myrpt->rpt_thread = AST_PTHREADT_STOP; 06701 pthread_exit(NULL); 06702 return NULL; 06703 }
static void* rpt_call | ( | void * | this | ) | [static] |
Definition at line 2526 of file app_rpt.c.
References accountcode, rpt::acctcode, ast_callerid_parse(), ast_channel_undefer_dtmf(), ast_copy_string(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, ast_free, ast_hangup(), ast_log(), ast_pbx_start(), ast_request(), ast_safe_sleep(), ast_softhangup(), AST_SOFTHANGUP_DEV, ast_strdup, ast_string_field_set, 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::duplex, rpt::exten, ast_channel::exten, ast_channel::fds, ast_frame::frametype, rpt::lock, LOG_ERROR, LOG_WARNING, ast_frame::mallocd, MSWAIT, rpt::mydtmf, name, ast_frame::offset, rpt::ourcallerid, rpt::p, rpt::patchcontext, rpt::patchdialtime, rpt::patchfarenddisconnect, rpt::patchquiet, ast_channel::pbx, rpt::pchannel, ast_channel::priority, rpt_mutex_lock, rpt_mutex_unlock, rpt_telemetry(), ast_frame::samples, ast_frame::subclass, TERM, and rpt::tonezone.
Referenced by local_dtmf_helper().
02527 { 02528 struct dahdi_confinfo ci; /* conference info */ 02529 struct rpt *myrpt = (struct rpt *)this; 02530 int res; 02531 struct ast_frame wf; 02532 int stopped, congstarted, dialtimer, lastcidx, aborted; 02533 struct ast_channel *mychannel, *genchannel; 02534 02535 myrpt->mydtmf = 0; 02536 /* allocate a pseudo-channel thru asterisk */ 02537 mychannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL); 02538 if (!mychannel) { 02539 ast_log(LOG_ERROR, "rpt: unable to obtain pseudo channel\n"); 02540 pthread_exit(NULL); 02541 } 02542 ci.chan = 0; 02543 ci.confno = myrpt->conf; /* use the pseudo conference */ 02544 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER 02545 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 02546 /* first put the channel on the conference */ 02547 if (ioctl(mychannel->fds[0], DAHDI_SETCONF, &ci) == -1) { 02548 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 02549 ast_hangup(mychannel); 02550 myrpt->callmode = 0; 02551 pthread_exit(NULL); 02552 } 02553 /* allocate a pseudo-channel thru asterisk */ 02554 genchannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL); 02555 if (!genchannel) { 02556 ast_log(LOG_ERROR, "rpt: unable to obtain pseudo channel\n"); 02557 ast_hangup(mychannel); 02558 pthread_exit(NULL); 02559 } 02560 ci.chan = 0; 02561 ci.confno = myrpt->conf; 02562 ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER 02563 | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 02564 /* first put the channel on the conference */ 02565 if (ioctl(genchannel->fds[0], DAHDI_SETCONF, &ci) == -1) { 02566 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 02567 ast_hangup(mychannel); 02568 ast_hangup(genchannel); 02569 myrpt->callmode = 0; 02570 pthread_exit(NULL); 02571 } 02572 if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0], myrpt->p.tonezone) == -1)) { 02573 ast_log(LOG_WARNING, "Unable to set tone zone %s\n", myrpt->p.tonezone); 02574 ast_hangup(mychannel); 02575 ast_hangup(genchannel); 02576 myrpt->callmode = 0; 02577 pthread_exit(NULL); 02578 } 02579 if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0], myrpt->p.tonezone) == -1)) { 02580 ast_log(LOG_WARNING, "Unable to set tone zone %s\n", myrpt->p.tonezone); 02581 ast_hangup(mychannel); 02582 ast_hangup(genchannel); 02583 myrpt->callmode = 0; 02584 pthread_exit(NULL); 02585 } 02586 /* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */ 02587 if ((!myrpt->patchquiet) && (tone_zone_play_tone(mychannel->fds[0], DAHDI_TONE_DIALTONE) < 0)) { 02588 ast_log(LOG_WARNING, "Cannot start dialtone\n"); 02589 ast_hangup(mychannel); 02590 ast_hangup(genchannel); 02591 myrpt->callmode = 0; 02592 pthread_exit(NULL); 02593 } 02594 stopped = 0; 02595 congstarted = 0; 02596 dialtimer = 0; 02597 lastcidx = 0; 02598 aborted = 0; 02599 02600 while ((myrpt->callmode == 1) || (myrpt->callmode == 4)) { 02601 if ((myrpt->patchdialtime) && (myrpt->callmode == 1) && (myrpt->cidx != lastcidx)) { 02602 dialtimer = 0; 02603 lastcidx = myrpt->cidx; 02604 } 02605 02606 if ((myrpt->patchdialtime) && (dialtimer >= myrpt->patchdialtime)) { 02607 rpt_mutex_lock(&myrpt->lock); 02608 aborted = 1; 02609 myrpt->callmode = 0; 02610 rpt_mutex_unlock(&myrpt->lock); 02611 break; 02612 } 02613 02614 if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0)) { 02615 stopped = 1; 02616 /* stop dial tone */ 02617 tone_zone_play_tone(mychannel->fds[0], -1); 02618 } 02619 if (myrpt->callmode == 4) { 02620 if (!congstarted) { 02621 congstarted = 1; 02622 /* start congestion tone */ 02623 tone_zone_play_tone(mychannel->fds[0], DAHDI_TONE_CONGESTION); 02624 } 02625 } 02626 res = ast_safe_sleep(mychannel, MSWAIT); 02627 if (res < 0) { 02628 ast_hangup(mychannel); 02629 ast_hangup(genchannel); 02630 rpt_mutex_lock(&myrpt->lock); 02631 myrpt->callmode = 0; 02632 rpt_mutex_unlock(&myrpt->lock); 02633 pthread_exit(NULL); 02634 } 02635 dialtimer += MSWAIT; 02636 } 02637 /* stop any tone generation */ 02638 tone_zone_play_tone(mychannel->fds[0], -1); 02639 /* end if done */ 02640 if (!myrpt->callmode) { 02641 ast_hangup(mychannel); 02642 ast_hangup(genchannel); 02643 rpt_mutex_lock(&myrpt->lock); 02644 myrpt->callmode = 0; 02645 rpt_mutex_unlock(&myrpt->lock); 02646 if ((!myrpt->patchquiet) && aborted) 02647 rpt_telemetry(myrpt, TERM, NULL); 02648 pthread_exit(NULL); 02649 } 02650 02651 if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid) { 02652 char *name, *loc, *instr; 02653 instr = ast_strdup(myrpt->p.ourcallerid); 02654 if (instr) { 02655 ast_callerid_parse(instr, &name, &loc); 02656 if (loc) { 02657 if (mychannel->cid.cid_num) 02658 ast_free(mychannel->cid.cid_num); 02659 mychannel->cid.cid_num = ast_strdup(loc); 02660 } 02661 if (name) { 02662 if (mychannel->cid.cid_name) 02663 ast_free(mychannel->cid.cid_name); 02664 mychannel->cid.cid_name = ast_strdup(name); 02665 } 02666 ast_free(instr); 02667 } 02668 } 02669 02670 ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten)); 02671 ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context)); 02672 02673 if (myrpt->p.acctcode) 02674 ast_string_field_set(mychannel, accountcode, myrpt->p.acctcode); 02675 mychannel->priority = 1; 02676 ast_channel_undefer_dtmf(mychannel); 02677 if (ast_pbx_start(mychannel) < 0) { 02678 ast_log(LOG_WARNING, "Unable to start PBX!!\n"); 02679 ast_hangup(mychannel); 02680 ast_hangup(genchannel); 02681 rpt_mutex_lock(&myrpt->lock); 02682 myrpt->callmode = 0; 02683 rpt_mutex_unlock(&myrpt->lock); 02684 pthread_exit(NULL); 02685 } 02686 usleep(10000); 02687 rpt_mutex_lock(&myrpt->lock); 02688 myrpt->callmode = 3; 02689 /* set appropriate conference for the pseudo */ 02690 ci.chan = 0; 02691 ci.confno = myrpt->conf; 02692 ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON : 02693 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER); 02694 /* first put the channel on the conference in announce mode */ 02695 if (ioctl(myrpt->pchannel->fds[0], DAHDI_SETCONF, &ci) == -1) { 02696 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 02697 ast_hangup(mychannel); 02698 ast_hangup(genchannel); 02699 myrpt->callmode = 0; 02700 pthread_exit(NULL); 02701 } 02702 while (myrpt->callmode) { 02703 if ((!mychannel->pbx) && (myrpt->callmode != 4)) { 02704 if (myrpt->patchfarenddisconnect) { /* If patch is setup for far end disconnect */ 02705 myrpt->callmode = 0; 02706 if (!myrpt->patchquiet) { 02707 rpt_mutex_unlock(&myrpt->lock); 02708 rpt_telemetry(myrpt, TERM, NULL); 02709 rpt_mutex_lock(&myrpt->lock); 02710 } 02711 } else { /* Send congestion until patch is downed by command */ 02712 myrpt->callmode = 4; 02713 rpt_mutex_unlock(&myrpt->lock); 02714 /* start congestion tone */ 02715 tone_zone_play_tone(genchannel->fds[0], DAHDI_TONE_CONGESTION); 02716 rpt_mutex_lock(&myrpt->lock); 02717 } 02718 } 02719 if (myrpt->mydtmf) { 02720 wf.frametype = AST_FRAME_DTMF; 02721 wf.subclass = myrpt->mydtmf; 02722 wf.offset = 0; 02723 wf.mallocd = 0; 02724 wf.data = NULL; 02725 wf.datalen = 0; 02726 wf.samples = 0; 02727 rpt_mutex_unlock(&myrpt->lock); 02728 ast_write(genchannel, &wf); 02729 rpt_mutex_lock(&myrpt->lock); 02730 myrpt->mydtmf = 0; 02731 } 02732 rpt_mutex_unlock(&myrpt->lock); 02733 usleep(MSWAIT * 1000); 02734 rpt_mutex_lock(&myrpt->lock); 02735 } 02736 rpt_mutex_unlock(&myrpt->lock); 02737 tone_zone_play_tone(genchannel->fds[0], -1); 02738 if (mychannel->pbx) 02739 ast_softhangup(mychannel, AST_SOFTHANGUP_DEV); 02740 ast_hangup(genchannel); 02741 rpt_mutex_lock(&myrpt->lock); 02742 myrpt->callmode = 0; 02743 rpt_mutex_unlock(&myrpt->lock); 02744 /* set appropriate conference for the pseudo */ 02745 ci.chan = 0; 02746 ci.confno = myrpt->conf; 02747 ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON : 02748 (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER); 02749 /* first put the channel on the conference in announce mode */ 02750 if (ioctl(myrpt->pchannel->fds[0], DAHDI_SETCONF, &ci) == -1) { 02751 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 02752 } 02753 pthread_exit(NULL); 02754 }
static int rpt_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 6809 of file app_rpt.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), f, LOG_WARNING, rpt::name, and rpt_vars.
Referenced by load_module().
06810 { 06811 int res = -1, i, rem_totx, n, phone_mode = 0; 06812 char *tmp, keyed = 0; 06813 char *options = NULL, *tele, c; 06814 struct rpt *myrpt; 06815 struct ast_frame *f; 06816 struct ast_channel *who; 06817 struct ast_channel *cs[20]; 06818 struct rpt_link *l; 06819 struct dahdi_confinfo ci; /* conference info */ 06820 struct dahdi_params par; 06821 int ms, elap; 06822 AST_DECLARE_APP_ARGS(args, 06823 AST_APP_ARG(node); 06824 AST_APP_ARG(options); 06825 ); 06826 06827 if (ast_strlen_zero(data)) { 06828 ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n"); 06829 return -1; 06830 } 06831 tmp = ast_strdupa((char *)data); 06832 AST_STANDARD_APP_ARGS(args, tmp); 06833 myrpt = NULL; 06834 /* see if we can find our specified one */ 06835 for (i = 0; i < nrpts; i++) { 06836 /* if name matches, assign it and exit loop */ 06837 if (!strcmp(args.node, rpt_vars[i].name)) { 06838 myrpt = &rpt_vars[i]; 06839 break; 06840 } 06841 } 06842 if (myrpt == NULL) { 06843 ast_log(LOG_WARNING, "Cannot find specified system node %s\n", args.node); 06844 return -1; 06845 } 06846 06847 /* if not phone access, must be an IAX connection */ 06848 if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R'))) { 06849 phone_mode = 1; 06850 if (*options == 'D') 06851 phone_mode = 2; 06852 ast_set_callerid(chan, "0", "app_rpt user", "0"); 06853 } else { 06854 if (strncmp(chan->name, "IAX2", 4)) { 06855 ast_log(LOG_WARNING, "We only accept links via IAX2!!\n"); 06856 return -1; 06857 } 06858 } 06859 if (*args.options == 'R') { 06860 /* Parts of this section taken from app_parkandannounce */ 06861 int m, lot, timeout = 0; 06862 char tmp[256]; 06863 char *s; 06864 AST_DECLARE_APP_ARGS(optionarg, 06865 AST_APP_ARG(template); 06866 AST_APP_ARG(timeout); 06867 AST_APP_ARG(return_context); 06868 ); 06869 06870 rpt_mutex_lock(&myrpt->lock); 06871 m = myrpt->callmode; 06872 rpt_mutex_unlock(&myrpt->lock); 06873 06874 if ((!myrpt->p.nobusyout) && m) { 06875 if (chan->_state != AST_STATE_UP) { 06876 ast_indicate(chan, AST_CONTROL_BUSY); 06877 } 06878 while (ast_safe_sleep(chan, 10000) != -1) { 06879 /* This used to be a busy loop. It's probably better to yield the processor here. */ 06880 usleep(1); 06881 } 06882 return -1; 06883 } 06884 06885 if (chan->_state != AST_STATE_UP) { 06886 ast_answer(chan); 06887 } 06888 06889 s = ast_strdupa(options); 06890 AST_STANDARD_APP_ARGS(optionarg, s); 06891 if (optionarg.argc == 0 || ast_strlen_zero(optionarg.template)) { 06892 ast_log(LOG_WARNING, "An announce template must be defined\n"); 06893 return -1; 06894 } 06895 06896 if (optionarg.argc >= 2) { 06897 timeout = atoi(optionarg.timeout) * 1000; 06898 } 06899 06900 if (!ast_strlen_zero(optionarg.return_context)) { 06901 if (ast_parseable_goto(chan, optionarg.return_context)) { 06902 ast_verb(3, "Warning: Return Context Invalid, call will return to default|s\n"); 06903 } 06904 } 06905 06906 /* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout 06907 before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */ 06908 06909 ast_masq_park_call(chan, NULL, timeout, &lot); 06910 ast_verb(3, "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, optionarg.return_context); 06911 06912 snprintf(tmp, sizeof(tmp), "%d,%s", lot, optionarg.template + 1); 06913 rpt_telemetry(myrpt, REV_PATCH, tmp); 06914 06915 return 0; 06916 } 06917 06918 if (!options) { 06919 struct ast_hostent ahp; 06920 struct hostent *hp; 06921 struct in_addr ia; 06922 char hisip[100], nodeip[100]; 06923 const char *val; 06924 char *s, *s1, *s2; 06925 06926 /* look at callerid to see what node this comes from */ 06927 if (!chan->cid.cid_num) { /* if doesn't have caller id */ 06928 ast_log(LOG_WARNING, "Doesn't have callerid on %s\n", args.node); 06929 return -1; 06930 } 06931 06932 /* get his IP from IAX2 module */ 06933 pbx_substitute_variables_helper(chan, "${IAXPEER(CURRENTCHANNEL)}", hisip, sizeof(hisip) - 1); 06934 if (ast_strlen_zero(hisip)) { 06935 ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n"); 06936 return -1; 06937 } 06938 06939 if (!strcmp(myrpt->name, chan->cid.cid_num)) { 06940 ast_log(LOG_WARNING, "Trying to link to self!!\n"); 06941 return -1; 06942 } 06943 06944 if (*(chan->cid.cid_num) < '1') { 06945 ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n", chan->cid.cid_num); 06946 return -1; 06947 } 06948 06949 /* look for his reported node string */ 06950 val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, chan->cid.cid_num); 06951 if (!val) { 06952 ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n", chan->cid.cid_num); 06953 return -1; 06954 } 06955 ast_copy_string(tmp, val, sizeof(tmp)); 06956 s = tmp; 06957 s1 = strsep(&s, ","); 06958 s2 = strsep(&s, ","); 06959 if (!s2) { 06960 ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n", chan->cid.cid_num); 06961 return -1; 06962 } 06963 if (strcmp(s2, "NONE")) { 06964 hp = ast_gethostbyname(s2, &ahp); 06965 if (!hp) { 06966 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n", chan->cid.cid_num, s2); 06967 return -1; 06968 } 06969 memcpy(&ia, hp->h_addr, sizeof(in_addr_t)); 06970 ast_copy_string(nodeip, ast_inet_ntoa(ia), sizeof(nodeip)); 06971 if (strcmp(hisip, nodeip)) { 06972 char *s3 = strchr(s1, '@'); 06973 if (s3) 06974 s1 = s3 + 1; 06975 s3 = strchr(s1, '/'); 06976 if (s3) 06977 *s3 = 0; 06978 hp = ast_gethostbyname(s1, &ahp); 06979 if (!hp) { 06980 ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n", chan->cid.cid_num, s1); 06981 return -1; 06982 } 06983 memcpy(&ia, hp->h_addr, sizeof(in_addr_t)); 06984 ast_copy_string(nodeip, ast_inet_ntoa(ia), sizeof(nodeip)); 06985 if (strcmp(hisip, nodeip)) { 06986 ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n", chan->cid.cid_num, nodeip, hisip); 06987 return -1; 06988 } 06989 } 06990 } 06991 } 06992 06993 /* if is not a remote */ 06994 if (!myrpt->remote) { 06995 int reconnects = 0; 06996 06997 /* look at callerid to see what node this comes from */ 06998 if (!chan->cid.cid_num) { /* if doesn't have caller id */ 06999 ast_log(LOG_WARNING, "Doesnt have callerid on %s\n", args.node); 07000 return -1; 07001 } 07002 07003 if (!strcmp(myrpt->name, chan->cid.cid_num)) { 07004 ast_log(LOG_WARNING, "Trying to link to self!!\n"); 07005 return -1; 07006 } 07007 rpt_mutex_lock(&myrpt->lock); 07008 l = myrpt->links.next; 07009 /* try to find this one in queue */ 07010 while (l != &myrpt->links) { 07011 if (l->name[0] == '0') { 07012 l = l->next; 07013 continue; 07014 } 07015 /* if found matching string */ 07016 if (!strcmp(l->name, chan->cid.cid_num)) 07017 break; 07018 l = l->next; 07019 } 07020 /* if found */ 07021 if (l != &myrpt->links) { 07022 l->killme = 1; 07023 l->retries = MAX_RETRIES + 1; 07024 l->disced = 2; 07025 reconnects = l->reconnects; 07026 reconnects++; 07027 rpt_mutex_unlock(&myrpt->lock); 07028 usleep(500000); 07029 } else 07030 rpt_mutex_unlock(&myrpt->lock); 07031 /* establish call in tranceive mode */ 07032 l = ast_calloc(1, sizeof(*l)); 07033 if (!l) { 07034 ast_log(LOG_WARNING, "Unable to malloc\n"); 07035 pthread_exit(NULL); 07036 } 07037 l->mode = 1; 07038 ast_copy_string(l->name, chan->cid.cid_num, sizeof(l->name)); 07039 l->isremote = 0; 07040 l->chan = chan; 07041 l->connected = 1; 07042 l->hasconnected = 1; 07043 l->reconnects = reconnects; 07044 l->phonemode = phone_mode; 07045 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR); 07046 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR); 07047 /* allocate a pseudo-channel thru asterisk */ 07048 l->pchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL); 07049 if (!l->pchan) { 07050 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n"); 07051 pthread_exit(NULL); 07052 } 07053 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR); 07054 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR); 07055 /* make a conference for the tx */ 07056 ci.chan = 0; 07057 ci.confno = myrpt->conf; 07058 ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER; 07059 /* first put the channel on the conference in proper mode */ 07060 if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1) { 07061 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 07062 pthread_exit(NULL); 07063 } 07064 rpt_mutex_lock(&myrpt->lock); 07065 if (phone_mode > 1) 07066 l->lastrx = 1; 07067 /* insert at end of queue */ 07068 insque((struct qelem *)l, (struct qelem *)myrpt->links.next); 07069 rpt_mutex_unlock(&myrpt->lock); 07070 if (chan->_state != AST_STATE_UP) { 07071 ast_answer(chan); 07072 } 07073 return 0; 07074 } 07075 rpt_mutex_lock(&myrpt->lock); 07076 /* if remote, error if anyone else already linked */ 07077 if (myrpt->remoteon) { 07078 rpt_mutex_unlock(&myrpt->lock); 07079 usleep(500000); 07080 if (myrpt->remoteon) { 07081 ast_log(LOG_WARNING, "Trying to use busy link on %s\n", args.node); 07082 return -1; 07083 } 07084 rpt_mutex_lock(&myrpt->lock); 07085 } 07086 myrpt->remoteon = 1; 07087 if (ioperm(myrpt->p.iobase, 1, 1) == -1) { 07088 rpt_mutex_unlock(&myrpt->lock); 07089 ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n", myrpt->p.iobase); 07090 return -1; 07091 } 07092 rpt_mutex_unlock(&myrpt->lock); 07093 /* find our index, and load the vars initially */ 07094 for (i = 0; i < nrpts; i++) { 07095 if (&rpt_vars[i] == myrpt) { 07096 load_rpt_vars(i, 0); 07097 break; 07098 } 07099 } 07100 rpt_mutex_lock(&myrpt->lock); 07101 tele = strchr(myrpt->rxchanname, '/'); 07102 if (!tele) { 07103 ast_log(LOG_ERROR, "rpt:Dial number must be in format tech/number\n"); 07104 rpt_mutex_unlock(&myrpt->lock); 07105 pthread_exit(NULL); 07106 } 07107 *tele++ = 0; 07108 myrpt->rxchannel = ast_request(myrpt->rxchanname, AST_FORMAT_SLINEAR, tele, NULL); 07109 if (myrpt->rxchannel) { 07110 ast_set_read_format(myrpt->rxchannel, AST_FORMAT_SLINEAR); 07111 ast_set_write_format(myrpt->rxchannel, AST_FORMAT_SLINEAR); 07112 myrpt->rxchannel->whentohangup = 0; 07113 myrpt->rxchannel->appl = "Apprpt"; 07114 myrpt->rxchannel->data = "(Link Rx)"; 07115 ast_verb(3, "rpt (Rx) initiating call to %s/%s on %s\n", 07116 myrpt->rxchanname, tele, myrpt->rxchannel->name); 07117 rpt_mutex_unlock(&myrpt->lock); 07118 ast_call(myrpt->rxchannel, tele, 999); 07119 rpt_mutex_lock(&myrpt->lock); 07120 } else { 07121 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Rx channel\n"); 07122 rpt_mutex_unlock(&myrpt->lock); 07123 pthread_exit(NULL); 07124 } 07125 *--tele = '/'; 07126 if (myrpt->txchanname) { 07127 tele = strchr(myrpt->txchanname, '/'); 07128 if (!tele) { 07129 ast_log(LOG_ERROR, "rpt:Dial number must be in format tech/number\n"); 07130 rpt_mutex_unlock(&myrpt->lock); 07131 ast_hangup(myrpt->rxchannel); 07132 pthread_exit(NULL); 07133 } 07134 *tele++ = 0; 07135 myrpt->txchannel = ast_request(myrpt->txchanname, AST_FORMAT_SLINEAR, tele, NULL); 07136 if (myrpt->txchannel) { 07137 ast_set_read_format(myrpt->txchannel, AST_FORMAT_SLINEAR); 07138 ast_set_write_format(myrpt->txchannel, AST_FORMAT_SLINEAR); 07139 myrpt->txchannel->whentohangup = 0; 07140 myrpt->txchannel->appl = "Apprpt"; 07141 myrpt->txchannel->data = "(Link Tx)"; 07142 ast_verb(3, "rpt (Tx) initiating call to %s/%s on %s\n", 07143 myrpt->txchanname, tele, myrpt->txchannel->name); 07144 rpt_mutex_unlock(&myrpt->lock); 07145 ast_call(myrpt->txchannel, tele, 999); 07146 rpt_mutex_lock(&myrpt->lock); 07147 } else { 07148 ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n"); 07149 rpt_mutex_unlock(&myrpt->lock); 07150 ast_hangup(myrpt->rxchannel); 07151 pthread_exit(NULL); 07152 } 07153 *--tele = '/'; 07154 } else { 07155 myrpt->txchannel = myrpt->rxchannel; 07156 } 07157 myrpt->remoterx = 0; 07158 myrpt->remotetx = 0; 07159 myrpt->retxtimer = 0; 07160 myrpt->remoteon = 1; 07161 myrpt->dtmfidx = -1; 07162 myrpt->dtmfbuf[0] = 0; 07163 myrpt->dtmf_time_rem = 0; 07164 myrpt->hfscanmode = 0; 07165 myrpt->hfscanstatus = 0; 07166 if (myrpt->p.startupmacro) { 07167 myrpt->remchannel = chan; /* Save copy of channel */ 07168 snprintf(myrpt->macrobuf, sizeof(myrpt->macrobuf), "PPPP%s", myrpt->p.startupmacro); 07169 } 07170 if (myrpt->p.startupgosub) { 07171 myrpt->remchannel = chan; /* Save copy of channel */ 07172 snprintf(myrpt->gosubbuf, sizeof(myrpt->gosubbuf), "PPPP%s", myrpt->p.startupgosub); 07173 } 07174 myrpt->reload = 0; 07175 rpt_mutex_unlock(&myrpt->lock); 07176 setrem(myrpt); 07177 ast_set_write_format(chan, AST_FORMAT_SLINEAR); 07178 ast_set_read_format(chan, AST_FORMAT_SLINEAR); 07179 /* if we are on 2w loop and are a remote, turn EC on */ 07180 if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel)) { 07181 i = 128; 07182 ioctl(myrpt->rxchannel->fds[0], DAHDI_ECHOCANCEL, &i); 07183 } 07184 if (chan->_state != AST_STATE_UP) { 07185 ast_answer(chan); 07186 } 07187 07188 if (ioctl(myrpt->txchannel->fds[0], DAHDI_GET_PARAMS, &par) != -1) { 07189 if (par.rxisoffhook) { 07190 ast_indicate(chan, AST_CONTROL_RADIO_KEY); 07191 myrpt->remoterx = 1; 07192 } 07193 } 07194 n = 0; 07195 cs[n++] = chan; 07196 cs[n++] = myrpt->rxchannel; 07197 if (myrpt->rxchannel != myrpt->txchannel) 07198 cs[n++] = myrpt->txchannel; 07199 for (;;) { 07200 if (ast_check_hangup(chan)) 07201 break; 07202 if (ast_check_hangup(myrpt->rxchannel)) 07203 break; 07204 if (myrpt->reload) { 07205 myrpt->reload = 0; 07206 rpt_mutex_unlock(&myrpt->lock); 07207 /* find our index, and load the vars */ 07208 for (i = 0; i < nrpts; i++) { 07209 if (&rpt_vars[i] == myrpt) { 07210 load_rpt_vars(i, 0); 07211 break; 07212 } 07213 } 07214 rpt_mutex_lock(&myrpt->lock); 07215 } 07216 ms = MSWAIT; 07217 who = ast_waitfor_n(cs, n, &ms); 07218 if (who == NULL) 07219 ms = 0; 07220 elap = MSWAIT - ms; 07221 if (myrpt->macrotimer) 07222 myrpt->macrotimer -= elap; 07223 if (myrpt->macrotimer < 0) 07224 myrpt->macrotimer = 0; 07225 if (myrpt->gosubtimer) 07226 myrpt->gosubtimer -= elap; 07227 if (myrpt->gosubtimer < 0) 07228 myrpt->gosubtimer = 0; 07229 rpt_mutex_unlock(&myrpt->lock); 07230 if (!ms) 07231 continue; 07232 rem_totx = keyed; 07233 07234 07235 if ((!myrpt->remoterx) && (!myrpt->remotetx)) { 07236 if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME) { 07237 myrpt->retxtimer = 0; 07238 ast_indicate(chan, AST_CONTROL_RADIO_UNKEY); 07239 } 07240 } else 07241 myrpt->retxtimer = 0; 07242 if (rem_totx && (!myrpt->remotetx)) { /* Remote base radio TX key */ 07243 myrpt->remotetx = 1; 07244 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_KEY); 07245 } 07246 if ((!rem_totx) && myrpt->remotetx) { /* Remote base radio TX unkey */ 07247 myrpt->remotetx = 0; 07248 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY); 07249 } 07250 07251 if (myrpt->tunerequest && (!strcmp(myrpt->remote, remote_rig_ft897))) { /* ft-897 specific for now... */ 07252 myrpt->tunerequest = 0; 07253 set_mode_ft897(myrpt, REM_MODE_AM); 07254 simple_command_ft897(myrpt, 8); 07255 myrpt->remotetx = 0; 07256 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY); 07257 if (!myrpt->remoterx) 07258 ast_indicate(chan, AST_CONTROL_RADIO_KEY); 07259 if (play_tone(chan, 800, 6000, 8192) == -1) 07260 break; 07261 07262 rmt_telem_finish(myrpt, chan); 07263 set_mode_ft897(myrpt, 0x88); 07264 setrem(myrpt); 07265 } 07266 07267 if (myrpt->hfscanmode) { 07268 myrpt->scantimer -= elap; 07269 if (myrpt->scantimer <= 0) { 07270 myrpt->scantimer = REM_SCANTIME; 07271 service_scan(myrpt); 07272 } 07273 } 07274 if (who == chan) { /* if it was a read from incoming */ 07275 f = ast_read(chan); 07276 if (!f) { 07277 ast_debug(1, "@@@@ link:Hung Up\n"); 07278 break; 07279 } 07280 if (f->frametype == AST_FRAME_VOICE) { 07281 /* if not transmitting, zero-out audio */ 07282 if (!myrpt->remotetx) 07283 memset(f->data, 0, f->datalen); 07284 ast_write(myrpt->txchannel, f); 07285 } 07286 if (f->frametype == AST_FRAME_DTMF) { 07287 myrpt->remchannel = chan; /* Save copy of channel */ 07288 if (handle_remote_phone_dtmf(myrpt, f->subclass, &keyed, phone_mode) == -1) { 07289 ast_debug(1, "@@@@ rpt:Hung Up\n"); 07290 ast_frfree(f); 07291 break; 07292 } 07293 } 07294 if (f->frametype == AST_FRAME_TEXT) { 07295 myrpt->remchannel = chan; /* Save copy of channel */ 07296 if (handle_remote_data(myrpt, f->data) == -1) { 07297 ast_debug(1, "@@@@ rpt:Hung Up\n"); 07298 ast_frfree(f); 07299 break; 07300 } 07301 } 07302 if (f->frametype == AST_FRAME_CONTROL) { 07303 if (f->subclass == AST_CONTROL_HANGUP) { 07304 ast_debug(1, "@@@@ rpt:Hung Up\n"); 07305 ast_frfree(f); 07306 break; 07307 } 07308 /* if RX key */ 07309 if (f->subclass == AST_CONTROL_RADIO_KEY) { 07310 ast_debug(8, "@@@@ rx key\n"); 07311 keyed = 1; 07312 } 07313 /* if RX un-key */ 07314 if (f->subclass == AST_CONTROL_RADIO_UNKEY) { 07315 ast_debug(8, "@@@@ rx un-key\n"); 07316 keyed = 0; 07317 } 07318 } 07319 if (myrpt->hfscanstatus) { 07320 myrpt->remchannel = chan; /* Save copy of channel */ 07321 myrpt->remotetx = 0; 07322 ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY); 07323 if (!myrpt->remoterx) { 07324 ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_KEY); 07325 } 07326 if (myrpt->hfscanstatus < 0) { 07327 if (myrpt->hfscanstatus == -1) { 07328 if (ast_safe_sleep(myrpt->remchannel, 1000) == -1) 07329 break; 07330 } 07331 sayfile(myrpt->remchannel, "rpt/stop"); 07332 } else { 07333 saynum(myrpt->remchannel, myrpt->hfscanstatus ); 07334 } 07335 rmt_telem_finish(myrpt, myrpt->remchannel); 07336 myrpt->hfscanstatus = 0; 07337 } 07338 ast_frfree(f); 07339 rpt_mutex_lock(&myrpt->lock); 07340 c = myrpt->macrobuf[0]; 07341 if (c && (!myrpt->macrotimer)) { 07342 myrpt->macrotimer = MACROTIME; 07343 memmove(myrpt->macrobuf, myrpt->macrobuf + 1, sizeof(myrpt->macrobuf) - 1); 07344 if ((c == 'p') || (c == 'P')) 07345 myrpt->macrotimer = MACROPTIME; 07346 rpt_mutex_unlock(&myrpt->lock); 07347 if (handle_remote_dtmf_digit(myrpt, c, &keyed, 0) == -1) 07348 break; 07349 continue; 07350 } 07351 c = myrpt->gosubbuf[0]; 07352 if (c && (!myrpt->gosubtimer)) { 07353 myrpt->gosubtimer = GOSUBTIME; 07354 memmove(myrpt->gosubbuf, myrpt->gosubbuf + 1, sizeof(myrpt->gosubbuf) - 1); 07355 if ((c == 'p') || (c == 'P')) 07356 myrpt->gosubtimer = GOSUBPTIME; 07357 rpt_mutex_unlock(&myrpt->lock); 07358 if (handle_remote_dtmf_digit(myrpt, c, &keyed, 0) == -1) 07359 break; 07360 continue; 07361 } 07362 rpt_mutex_unlock(&myrpt->lock); 07363 continue; 07364 } 07365 if (who == myrpt->rxchannel) { /* if it was a read from radio */ 07366 f = ast_read(myrpt->rxchannel); 07367 if (!f) { 07368 ast_debug(1, "@@@@ link:Hung Up\n"); 07369 break; 07370 } 07371 if (f->frametype == AST_FRAME_VOICE) { 07372 if ((myrpt->remote) && (myrpt->remotetx)) 07373 memset(f->data, 0, f->datalen); 07374 ast_write(chan, f); 07375 } else if (f->frametype == AST_FRAME_CONTROL) { 07376 if (f->subclass == AST_CONTROL_HANGUP) { 07377 ast_debug(1, "@@@@ rpt:Hung Up\n"); 07378 ast_frfree(f); 07379 break; 07380 } 07381 /* if RX key */ 07382 if (f->subclass == AST_CONTROL_RADIO_KEY) { 07383 ast_debug(8, "@@@@ remote rx key\n"); 07384 if (!myrpt->remotetx) { 07385 ast_indicate(chan, AST_CONTROL_RADIO_KEY); 07386 myrpt->remoterx = 1; 07387 } 07388 } 07389 /* if RX un-key */ 07390 if (f->subclass == AST_CONTROL_RADIO_UNKEY) { 07391 ast_debug(8, "@@@@ remote rx un-key\n"); 07392 if (!myrpt->remotetx) { 07393 ast_indicate(chan, AST_CONTROL_RADIO_UNKEY); 07394 myrpt->remoterx = 0; 07395 } 07396 } 07397 } 07398 ast_frfree(f); 07399 continue; 07400 } 07401 if ((myrpt->rxchannel != myrpt->txchannel) && (who == myrpt->txchannel)) { 07402 /* do this cuz you have to */ 07403 f = ast_read(myrpt->txchannel); 07404 if (!f) { 07405 ast_debug(1, "@@@@ link:Hung Up\n"); 07406 break; 07407 } 07408 if (f->frametype == AST_FRAME_CONTROL) { 07409 if (f->subclass == AST_CONTROL_HANGUP) { 07410 ast_debug(1, "@@@@ rpt:Hung Up\n"); 07411 ast_frfree(f); 07412 break; 07413 } 07414 } 07415 ast_frfree(f); 07416 continue; 07417 } 07418 07419 } 07420 rpt_mutex_lock(&myrpt->lock); 07421 if (myrpt->rxchannel != myrpt->txchannel) 07422 ast_hangup(myrpt->txchannel); 07423 ast_hangup(myrpt->rxchannel); 07424 myrpt->hfscanmode = 0; 07425 myrpt->hfscanstatus = 0; 07426 myrpt->remoteon = 0; 07427 rpt_mutex_unlock(&myrpt->lock); 07428 closerem(myrpt); 07429 return res; 07430 }
static void* rpt_master | ( | void * | config | ) | [static] |
Definition at line 6706 of file app_rpt.c.
References ast_category_browse(), ast_cli_command(), ast_config_destroy(), ast_copy_string(), ast_log(), ast_mutex_init(), ast_pthread_create_detached, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_strdup, ast_variable_retrieve(), rpt::cfg, rpt::ident, rpt::lastthreadrestarttime, load_rpt_vars(), lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, name, rpt::name, rpt_tele::next, rpt::offset, rpt::powerlevel, rpt_tele::prev, REM_MEDPWR, REM_MODE_FM, REM_SIMPLEX, rpt::remmode, rpt::remote, rpt::rpt_thread, rpt_vars, rpt::rxchanname, rpt::tailmessagen, rpt::tele, rpt::threadrestarts, and rpt::txchanname.
Referenced by load_module().
06707 { 06708 int i, n; 06709 struct ast_config *cfg; 06710 char *this; 06711 const char *val; 06712 06713 /* go thru all the specified repeaters */ 06714 this = NULL; 06715 n = 0; 06716 rpt_vars[n].cfg = config; 06717 cfg = rpt_vars[n].cfg; 06718 if (!cfg) { 06719 ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n"); 06720 pthread_exit(NULL); 06721 } 06722 while ((this = ast_category_browse(cfg, this)) != NULL) { 06723 for (i = 0; i < strlen(this); i++) { 06724 if ((this[i] < '0') || (this[i] > '9')) 06725 break; 06726 } 06727 if (i != strlen(this)) 06728 continue; /* Not a node defn */ 06729 memset(&rpt_vars[n], 0, sizeof(rpt_vars[n])); 06730 rpt_vars[n].name = ast_strdup(this); 06731 val = ast_variable_retrieve(cfg, this, "rxchannel"); 06732 if (val) 06733 rpt_vars[n].rxchanname = ast_strdup(val); 06734 val = ast_variable_retrieve(cfg, this, "txchannel"); 06735 if (val) 06736 rpt_vars[n].txchanname = ast_strdup(val); 06737 val = ast_variable_retrieve(cfg, this, "remote"); 06738 if (val) 06739 rpt_vars[n].remote = ast_strdup(val); 06740 ast_mutex_init(&rpt_vars[n].lock); 06741 rpt_vars[n].tele.next = &rpt_vars[n].tele; 06742 rpt_vars[n].tele.prev = &rpt_vars[n].tele; 06743 rpt_vars[n].rpt_thread = AST_PTHREADT_NULL; 06744 rpt_vars[n].tailmessagen = 0; 06745 #ifdef _MDC_DECODE_H_ 06746 rpt_vars[n].mdc = mdc_decoder_new(8000); 06747 #endif 06748 n++; 06749 } 06750 nrpts = n; 06751 ast_config_destroy(cfg); 06752 06753 /* start em all */ 06754 for (i = 0; i < n; i++) { 06755 load_rpt_vars(i, 1); 06756 06757 /* if is a remote, dont start one for it */ 06758 if (rpt_vars[i].remote) { 06759 ast_copy_string(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq)); 06760 ast_copy_string(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl)); 06761 ast_copy_string(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl)); 06762 rpt_vars[i].remmode = REM_MODE_FM; 06763 rpt_vars[i].offset = REM_SIMPLEX; 06764 rpt_vars[i].powerlevel = REM_MEDPWR; 06765 continue; 06766 } 06767 if (!rpt_vars[i].p.ident) { 06768 ast_log(LOG_WARNING, "Did not specify ident for node %s\n", rpt_vars[i].name); 06769 ast_config_destroy(cfg); 06770 pthread_exit(NULL); 06771 } 06772 ast_pthread_create_detached(&rpt_vars[i].rpt_thread, NULL, rpt, (void *) &rpt_vars[i]); 06773 } 06774 usleep(500000); 06775 for (;;) { 06776 /* Now monitor each thread, and restart it if necessary */ 06777 for (i = 0; i < n; i++) { 06778 int rv; 06779 if (rpt_vars[i].remote) 06780 continue; 06781 if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP) 06782 rv = -1; 06783 else 06784 rv = pthread_kill(rpt_vars[i].rpt_thread, 0); 06785 if (rv) { 06786 if (time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15) { 06787 if (rpt_vars[i].threadrestarts >= 5) { 06788 ast_log(LOG_ERROR, "Continual RPT thread restarts, killing Asterisk\n"); 06789 ast_cli_command(STDERR_FILENO, "restart now"); 06790 } else { 06791 ast_log(LOG_NOTICE, "RPT thread restarted on %s\n", rpt_vars[i].name); 06792 rpt_vars[i].threadrestarts++; 06793 } 06794 } else 06795 rpt_vars[i].threadrestarts = 0; 06796 06797 rpt_vars[i].lastthreadrestarttime = time(NULL); 06798 ast_pthread_create_detached(&rpt_vars[i].rpt_thread, NULL, rpt, (void *) &rpt_vars[i]); 06799 ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name); 06800 } 06801 06802 } 06803 sleep(2); 06804 } 06805 ast_config_destroy(cfg); 06806 pthread_exit(NULL); 06807 }
static void* rpt_tele_thread | ( | void * | this | ) | [static] |
Definition at line 1893 of file app_rpt.c.
References ARB_ALPHA, AST_FORMAT_SLINEAR, ast_free, ast_hangup(), ast_localtime(), ast_log(), ast_malloc, 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_tvnow(), ast_variable_retrieve(), ast_waitstream(), rpt::callmode, rpt::cfg, rpt_tele::chan, rpt::cmdnode, COMPLETE, rpt::conf, CONNECTED, rpt_link::connected, CONNFAIL, rpt::dailykerchunks, DLY_CALLTERM, DLY_ID, DLY_TELEM, DLY_UNKEY, ast_channel::fds, get_wait_interval(), GOSUB_BUSY, GOSUB_NOTFOUND, ID, ID1, rpt::ident, IDTALKOVER, rpt_link::isremote, rpt::keyed, ast_channel::language, LASTNODEKEY, rpt::lastnodewhichkeyedusup, rpt::links, rpt::lock, LOG_NOTICE, LOG_WARNING, MACRO_BUSY, MACRO_NOTFOUND, rpt_link::mode, rpt_tele::mode, rpt_tele::mylink, ast_channel::name, rpt_link::name, rpt::name, rpt_link::next, rpt_tele::next, rpt::p, rpt_tele::param, rpt::patchnoct, rpt_link::prev, PROC, REMALREADY, REMDISC, REMGO, REMNOTFOUND, REV_PATCH, rpt_tele::rpt, rpt_mutex_lock, rpt_mutex_unlock, saycharstr(), sayfile(), STATS_TIME, STATS_VERSION, STATUS, rpt::stopgen, strsep(), rpt::tailmessagen, rpt::tailmsg, TAILMSG, rpt::tailsquashedtime, rpt::tele, telem_any(), telem_lookup(), TERM, TEST_TONE, TIMEOUT, ast_tm::tm_hour, rpt::tmsgtimer, rpt::totalkerchunks, rpt::txconf, UNKEY, rpt::unkeytocttimer, and wait_interval().
Referenced by rpt_telemetry().
01894 { 01895 struct dahdi_confinfo ci; /* conference info */ 01896 int res = 0, haslink, hastx, hasremote, imdone = 0, unkeys_queued, x; 01897 struct rpt_tele *mytele = (struct rpt_tele *)this; 01898 struct rpt_tele *tlist; 01899 struct rpt *myrpt; 01900 struct rpt_link *l, *m, linkbase; 01901 struct ast_channel *mychannel; 01902 const char *p, *ct; 01903 struct timeval tv; 01904 struct ast_tm localtm; 01905 #ifdef APP_RPT_LOCK_DEBUG 01906 struct lockthread *t; 01907 #endif 01908 01909 /* get a pointer to myrpt */ 01910 myrpt = mytele->rpt; 01911 01912 /* Snag copies of a few key myrpt variables */ 01913 rpt_mutex_lock(&myrpt->lock); 01914 rpt_mutex_unlock(&myrpt->lock); 01915 01916 /* allocate a pseudo-channel thru asterisk */ 01917 mychannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL); 01918 if (!mychannel) { 01919 ast_log(LOG_WARNING, "rpt: unable to obtain pseudo channel\n"); 01920 rpt_mutex_lock(&myrpt->lock); 01921 remque((struct qelem *)mytele); 01922 ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/ 01923 rpt_mutex_unlock(&myrpt->lock); 01924 ast_free(mytele); 01925 pthread_exit(NULL); 01926 } 01927 rpt_mutex_lock(&myrpt->lock); 01928 mytele->chan = mychannel; /* Save a copy of the channel so we can access it externally if need be */ 01929 rpt_mutex_unlock(&myrpt->lock); 01930 01931 /* make a conference for the tx */ 01932 ci.chan = 0; 01933 /* If there's an ID queued, or tail message queued, */ 01934 /* only connect the ID audio to the local tx conference so */ 01935 /* linked systems can't hear it */ 01936 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) || 01937 (mytele->mode == TAILMSG)) ? 01938 myrpt->txconf : myrpt->conf); 01939 ci.confmode = DAHDI_CONF_CONFANN; 01940 /* first put the channel on the conference in announce mode */ 01941 if (ioctl(mychannel->fds[0], DAHDI_SETCONF, &ci) == -1) { 01942 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 01943 rpt_mutex_lock(&myrpt->lock); 01944 remque((struct qelem *)mytele); 01945 rpt_mutex_unlock(&myrpt->lock); 01946 ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/ 01947 ast_free(mytele); 01948 ast_hangup(mychannel); 01949 pthread_exit(NULL); 01950 } 01951 ast_stopstream(mychannel); 01952 switch (mytele->mode) { 01953 case ID: 01954 case ID1: 01955 /* wait a bit */ 01956 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM, mychannel); 01957 res = telem_any(myrpt, mychannel, myrpt->p.ident); 01958 imdone=1; 01959 break; 01960 01961 case TAILMSG: 01962 res = ast_streamfile(mychannel, myrpt->p.tailmsg.msgs[myrpt->tailmessagen], mychannel->language); 01963 break; 01964 01965 case IDTALKOVER: 01966 p = ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover"); 01967 if (p) 01968 res = telem_any(myrpt, mychannel, p); 01969 imdone = 1; 01970 break; 01971 case PROC: 01972 /* wait a little bit longer */ 01973 wait_interval(myrpt, DLY_TELEM, mychannel); 01974 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup"); 01975 if (res < 0) { /* Then default message */ 01976 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language); 01977 } 01978 break; 01979 case TERM: 01980 /* wait a little bit longer */ 01981 wait_interval(myrpt, DLY_CALLTERM, mychannel); 01982 res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown"); 01983 if (res < 0) { /* Then default message */ 01984 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language); 01985 } 01986 break; 01987 case COMPLETE: 01988 /* wait a little bit */ 01989 wait_interval(myrpt, DLY_TELEM, mychannel); 01990 res = telem_lookup(myrpt, mychannel, myrpt->name, "functcomplete"); 01991 break; 01992 case MACRO_NOTFOUND: 01993 /* wait a little bit */ 01994 wait_interval(myrpt, DLY_TELEM, mychannel); 01995 res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language); 01996 break; 01997 case GOSUB_NOTFOUND: 01998 /* wait a little bit */ 01999 wait_interval(myrpt, DLY_TELEM, mychannel); 02000 res = ast_streamfile(mychannel, "rpt/gosub_notfound", mychannel->language); 02001 break; 02002 case MACRO_BUSY: 02003 /* wait a little bit */ 02004 wait_interval(myrpt, DLY_TELEM, mychannel); 02005 res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language); 02006 break; 02007 case GOSUB_BUSY: 02008 /* wait a little bit */ 02009 wait_interval(myrpt, DLY_TELEM, mychannel); 02010 res = ast_streamfile(mychannel, "rpt/gosub_busy", mychannel->language); 02011 break; 02012 case UNKEY: 02013 if (myrpt->patchnoct && myrpt->callmode) { /* If no CT during patch configured, then don't send one */ 02014 imdone = 1; 02015 break; 02016 } 02017 02018 /* 02019 * Reset the Unkey to CT timer 02020 */ 02021 02022 x = get_wait_interval(myrpt, DLY_UNKEY); 02023 rpt_mutex_lock(&myrpt->lock); 02024 myrpt->unkeytocttimer = x; /* Must be protected as it is changed below */ 02025 rpt_mutex_unlock(&myrpt->lock); 02026 02027 /* 02028 * If there's one already queued, don't do another 02029 */ 02030 02031 tlist = myrpt->tele.next; 02032 unkeys_queued = 0; 02033 if (tlist != &myrpt->tele) { 02034 rpt_mutex_lock(&myrpt->lock); 02035 while (tlist != &myrpt->tele) { 02036 if (tlist->mode == UNKEY) 02037 unkeys_queued++; 02038 tlist = tlist->next; 02039 } 02040 rpt_mutex_unlock(&myrpt->lock); 02041 } 02042 if (unkeys_queued > 1) { 02043 imdone = 1; 02044 break; 02045 } 02046 02047 /* Wait for the telemetry timer to expire */ 02048 /* Periodically check the timer since it can be re-initialized above */ 02049 while (myrpt->unkeytocttimer) { 02050 int ctint; 02051 if (myrpt->unkeytocttimer > 100) 02052 ctint = 100; 02053 else 02054 ctint = myrpt->unkeytocttimer; 02055 ast_safe_sleep(mychannel, ctint); 02056 rpt_mutex_lock(&myrpt->lock); 02057 if (myrpt->unkeytocttimer < ctint) 02058 myrpt->unkeytocttimer = 0; 02059 else 02060 myrpt->unkeytocttimer -= ctint; 02061 rpt_mutex_unlock(&myrpt->lock); 02062 } 02063 02064 /* 02065 * Now, the carrier on the rptr rx should be gone. 02066 * If it re-appeared, then forget about sending the CT 02067 */ 02068 if (myrpt->keyed) { 02069 imdone = 1; 02070 break; 02071 } 02072 02073 rpt_mutex_lock(&myrpt->lock); /* Update the kerchunk counters */ 02074 myrpt->dailykerchunks++; 02075 myrpt->totalkerchunks++; 02076 rpt_mutex_unlock(&myrpt->lock); 02077 02078 haslink = 0; 02079 hastx = 0; 02080 hasremote = 0; 02081 l = myrpt->links.next; 02082 if (l != &myrpt->links) { 02083 rpt_mutex_lock(&myrpt->lock); 02084 while (l != &myrpt->links) { 02085 if (l->name[0] == '0') { 02086 l = l->next; 02087 continue; 02088 } 02089 haslink = 1; 02090 if (l->mode) { 02091 hastx++; 02092 if (l->isremote) 02093 hasremote++; 02094 } 02095 l = l->next; 02096 } 02097 rpt_mutex_unlock(&myrpt->lock); 02098 } 02099 if (haslink) { 02100 res = telem_lookup(myrpt, mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx"); 02101 if (res) 02102 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name); 02103 02104 /* if in remote cmd mode, indicate it */ 02105 if (myrpt->cmdnode[0]) { 02106 ast_safe_sleep(mychannel, 200); 02107 res = telem_lookup(myrpt, mychannel, myrpt->name, "cmdmode"); 02108 if (res) 02109 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name); 02110 ast_stopstream(mychannel); 02111 } 02112 } else if ((ct = ast_variable_retrieve(myrpt->cfg, myrpt->name, "unlinkedct"))) { /* Unlinked Courtesy Tone */ 02113 res = telem_lookup(myrpt, mychannel, myrpt->name, ct); 02114 if (res) 02115 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name); 02116 } 02117 if (hasremote && (!myrpt->cmdnode[0])) { 02118 /* set for all to hear */ 02119 ci.chan = 0; 02120 ci.confno = myrpt->conf; 02121 ci.confmode = DAHDI_CONF_CONFANN; 02122 /* first put the channel on the conference in announce mode */ 02123 if (ioctl(mychannel->fds[0], DAHDI_SETCONF, &ci) == -1) { 02124 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 02125 rpt_mutex_lock(&myrpt->lock); 02126 remque((struct qelem *)mytele); 02127 rpt_mutex_unlock(&myrpt->lock); 02128 ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/ 02129 ast_free(mytele); 02130 ast_hangup(mychannel); 02131 pthread_exit(NULL); 02132 } 02133 if ((ct = ast_variable_retrieve(myrpt->cfg, myrpt->name, "remotect"))) { /* Unlinked Courtesy Tone */ 02134 ast_safe_sleep(mychannel, 200); 02135 res = telem_lookup(myrpt, mychannel, myrpt->name, ct); 02136 if (res) 02137 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name); 02138 } 02139 } 02140 #ifdef _MDC_DECODE_H_ 02141 if (myrpt->lastunit) { 02142 char mystr[10]; 02143 02144 ast_safe_sleep(mychannel, 200); 02145 /* set for all to hear */ 02146 ci.chan = 0; 02147 ci.confno = myrpt->txconf; 02148 ci.confmode = DAHDI_CONF_CONFANN; 02149 /* first put the channel on the conference in announce mode */ 02150 if (ioctl(mychannel->fds[0], DAHDI_SETCONF, &ci) == -1) { 02151 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); 02152 rpt_mutex_lock(&myrpt->lock); 02153 remque((struct qelem *)mytele); 02154 rpt_mutex_unlock(&myrpt->lock); 02155 ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/ 02156 ast_free(mytele); 02157 ast_hangup(mychannel); 02158 pthread_exit(NULL); 02159 } 02160 snprintf(mystr, sizeof(mystr), "%04x", myrpt->lastunit); 02161 myrpt->lastunit = 0; 02162 ast_say_character_str(mychannel, mystr, NULL, mychannel->language); 02163 break; 02164 } 02165 #endif 02166 imdone = 1; 02167 break; 02168 case REMDISC: 02169 /* wait a little bit */ 02170 wait_interval(myrpt, DLY_TELEM, mychannel); 02171 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 02172 if (!res) 02173 res = ast_waitstream(mychannel, ""); 02174 else 02175 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02176 ast_stopstream(mychannel); 02177 ast_say_character_str(mychannel, mytele->mylink.name, NULL, mychannel->language); 02178 res = ast_streamfile(mychannel, ((mytele->mylink.connected) ? 02179 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language); 02180 break; 02181 case REMALREADY: 02182 /* wait a little bit */ 02183 wait_interval(myrpt, DLY_TELEM, mychannel); 02184 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language); 02185 break; 02186 case REMNOTFOUND: 02187 /* wait a little bit */ 02188 wait_interval(myrpt, DLY_TELEM, mychannel); 02189 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language); 02190 break; 02191 case REMGO: 02192 /* wait a little bit */ 02193 wait_interval(myrpt, DLY_TELEM, mychannel); 02194 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language); 02195 break; 02196 case CONNECTED: 02197 /* wait a little bit */ 02198 wait_interval(myrpt, DLY_TELEM, mychannel); 02199 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 02200 if (!res) 02201 res = ast_waitstream(mychannel, ""); 02202 else 02203 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02204 ast_stopstream(mychannel); 02205 ast_say_character_str(mychannel, mytele->mylink.name, NULL, mychannel->language); 02206 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language); 02207 break; 02208 case CONNFAIL: 02209 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 02210 if (!res) 02211 res = ast_waitstream(mychannel, ""); 02212 else 02213 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02214 ast_stopstream(mychannel); 02215 ast_say_character_str(mychannel, mytele->mylink.name, NULL, mychannel->language); 02216 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language); 02217 break; 02218 case STATUS: 02219 /* wait a little bit */ 02220 wait_interval(myrpt, DLY_TELEM, mychannel); 02221 hastx = 0; 02222 linkbase.next = &linkbase; 02223 linkbase.prev = &linkbase; 02224 rpt_mutex_lock(&myrpt->lock); 02225 /* make our own list of links */ 02226 l = myrpt->links.next; 02227 while (l != &myrpt->links) { 02228 if (l->name[0] == '0') { 02229 l = l->next; 02230 continue; 02231 } 02232 m = ast_malloc(sizeof(*m)); 02233 if (!m) { 02234 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name); 02235 remque((struct qelem *)mytele); 02236 rpt_mutex_unlock(&myrpt->lock); 02237 ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/ 02238 ast_free(mytele); 02239 ast_hangup(mychannel); 02240 pthread_exit(NULL); 02241 } 02242 memcpy(m, l, sizeof(struct rpt_link)); 02243 m->next = m->prev = NULL; 02244 insque((struct qelem *)m, (struct qelem *)linkbase.next); 02245 l = l->next; 02246 } 02247 rpt_mutex_unlock(&myrpt->lock); 02248 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 02249 if (!res) 02250 res = ast_waitstream(mychannel, ""); 02251 else 02252 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02253 ast_stopstream(mychannel); 02254 ast_say_character_str(mychannel, myrpt->name, NULL, mychannel->language); 02255 if (!res) 02256 res = ast_waitstream(mychannel, ""); 02257 else 02258 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02259 ast_stopstream(mychannel); 02260 if (myrpt->callmode) { 02261 hastx = 1; 02262 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language); 02263 if (!res) 02264 res = ast_waitstream(mychannel, ""); 02265 else 02266 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02267 ast_stopstream(mychannel); 02268 } 02269 l = linkbase.next; 02270 while (l != &linkbase) { 02271 hastx = 1; 02272 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 02273 if (!res) 02274 res = ast_waitstream(mychannel, ""); 02275 else 02276 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02277 ast_stopstream(mychannel); 02278 ast_say_character_str(mychannel, l->name, NULL, mychannel->language); 02279 if (!res) 02280 res = ast_waitstream(mychannel, ""); 02281 else 02282 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02283 ast_stopstream(mychannel); 02284 res = ast_streamfile(mychannel, ((l->mode) ? 02285 "rpt/tranceive" : "rpt/monitor"), mychannel->language); 02286 if (!res) 02287 res = ast_waitstream(mychannel, ""); 02288 else 02289 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02290 ast_stopstream(mychannel); 02291 l = l->next; 02292 } 02293 if (!hastx) { 02294 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language); 02295 if (!res) 02296 res = ast_waitstream(mychannel, ""); 02297 else 02298 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02299 ast_stopstream(mychannel); 02300 } 02301 /* destroy our local link queue */ 02302 l = linkbase.next; 02303 while (l != &linkbase) { 02304 m = l; 02305 l = l->next; 02306 remque((struct qelem *)m); 02307 ast_free(m); 02308 } 02309 imdone = 1; 02310 break; 02311 02312 case LASTNODEKEY: /* Identify last node which keyed us up */ 02313 rpt_mutex_lock(&myrpt->lock); 02314 if (myrpt->lastnodewhichkeyedusup) 02315 p = ast_strdupa(myrpt->lastnodewhichkeyedusup); /* Make a local copy of the node name */ 02316 else 02317 p = NULL; 02318 rpt_mutex_unlock(&myrpt->lock); 02319 if (!p) { 02320 imdone = 1; /* no node previously keyed us up, or the node which did has been disconnected */ 02321 break; 02322 } 02323 wait_interval(myrpt, DLY_TELEM, mychannel); 02324 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 02325 if (!res) 02326 res = ast_waitstream(mychannel, ""); 02327 else 02328 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02329 ast_stopstream(mychannel); 02330 ast_say_character_str(mychannel, p, NULL, mychannel->language); 02331 if (!res) 02332 res = ast_waitstream(mychannel, ""); 02333 else 02334 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02335 ast_stopstream(mychannel); 02336 imdone = 1; 02337 break; 02338 02339 case TIMEOUT: 02340 res = ast_streamfile(mychannel, "rpt/node", mychannel->language); 02341 if (!res) 02342 res = ast_waitstream(mychannel, ""); 02343 else 02344 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02345 ast_stopstream(mychannel); 02346 ast_say_character_str(mychannel, myrpt->name, NULL, mychannel->language); 02347 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language); 02348 break; 02349 02350 case STATS_TIME: 02351 wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */ 02352 tv = ast_tvnow(); 02353 ast_localtime(&tv, &localtm, NULL); 02354 /* Say the phase of the day is before the time */ 02355 if ((localtm.tm_hour >= 0) && (localtm.tm_hour < 12)) 02356 p = "rpt/goodmorning"; 02357 else if ((localtm.tm_hour >= 12) && (localtm.tm_hour < 18)) 02358 p = "rpt/goodafternoon"; 02359 else 02360 p = "rpt/goodevening"; 02361 if (sayfile(mychannel, p) == -1) { 02362 imdone = 1; 02363 break; 02364 } 02365 /* Say the time is ... */ 02366 if (sayfile(mychannel, "rpt/thetimeis") == -1) { 02367 imdone = 1; 02368 break; 02369 } 02370 /* Say the time */ 02371 res = ast_say_time(mychannel, tv.tv_sec, "", mychannel->language); 02372 if (!res) 02373 res = ast_waitstream(mychannel, ""); 02374 ast_stopstream(mychannel); 02375 imdone = 1; 02376 break; 02377 case STATS_VERSION: 02378 wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */ 02379 /* Say "version" */ 02380 if (sayfile(mychannel, "rpt/version") == -1) { 02381 imdone = 1; 02382 break; 02383 } 02384 if (!res) /* Say "X" */ 02385 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL); 02386 if (!res) 02387 res = ast_waitstream(mychannel, ""); 02388 ast_stopstream(mychannel); 02389 if (saycharstr(mychannel, ".") == -1) { 02390 imdone = 1; 02391 break; 02392 } 02393 if (!res) /* Say "Y" */ 02394 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL); 02395 if (!res) { 02396 res = ast_waitstream(mychannel, ""); 02397 ast_stopstream(mychannel); 02398 } else 02399 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02400 imdone = 1; 02401 break; 02402 case ARB_ALPHA: 02403 wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */ 02404 if (mytele->param) 02405 saycharstr(mychannel, mytele->param); 02406 imdone = 1; 02407 break; 02408 case REV_PATCH: 02409 wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */ 02410 if (mytele->param) { 02411 /* Parts of this section taken from app_parkandannounce */ 02412 char *tpl_working, *tpl_current; 02413 char *tmp[100], *myparm; 02414 int looptemp=0, i = 0, dres = 0; 02415 02416 tpl_working = ast_strdupa(mytele->param); 02417 myparm = strsep(&tpl_working, ","); 02418 tpl_current = strsep(&tpl_working, ":"); 02419 02420 while (tpl_current && looptemp < sizeof(tmp)) { 02421 tmp[looptemp] = tpl_current; 02422 looptemp++; 02423 tpl_current = strsep(&tpl_working, ":"); 02424 } 02425 02426 for (i = 0; i < looptemp; i++) { 02427 if (!strcmp(tmp[i], "PARKED")) { 02428 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language); 02429 } else if (!strcmp(tmp[i], "NODE")) { 02430 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language); 02431 } else { 02432 dres = ast_streamfile(mychannel, tmp[i], mychannel->language); 02433 if (!dres) { 02434 dres = ast_waitstream(mychannel, ""); 02435 } else { 02436 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name); 02437 dres = 0; 02438 } 02439 } 02440 } 02441 } 02442 imdone = 1; 02443 break; 02444 case TEST_TONE: 02445 imdone = 1; 02446 myrpt->stopgen = 0; 02447 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0))) 02448 break; 02449 while (mychannel->generatordata && (!myrpt->stopgen)) { 02450 if (ast_safe_sleep(mychannel, 1)) break; 02451 imdone = 1; 02452 } 02453 break; 02454 default: 02455 break; 02456 } 02457 02458 myrpt->stopgen = 0; 02459 if (!imdone) { 02460 if (!res) 02461 res = ast_waitstream(mychannel, ""); 02462 else { 02463 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 02464 res = 0; 02465 } 02466 } 02467 ast_stopstream(mychannel); 02468 rpt_mutex_lock(&myrpt->lock); 02469 if (mytele->mode == TAILMSG) { 02470 if (!res) { 02471 myrpt->tailmessagen++; 02472 if (myrpt->tailmessagen >= myrpt->p.tailmsg.argc) 02473 myrpt->tailmessagen = 0; 02474 } else { 02475 myrpt->tmsgtimer = myrpt->p.tailsquashedtime; 02476 } 02477 } 02478 remque((struct qelem *)mytele); 02479 rpt_mutex_unlock(&myrpt->lock); 02480 ast_free(mytele); 02481 ast_hangup(mychannel); 02482 #ifdef APP_RPT_LOCK_DEBUG 02483 sleep(5); 02484 ast_mutex_lock(&locklock); 02485 t = get_lockthread(pthread_self()); 02486 if (t) 02487 memset(t, 0, sizeof(struct lockthread)); 02488 ast_mutex_unlock(&locklock); 02489 #endif 02490 pthread_exit(NULL); 02491 }
static void rpt_telemetry | ( | struct rpt * | myrpt, | |
int | mode, | |||
void * | data | |||
) | [static] |
Definition at line 2493 of file app_rpt.c.
References ARB_ALPHA, ast_calloc, ast_copy_string(), ast_log(), ast_pthread_create_detached, CONNECTED, CONNFAIL, rpt::lock, LOG_WARNING, rpt_tele::next, REMDISC, REV_PATCH, rpt_mutex_lock, rpt_mutex_unlock, rpt_tele_thread(), and rpt::tele.
Referenced by function_autopatchdn(), function_cop(), function_gosub(), function_ilink(), function_macro(), function_status(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), queue_id(), rpt(), and rpt_call().
02494 { 02495 struct rpt_tele *tele; 02496 struct rpt_link *mylink = (struct rpt_link *) data; 02497 int res; 02498 02499 tele = ast_calloc(1, sizeof(*tele)); 02500 if (!tele) { 02501 ast_log(LOG_WARNING, "Unable to allocate memory\n"); 02502 pthread_exit(NULL); 02503 } 02504 tele->rpt = myrpt; 02505 tele->mode = mode; 02506 rpt_mutex_lock(&myrpt->lock); 02507 if ((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED)) { 02508 if (mylink) { 02509 memcpy(&tele->mylink, mylink, sizeof(struct rpt_link)); 02510 } 02511 } else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) { 02512 ast_copy_string(tele->param, (char *) data, sizeof(tele->param)); 02513 } 02514 insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next); 02515 rpt_mutex_unlock(&myrpt->lock); 02516 res = ast_pthread_create_detached(&tele->threadid, NULL, rpt_tele_thread, (void *) tele); 02517 if (res != 0) { 02518 rpt_mutex_lock(&myrpt->lock); 02519 remque((struct qlem *) tele); /* We don't like stuck transmitters, remove it from the queue */ 02520 rpt_mutex_unlock(&myrpt->lock); 02521 ast_log(LOG_WARNING, "Could not create telemetry thread: %s\n", strerror(res)); 02522 } 02523 return; 02524 }
static int saycharstr | ( | struct ast_channel * | mychannel, | |
char * | str | |||
) | [static] |
Definition at line 1719 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().
01720 { 01721 int res; 01722 01723 res = ast_say_character_str(mychannel, str, NULL, mychannel->language); 01724 if (!res) 01725 res = ast_waitstream(mychannel, ""); 01726 else 01727 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01728 ast_stopstream(mychannel); 01729 return res; 01730 }
static int saydigits | ( | struct ast_channel * | mychannel, | |
int | num | |||
) | [static] |
Definition at line 1744 of file app_rpt.c.
References ast_log(), ast_say_digits(), ast_stopstream(), ast_waitstream(), ast_channel::language, LOG_WARNING, and ast_channel::name.
Referenced by function_remote().
01745 { 01746 int res; 01747 res = ast_say_digits(mychannel, num, NULL, mychannel->language); 01748 if (!res) 01749 res = ast_waitstream(mychannel, ""); 01750 else 01751 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01752 ast_stopstream(mychannel); 01753 return res; 01754 }
static int sayfile | ( | struct ast_channel * | mychannel, | |
const char * | fname | |||
) | [static] |
Definition at line 1706 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().
01707 { 01708 int res; 01709 01710 res = ast_streamfile(mychannel, fname, mychannel->language); 01711 if (!res) 01712 res = ast_waitstream(mychannel, ""); 01713 else 01714 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01715 ast_stopstream(mychannel); 01716 return res; 01717 }
static int saynum | ( | struct ast_channel * | mychannel, | |
int | num | |||
) | [static] |
Definition at line 1732 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().
01733 { 01734 int res; 01735 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL); 01736 if (!res) 01737 res = ast_waitstream(mychannel, ""); 01738 else 01739 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); 01740 ast_stopstream(mychannel); 01741 return res; 01742 }
static void send_link_dtmf | ( | struct rpt * | myrpt, | |
char | c | |||
) | [static] |
Definition at line 2756 of file app_rpt.c.
References AST_FRAME_TEXT, ast_strdup, 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, str, and ast_frame::subclass.
Referenced by handle_link_phone_dtmf(), and local_dtmf_helper().
02757 { 02758 char str[300]; 02759 struct ast_frame wf; 02760 struct rpt_link *l; 02761 02762 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c); 02763 wf.frametype = AST_FRAME_TEXT; 02764 wf.subclass = 0; 02765 wf.offset = 0; 02766 wf.mallocd = 1; 02767 wf.datalen = strlen(str) + 1; 02768 wf.samples = 0; 02769 l = myrpt->links.next; 02770 /* first, see if our dude is there */ 02771 while (l != &myrpt->links) { 02772 if (l->name[0] == '0') { 02773 l = l->next; 02774 continue; 02775 } 02776 /* if we found it, write it and were done */ 02777 if (!strcmp(l->name, myrpt->cmdnode)) { 02778 wf.data = ast_strdup(str); 02779 if (l->chan) 02780 ast_write(l->chan, &wf); 02781 return; 02782 } 02783 l = l->next; 02784 } 02785 l = myrpt->links.next; 02786 /* if not, give it to everyone */ 02787 while (l != &myrpt->links) { 02788 wf.data = ast_strdup(str); 02789 if (l->chan) 02790 ast_write(l->chan, &wf); 02791 l = l->next; 02792 } 02793 return; 02794 }
static int send_morse | ( | struct ast_channel * | chan, | |
const char * | string, | |||
int | speed, | |||
int | freq, | |||
int | amplitude | |||
) | [static] |
Definition at line 1494 of file app_rpt.c.
References ast_safe_sleep(), ast_stopstream(), ast_waitstream(), chan, morse_bits::ddcomb, ast_channel::fds, morse_bits::len, play_silence(), and play_tone().
Referenced by telem_any().
01495 { 01496 01497 static struct morse_bits mbits[] = { 01498 {0, 0}, /* SPACE */ 01499 {0, 0}, 01500 {6, 18},/* " */ 01501 {0, 0}, 01502 {7, 72},/* $ */ 01503 {0, 0}, 01504 {0, 0}, 01505 {6, 30},/* ' */ 01506 {5, 13},/* ( */ 01507 {6, 29},/* ) */ 01508 {0, 0}, 01509 {5, 10},/* + */ 01510 {6, 51},/* , */ 01511 {6, 33},/* - */ 01512 {6, 42},/* . */ 01513 {5, 9}, /* / */ 01514 {5, 31},/* 0 */ 01515 {5, 30},/* 1 */ 01516 {5, 28},/* 2 */ 01517 {5, 24},/* 3 */ 01518 {5, 16},/* 4 */ 01519 {5, 0}, /* 5 */ 01520 {5, 1}, /* 6 */ 01521 {5, 3}, /* 7 */ 01522 {5, 7}, /* 8 */ 01523 {5, 15},/* 9 */ 01524 {6, 7}, /* : */ 01525 {6, 21},/* ; */ 01526 {0, 0}, 01527 {5, 33},/* = */ 01528 {0, 0}, 01529 {6, 12},/* ? */ 01530 {0, 0}, 01531 {2, 2}, /* A */ 01532 {4, 1}, /* B */ 01533 {4, 5}, /* C */ 01534 {3, 1}, /* D */ 01535 {1, 0}, /* E */ 01536 {4, 4}, /* F */ 01537 {3, 3}, /* G */ 01538 {4, 0}, /* H */ 01539 {2, 0}, /* I */ 01540 {4, 14},/* J */ 01541 {3, 5}, /* K */ 01542 {4, 2}, /* L */ 01543 {2, 3}, /* M */ 01544 {2, 1}, /* N */ 01545 {3, 7}, /* O */ 01546 {4, 6}, /* P */ 01547 {4, 11},/* Q */ 01548 {3, 2}, /* R */ 01549 {3, 0}, /* S */ 01550 {1, 1}, /* T */ 01551 {3, 4}, /* U */ 01552 {4, 8}, /* V */ 01553 {3, 6}, /* W */ 01554 {4, 9}, /* X */ 01555 {4, 13},/* Y */ 01556 {4, 3} /* Z */ 01557 }; 01558 01559 int dottime; 01560 int dashtime; 01561 int intralettertime; 01562 int interlettertime; 01563 int interwordtime; 01564 int len, ddcomb; 01565 int res; 01566 int c; 01567 int i; 01568 int flags; 01569 01570 res = 0; 01571 01572 /* Approximate the dot time from the speed arg. */ 01573 01574 dottime = 900 / speed; 01575 01576 /* Establish timing relationships */ 01577 01578 dashtime = 3 * dottime; 01579 intralettertime = dottime; 01580 interlettertime = dottime * 4 ; 01581 interwordtime = dottime * 7; 01582 01583 for (; (*string) && (!res); string++) { 01584 01585 c = *string; 01586 01587 /* Convert lower case to upper case */ 01588 01589 if ((c >= 'a') && (c <= 'z')) 01590 c -= 0x20; 01591 01592 /* Can't deal with any char code greater than Z, skip it */ 01593 01594 if (c > 'Z') 01595 continue; 01596 01597 /* If space char, wait the inter word time */ 01598 01599 if (c == ' ') { 01600 if (!res) 01601 res = play_silence(chan, interwordtime); 01602 continue; 01603 } 01604 01605 /* Subtract out control char offset to match our table */ 01606 01607 c -= 0x20; 01608 01609 /* Get the character data */ 01610 01611 len = mbits[c].len; 01612 ddcomb = mbits[c].ddcomb; 01613 01614 /* Send the character */ 01615 01616 for (; len ; len--) { 01617 if (!res) 01618 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude); 01619 if (!res) 01620 res = play_silence(chan, intralettertime); 01621 ddcomb >>= 1; 01622 } 01623 01624 /* Wait the interletter time */ 01625 01626 if (!res) 01627 res = play_silence(chan, interlettertime - intralettertime); 01628 } 01629 01630 /* Wait for all the frames to be sent */ 01631 01632 if (!res) 01633 res = ast_waitstream(chan, ""); 01634 ast_stopstream(chan); 01635 01636 /* 01637 * Wait for the dahdi driver to physically write the tone blocks to the hardware 01638 */ 01639 01640 for (i = 0; i < 20 ; i++) { 01641 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT; 01642 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags); 01643 if (flags & DAHDI_IOMUX_WRITEEMPTY) 01644 break; 01645 if ( ast_safe_sleep(chan, 50)) { 01646 res = -1; 01647 break; 01648 } 01649 } 01650 01651 01652 return res; 01653 }
static int send_tone_telemetry | ( | struct ast_channel * | chan, | |
const char * | tonestring | |||
) | [static] |
Definition at line 1655 of file app_rpt.c.
References ast_safe_sleep(), ast_stopstream(), ast_strdupa, ast_waitstream(), chan, ast_channel::fds, play_tone_pair(), and strsep().
Referenced by telem_any().
01656 { 01657 char *stringp; 01658 char *tonesubset; 01659 int f1, f2; 01660 int duration; 01661 int amplitude; 01662 int res; 01663 int i; 01664 int flags; 01665 01666 res = 0; 01667 01668 stringp = ast_strdupa(tonestring); 01669 01670 for (;tonestring;) { 01671 tonesubset = strsep(&stringp, ")"); 01672 if (!tonesubset) 01673 break; 01674 if (sscanf(tonesubset, "(%d,%d,%d,%d", &f1, &f2, &duration, &litude) != 4) 01675 break; 01676 res = play_tone_pair(chan, f1, f2, duration, amplitude); 01677 if (res) 01678 break; 01679 } 01680 if (!res) 01681 res = play_tone_pair(chan, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */ 01682 01683 if (!res) 01684 res = ast_waitstream(chan, ""); 01685 ast_stopstream(chan); 01686 01687 /* 01688 * Wait for the dahdi driver to physically write the tone blocks to the hardware 01689 */ 01690 01691 for (i = 0; i < 20 ; i++) { 01692 flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT; 01693 res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags); 01694 if (flags & DAHDI_IOMUX_WRITEEMPTY) 01695 break; 01696 if (ast_safe_sleep(chan, 50)) { 01697 res = -1; 01698 break; 01699 } 01700 } 01701 01702 return res; 01703 }
static int serial_remote_io | ( | struct rpt * | myrpt, | |
unsigned char * | txbuf, | |||
int | txbytes, | |||
char * | rxbuf, | |||
int | rxmaxbytes, | |||
int | asciiflag | |||
) | [static] |
Definition at line 3947 of file app_rpt.c.
References ast_copy_string(), ast_debug, 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().
03948 { 03949 int i; 03950 struct dahdi_radio_param prm; 03951 03952 char *buf = alloca(30 + txbytes * 3); 03953 int len; 03954 ast_copy_string(buf, "String output was: ", 30 + txbytes * 3); 03955 len = strlen(buf); 03956 for (i = 0; i < txbytes; i++) 03957 len += snprintf(buf + len, 30 + txbytes * 3 - len, "%02X ", (unsigned char) txbuf[i]); 03958 strcat(buf + len, "\n"); 03959 ast_debug(1, "%s", buf); 03960 03961 prm.radpar = DAHDI_RADPAR_REMMODE; 03962 if (asciiflag) 03963 prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII; 03964 else 03965 prm.data = DAHDI_RADPAR_REM_SERIAL; 03966 if (ioctl(myrpt->rxchannel->fds[0], DAHDI_RADIO_SETPARAM, &prm) == -1) 03967 return -1; 03968 prm.radpar = DAHDI_RADPAR_REMCOMMAND; 03969 prm.data = rxmaxbytes; 03970 memcpy(prm.buf, txbuf, txbytes); 03971 prm.index = txbytes; 03972 if (ioctl(myrpt->rxchannel->fds[0], DAHDI_RADIO_SETPARAM, &prm) == -1) 03973 return -1; 03974 if (rxbuf) { 03975 *rxbuf = 0; 03976 memcpy(rxbuf, prm.buf, prm.index); 03977 } 03978 return(prm.index); 03979 }
static int service_scan | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 4507 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, multimode_bump_freq(), split_freq, and stop_scan().
04508 { 04509 int res, interval, mhz, decimals; 04510 char k10=0, k100=0; 04511 04512 switch (myrpt->hfscanmode) { 04513 04514 case HF_SCAN_DOWN_SLOW: 04515 interval = -10; /* 100Hz /sec */ 04516 break; 04517 04518 case HF_SCAN_DOWN_QUICK: 04519 interval = -50; /* 500Hz /sec */ 04520 break; 04521 04522 case HF_SCAN_DOWN_FAST: 04523 interval = -200; /* 2KHz /sec */ 04524 break; 04525 04526 case HF_SCAN_UP_SLOW: 04527 interval = 10; /* 100Hz /sec */ 04528 break; 04529 04530 case HF_SCAN_UP_QUICK: 04531 interval = 50; /* 500 Hz/sec */ 04532 break; 04533 04534 case HF_SCAN_UP_FAST: 04535 interval = 200; /* 2KHz /sec */ 04536 break; 04537 04538 default: 04539 myrpt->hfscanmode = 0; /* Huh? */ 04540 return -1; 04541 } 04542 04543 res = split_freq(&mhz, &decimals, myrpt->freq); 04544 04545 if (!res) { 04546 k100 = decimals / 10000; 04547 k10 = (decimals / 1000) % 10; 04548 res = multimode_bump_freq(myrpt, interval); 04549 } 04550 04551 if (!res) 04552 res = split_freq(&mhz, &decimals, myrpt->freq); 04553 04554 if (res) { 04555 stop_scan(myrpt, 1); 04556 return -1; 04557 } 04558 04559 /* Announce 10KHz boundaries */ 04560 if (k10 != (decimals / 1000) % 10) { 04561 int myhund = (interval < 0) ? k100 : decimals / 10000; 04562 int myten = (interval < 0) ? k10 : (decimals / 1000) % 10; 04563 myrpt->hfscanstatus = (myten == 0) ? (myhund) * 100 : (myten) * 10; 04564 } 04565 return res; 04566 04567 }
static int set_ctcss_freq_ft897 | ( | struct rpt * | myrpt, | |
char * | txtone, | |||
char * | rxtone | |||
) | [static] |
Definition at line 4317 of file app_rpt.c.
References serial_remote_io(), and split_ctcss_freq.
Referenced by set_ft897().
04318 { 04319 unsigned char cmdstr[5] = { 0, 0, 0, 0, 0x0B }; 04320 int hertz, decimal; 04321 04322 if (split_ctcss_freq(&hertz, &decimal, txtone)) 04323 return -1; 04324 04325 cmdstr[0] = ((hertz / 100) << 4) + (hertz % 100) / 10; 04326 cmdstr[1] = ((hertz % 10) << 4) + (decimal % 10); 04327 04328 if (rxtone) { 04329 if (split_ctcss_freq(&hertz, &decimal, rxtone)) 04330 return -1; 04331 04332 cmdstr[2] = ((hertz / 100) << 4) + (hertz % 100)/ 10; 04333 cmdstr[3] = ((hertz % 10) << 4) + (decimal % 10); 04334 } 04335 04336 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 04337 }
static int set_ctcss_mode_ft897 | ( | struct rpt * | myrpt, | |
char | txplon, | |||
char | rxplon | |||
) | [static] |
Definition at line 4298 of file app_rpt.c.
References serial_remote_io().
Referenced by set_ft897().
04299 { 04300 unsigned char cmdstr[5] = { 0, 0, 0, 0, 0x0A }; 04301 04302 if (rxplon && txplon) 04303 cmdstr[0] = 0x2A; /* Encode and Decode */ 04304 else if (!rxplon && txplon) 04305 cmdstr[0] = 0x4A; /* Encode only */ 04306 else if (rxplon && !txplon) 04307 cmdstr[0] = 0x3A; /* Encode only */ 04308 else 04309 cmdstr[0] = 0x8A; /* OFF */ 04310 04311 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 04312 }
static int set_freq_ft897 | ( | struct rpt * | myrpt, | |
char * | newfreq | |||
) | [static] |
Definition at line 4214 of file app_rpt.c.
References ast_debug, serial_remote_io(), and split_freq.
Referenced by multimode_bump_freq_ft897(), and set_ft897().
04215 { 04216 unsigned char cmdstr[5]; 04217 int fd, m, d; 04218 04219 fd = 0; 04220 ast_debug(1, "New frequency: %s\n", newfreq); 04221 04222 if (split_freq(&m, &d, newfreq)) 04223 return -1; 04224 04225 /* The FT-897 likes packed BCD frequencies */ 04226 04227 cmdstr[0] = ((m / 100) << 4) + ((m % 100) / 10); /* 100MHz 10Mhz */ 04228 cmdstr[1] = ((m % 10) << 4) + (d / 10000); /* 1MHz 100KHz */ 04229 cmdstr[2] = (((d % 10000) / 1000) << 4) + ((d % 1000) / 100); /* 10KHz 1KHz */ 04230 cmdstr[3] = (((d % 100) / 10) << 4) + (d % 10); /* 100Hz 10Hz */ 04231 cmdstr[4] = 0x01; /* command */ 04232 04233 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 04234 }
static int set_ft897 | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 4341 of file app_rpt.c.
References ast_debug, 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().
04342 { 04343 int res; 04344 04345 ast_debug(1, "@@@@ lock on\n"); 04346 04347 res = simple_command_ft897(myrpt, 0x00); /* LOCK on */ 04348 04349 ast_debug(1, "@@@@ ptt off\n"); 04350 04351 if (!res) 04352 res = simple_command_ft897(myrpt, 0x88); /* PTT off */ 04353 04354 ast_debug(1, "Modulation mode\n"); 04355 04356 if (!res) 04357 res = set_mode_ft897(myrpt, myrpt->remmode); /* Modulation mode */ 04358 04359 ast_debug(1, "Split off\n"); 04360 04361 if (!res) 04362 simple_command_ft897(myrpt, 0x82); /* Split off */ 04363 04364 ast_debug(1, "Frequency\n"); 04365 04366 if (!res) 04367 res = set_freq_ft897(myrpt, myrpt->freq); /* Frequency */ 04368 if ((myrpt->remmode == REM_MODE_FM)) { 04369 ast_debug(1, "Offset\n"); 04370 if (!res) 04371 res = set_offset_ft897(myrpt, myrpt->offset); /* Offset if FM */ 04372 if ((!res)&&(myrpt->rxplon || myrpt->txplon)) { 04373 ast_debug(1, "CTCSS tone freqs.\n"); 04374 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl); /* CTCSS freqs if CTCSS is enabled */ 04375 } 04376 if (!res) { 04377 ast_debug(1, "CTCSS mode\n"); 04378 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */ 04379 } 04380 } 04381 if ((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)) { 04382 ast_debug(1, "Clarifier off\n"); 04383 simple_command_ft897(myrpt, 0x85); /* Clarifier off if LSB or USB */ 04384 } 04385 return res; 04386 }
static int set_mode_ft897 | ( | struct rpt * | myrpt, | |
char | newmode | |||
) | [static] |
Definition at line 4272 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().
04273 { 04274 unsigned char cmdstr[5] = { 0, 0, 0, 0, 0x07 }; 04275 04276 switch (newmode) { 04277 case REM_MODE_FM: 04278 cmdstr[0] = 0x08; 04279 break; 04280 case REM_MODE_USB: 04281 cmdstr[0] = 0x01; 04282 break; 04283 case REM_MODE_LSB: 04284 cmdstr[0] = 0x00; 04285 break; 04286 case REM_MODE_AM: 04287 cmdstr[0] = 0x04; 04288 break; 04289 default: 04290 return -1; 04291 } 04292 04293 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 04294 }
static int set_offset_ft897 | ( | struct rpt * | myrpt, | |
char | offset | |||
) | [static] |
Definition at line 4247 of file app_rpt.c.
References REM_MINUS, REM_PLUS, REM_SIMPLEX, and serial_remote_io().
Referenced by set_ft897().
04248 { 04249 unsigned char cmdstr[5] = ""; 04250 04251 switch (offset) { 04252 case REM_SIMPLEX: 04253 cmdstr[0] = 0x89; 04254 break; 04255 case REM_MINUS: 04256 cmdstr[0] = 0x09; 04257 break; 04258 case REM_PLUS: 04259 cmdstr[0] = 0x49; 04260 break; 04261 default: 04262 return -1; 04263 } 04264 04265 cmdstr[4] = 0x09; 04266 04267 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 04268 }
static int setrbi | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 3981 of file app_rpt.c.
References ast_copy_string(), ast_debug, 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().
03982 { 03983 char tmp[MAXREMSTR] = "", *s; 03984 unsigned char rbicmd[5]; 03985 int band, txoffset = 0, txpower = 0, txpl; 03986 03987 /* must be a remote system */ 03988 if (!myrpt->remote) 03989 return(0); 03990 /* must have rbi hardware */ 03991 if (strncmp(myrpt->remote, remote_rig_rbi, 3)) 03992 return(0); 03993 ast_copy_string(tmp, myrpt->freq, sizeof(tmp)); 03994 s = strchr(tmp, '.'); 03995 /* if no decimal, is invalid */ 03996 03997 if (s == NULL) { 03998 ast_debug(1, "@@@@ Frequency needs a decimal\n"); 03999 return -1; 04000 } 04001 04002 *s++ = 0; 04003 if (strlen(tmp) < 2) { 04004 ast_debug(1, "@@@@ Bad MHz digits: %s\n", tmp); 04005 return -1; 04006 } 04007 04008 if (strlen(s) < 3) { 04009 ast_debug(1, "@@@@ Bad KHz digits: %s\n", s); 04010 return -1; 04011 } 04012 04013 if ((s[2] != '0') && (s[2] != '5')) { 04014 ast_debug(1, "@@@@ KHz must end in 0 or 5: %c\n", s[2]); 04015 return -1; 04016 } 04017 04018 band = rbi_mhztoband(tmp); 04019 if (band == -1) { 04020 ast_debug(1, "@@@@ Bad Band: %s\n", tmp); 04021 return -1; 04022 } 04023 04024 txpl = rbi_pltocode(myrpt->txpl); 04025 04026 if (txpl == -1) { 04027 ast_debug(1, "@@@@ Bad TX PL: %s\n", myrpt->txpl); 04028 return -1; 04029 } 04030 04031 04032 switch (myrpt->offset) { 04033 case REM_MINUS: 04034 txoffset = 0; 04035 break; 04036 case REM_PLUS: 04037 txoffset = 0x10; 04038 break; 04039 case REM_SIMPLEX: 04040 txoffset = 0x20; 04041 break; 04042 } 04043 switch(myrpt->powerlevel) { 04044 case REM_LOWPWR: 04045 txpower = 0; 04046 break; 04047 case REM_MEDPWR: 04048 txpower = 0x20; 04049 break; 04050 case REM_HIPWR: 04051 txpower = 0x10; 04052 break; 04053 } 04054 rbicmd[0] = 0; 04055 rbicmd[1] = band | txpower | 0xc0; 04056 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80; 04057 if (s[2] == '5') 04058 rbicmd[2] |= 0x40; 04059 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0'); 04060 rbicmd[4] = txpl; 04061 if (myrpt->txplon) 04062 rbicmd[4] |= 0x40; 04063 if (myrpt->rxplon) 04064 rbicmd[4] |= 0x80; 04065 rbi_out(myrpt, rbicmd); 04066 return 0; 04067 }
static int setrem | ( | struct rpt * | myrpt | ) | [static] |
Definition at line 4435 of file app_rpt.c.
References rpt::remote, set_ft897(), and setrbi().
Referenced by function_remote().
04436 { 04437 return 0; /* XXX BROKEN!! */ 04438 if (!strcmp(myrpt->remote, remote_rig_ft897)) 04439 return set_ft897(myrpt); 04440 else if (!strcmp(myrpt->remote, remote_rig_rbi)) 04441 return setrbi(myrpt); 04442 else 04443 return -1; 04444 }
static int simple_command_ft897 | ( | struct rpt * | myrpt, | |
char | command | |||
) | [static] |
Definition at line 4238 of file app_rpt.c.
References serial_remote_io().
Referenced by closerem_ft897(), and set_ft897().
04239 { 04240 unsigned char cmdstr[5] = { 0, 0, 0, 0, command }; 04241 04242 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0); 04243 }
static char* skipchars | ( | char * | string, | |
char * | charlist | |||
) | [static] |
Definition at line 788 of file app_rpt.c.
Referenced by function_autopatchup().
00789 { 00790 int i; 00791 while (*string) { 00792 for (i = 0; charlist[i] ; i++) { 00793 if (*string == charlist[i]) { 00794 string++; 00795 break; 00796 } 00797 } 00798 if (!charlist[i]) 00799 return string; 00800 } 00801 return string; 00802 }
static int split_decimal | ( | char * | input, | |
int * | ints, | |||
int * | decs, | |||
int | places | |||
) | [static] |
Definition at line 4102 of file app_rpt.c.
04103 { 04104 double input2 = 0.0; 04105 long long modifier = (long long)pow(10.0, (double)places); 04106 if (sscanf(input, "%lf", &input2) == 1) { 04107 long long input3 = input2 * modifier; 04108 *ints = input3 / modifier; 04109 *decs = input3 % modifier; 04110 return 0; 04111 } else 04112 return -1; 04113 }
static void stop_scan | ( | struct rpt * | myrpt, | |
int | flag | |||
) | [static] |
Definition at line 4497 of file app_rpt.c.
References rpt::hfscanmode, and rpt::hfscanstatus.
Referenced by handle_remote_dtmf_digit(), and service_scan().
04498 { 04499 myrpt->hfscanmode = 0; 04500 myrpt->hfscanstatus = ((flag) ? -2 : -1); 04501 }
static int telem_any | ( | struct rpt * | myrpt, | |
struct ast_channel * | chan, | |||
const char * | entry | |||
) | [static] |
Definition at line 1757 of file app_rpt.c.
References chan, MORSE, retrieve_astcfgint(), sayfile(), send_morse(), and send_tone_telemetry().
Referenced by rpt_tele_thread(), and telem_lookup().
01758 { 01759 int res; 01760 char c; 01761 01762 static int morsespeed; 01763 static int morsefreq; 01764 static int morseampl; 01765 static int morseidfreq = 0; 01766 static int morseidampl; 01767 static char mcat[] = MORSE; 01768 01769 res = 0; 01770 01771 if (!morseidfreq) { /* Get the morse parameters if not already loaded */ 01772 morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20); 01773 morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800); 01774 morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096); 01775 morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048); 01776 morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330); 01777 } 01778 01779 /* Is it a file, or a tone sequence? */ 01780 01781 if (entry[0] == '|') { 01782 c = entry[1]; 01783 if ((c >= 'a') && (c <= 'z')) 01784 c -= 0x20; 01785 01786 switch (c) { 01787 case 'I': /* Morse ID */ 01788 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl); 01789 break; 01790 case 'M': /* Morse Message */ 01791 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl); 01792 break; 01793 case 'T': /* Tone sequence */ 01794 res = send_tone_telemetry(chan, entry + 2); 01795 break; 01796 default: 01797 res = -1; 01798 } 01799 } else 01800 res = sayfile(chan, entry); /* File */ 01801 return res; 01802 }
static int telem_lookup | ( | struct rpt * | myrpt, | |
struct ast_channel * | chan, | |||
const char * | node, | |||
const char * | name | |||
) | [static] |
Definition at line 1810 of file app_rpt.c.
References ast_strlen_zero(), ast_variable_retrieve(), rpt::cfg, chan, tele_defs, telem_any(), and TELEMETRY.
Referenced by handle_remote_data(), handle_remote_phone_dtmf(), and rpt_tele_thread().
01811 { 01812 int res = 0; 01813 int i; 01814 const char *entry = NULL; 01815 const char *telemetry; 01816 01817 /* Retrieve the section name for telemetry from the node section */ 01818 if ((telemetry = ast_variable_retrieve(myrpt->cfg, node, TELEMETRY))) 01819 entry = ast_variable_retrieve(myrpt->cfg, telemetry, name); 01820 01821 /* Try to look up the telemetry name */ 01822 01823 if (!entry) { 01824 /* Telemetry name wasn't found in the config file, use the default */ 01825 for (i = 0; i < sizeof(tele_defs) / sizeof(struct telem_defaults); i++) { 01826 if (!strcasecmp(tele_defs[i].name, name)) 01827 entry = tele_defs[i].value; 01828 } 01829 } 01830 if (entry) { 01831 if (!ast_strlen_zero(entry)) 01832 telem_any(myrpt, chan, entry); 01833 } else { 01834 res = -1; 01835 } 01836 return res; 01837 }
static int unload_module | ( | void | ) | [static] |
Definition at line 7432 of file app_rpt.c.
References ast_cli_unregister_multiple(), ast_mutex_destroy(), ast_unregister_application(), cli_rpt, lock, name, rpt::nodes, and rpt_vars.
07433 { 07434 int i; 07435 07436 for (i = 0; i < nrpts; i++) { 07437 if (!strcmp(rpt_vars[i].name, rpt_vars[i].p.nodes)) 07438 continue; 07439 ast_mutex_destroy(&rpt_vars[i].lock); 07440 } 07441 i = ast_unregister_application(app); 07442 07443 /* Unregister cli extensions */ 07444 ast_cli_unregister_multiple(cli_rpt, sizeof(cli_rpt) / sizeof(struct ast_cli_entry)); 07445 07446 return i; 07447 }
static void wait_interval | ( | struct rpt * | myrpt, | |
int | type, | |||
struct ast_channel * | chan | |||
) | [static] |
Definition at line 1879 of file app_rpt.c.
References ast_log(), ast_safe_sleep(), chan, get_wait_interval(), and LOG_NOTICE.
Referenced by rpt_tele_thread().
01880 { 01881 int interval; 01882 interval = get_wait_interval(myrpt, type); 01883 if (debug) 01884 ast_log(LOG_NOTICE, " Delay interval = %d\n", interval); 01885 if (interval) 01886 ast_safe_sleep(chan, interval); 01887 if (debug) 01888 ast_log(LOG_NOTICE, "Delay complete\n"); 01889 return; 01890 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Radio Repeater / Remote Base" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
const struct ast_module_info* ast_module_info = &__mod_info [static] |
struct ast_cli_entry cli_rpt[] [static] |
int debug = 0 [static] |
Definition at line 283 of file app_rpt.c.
Referenced by add_sdp(), aji_load_config(), check_peer_ok(), check_user_ok(), handle_incoming(), handle_pri_show_debug(), handle_verbose(), process_sdp(), and set_destination().
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] |
char* synopsis = "Radio Repeater/Remote Base Control System" [static] |
struct telem_defaults tele_defs[] [static] |