Complete re-vamp of Radio Repeater application (app_rpt) and VERY minor changes in chan_zap (to allow pseudo-channels to work properly (finally!)) and in dsp.c to allow for super-relaxed DTMF decoding which radio systems need to function properly.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3117 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Jim Dixon
2004-05-31 16:04:10 +00:00
parent b0f9569b5c
commit 8968d50976
6 changed files with 555 additions and 43 deletions

View File

@@ -57,6 +57,10 @@ DEBUG=-g #-pg
# You can still use the old libpri if you do "cvs update -D "08/03/03" in libpri source code # You can still use the old libpri if you do "cvs update -D "08/03/03" in libpri source code
OPTIONS += -DNEW_PRI_HANGUP OPTIONS += -DNEW_PRI_HANGUP
# If you are running a radio application, define RADIO_RELAX so that the DTMF
# will be received more reliably
#OPTIONS += -DRADIO_RELAX
# Optional debugging parameters # Optional debugging parameters
DEBUG_THREADS = #-DDEBUG_THREADS #-DDO_CRASH DEBUG_THREADS = #-DDEBUG_THREADS #-DDO_CRASH

View File

@@ -35,9 +35,9 @@ endif
#APPS+=app_sql_postgres.so #APPS+=app_sql_postgres.so
#APPS+=app_sql_odbc.so #APPS+=app_sql_odbc.so
#APPS+=app_rpt.so
APPS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi) APPS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi)
#APPS+=$(shell if [ -f /usr/include/zap.h ]; then echo "app_rpt.so" ; fi)
CFLAGS+=-fPIC CFLAGS+=-fPIC
@@ -64,12 +64,6 @@ install: all
for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so
app_todd.o: app_todd.c
gcc -pipe -O6 -g -Iinclude -I../include -D_REENTRANT -march=i586 -DDO_CRASH -c -o app_todd.o app_todd.c
app_todd.so: app_todd.o
$(CC) $(SOLINK) -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto
app_voicemail.so : app_voicemail.o app_voicemail.so : app_voicemail.o
ifeq ($(USE_MYSQL_VM_INTERFACE),1) ifeq ($(USE_MYSQL_VM_INTERFACE),1)
$(CC) $(SOLINK) -o $@ $(MLFLAGS) $< -L/usr/lib/mysql -lmysqlclient -lz $(CC) $(SOLINK) -o $@ $(MLFLAGS) $< -L/usr/lib/mysql -lmysqlclient -lz

View File

@@ -2,17 +2,40 @@
* *
* Asterisk -- A telephony toolkit for Linux. * Asterisk -- A telephony toolkit for Linux.
* *
* Radio Repeater program * Radio Repeater / Remote Base program
* version 0.2 5/30/04
* *
* Copyright (C) 2002, Jim Dixon * Copyright (C) 2002-2004, Jim Dixon
* *
* Jim Dixon <jim@lambdatel.com> * Jim Dixon <jim@lambdatel.com>
* *
* This program is free software, distributed under the terms of * This program is free software, distributed under the terms of
* the GNU General Public License * the GNU General Public License
* *
* Repeater / Remote Functions:
* "Simple" Mode: * - autopatch access, # - autopatch hangup
* Normal mode:
* *0 - autopatch access
* *1 - remote base off
* *2 - remote base monitor
* *3 - remote base tranceive
* *8 - force ID
* *9 - system reset
*
* To send an asterisk (*) while dialing or talking on phone,
* use the autopatch acess code.
*/ */
/* number of digits for function after *. Must be at least 1 */
#define FUNCTION_LEN 1
/* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
#define MAXDTMF 10
#define DTMF_TIMEOUT 3
enum {REM_OFF,REM_MONITOR,REM_TX};
#include <asterisk/lock.h> #include <asterisk/lock.h>
#include <asterisk/file.h> #include <asterisk/file.h>
#include <asterisk/logger.h> #include <asterisk/logger.h>
@@ -40,7 +63,7 @@
#include <tonezone.h> #include <tonezone.h>
#include <linux/zaptel.h> #include <linux/zaptel.h>
static char *tdesc = "Radio Repeater"; static char *tdesc = "Radio Repeater / Remote Base version 0.2 05/30/2004";
static int debug = 0; static int debug = 0;
STANDARD_LOCAL_USER; STANDARD_LOCAL_USER;
LOCAL_USER_DECL; LOCAL_USER_DECL;
@@ -58,17 +81,25 @@ static struct rpt
char *name; char *name;
char *rxchanname; char *rxchanname;
char *txchanname; char *txchanname;
char *rem_rxchanname;
char *rem_txchanname;
char *ourcontext; char *ourcontext;
char *ourcallerid; char *ourcallerid;
char *acctcode; char *acctcode;
char *idrecording; char *idrecording;
char *tonezone;
int hangtime; int hangtime;
int totime; int totime;
int idtime; int idtime;
struct ast_channel *rxchannel,*txchannel,*pchannel; char remoterx;
char remotetx;
char remotemode;
char simple;
struct ast_channel *rxchannel,*txchannel,*rem_rxchannel;
struct ast_channel *rem_txchannel,*pchannel;
int tailtimer,totimer,idtimer,txconf,pconf,callmode,cidx; int tailtimer,totimer,idtimer,txconf,pconf,callmode,cidx;
pthread_t rpt_id_thread,rpt_term_thread,rpt_proc_thread,rpt_call_thread; pthread_t rpt_id_thread,rpt_term_thread,rpt_proc_thread,rpt_call_thread;
char mydtmf,iding,terming; char mydtmf,iding,terming,teleing,comping,procing;
char exten[AST_MAX_EXTENSION]; char exten[AST_MAX_EXTENSION];
} rpt_vars[MAXRPTS]; } rpt_vars[MAXRPTS];
@@ -130,7 +161,7 @@ struct ast_channel *mychannel;
} }
/* make a conference for the tx */ /* make a conference for the tx */
ci.chan = 0; ci.chan = 0;
ci.confno = myrpt->pconf; /* use the tx conference */ ci.confno = myrpt->txconf; /* use the tx conference */
ci.confmode = ZT_CONF_CONFANN; ci.confmode = ZT_CONF_CONFANN;
/* first put the channel on the conference in announce mode */ /* first put the channel on the conference in announce mode */
if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1) if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
@@ -138,7 +169,7 @@ struct ast_channel *mychannel;
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n"); ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL); pthread_exit(NULL);
} }
myrpt->terming = 1; myrpt->procing = 1;
ast_stopstream(mychannel); ast_stopstream(mychannel);
res = ast_streamfile(mychannel, "callproceeding", mychannel->language); res = ast_streamfile(mychannel, "callproceeding", mychannel->language);
if (!res) if (!res)
@@ -147,7 +178,7 @@ struct ast_channel *mychannel;
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name); ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
res = 0; res = 0;
} }
myrpt->terming = 0; myrpt->procing = 0;
ast_stopstream(mychannel); ast_stopstream(mychannel);
ast_hangup(mychannel); ast_hangup(mychannel);
pthread_exit(NULL); pthread_exit(NULL);
@@ -171,7 +202,7 @@ struct ast_channel *mychannel;
} }
/* make a conference for the tx */ /* make a conference for the tx */
ci.chan = 0; ci.chan = 0;
ci.confno = myrpt->pconf; /* use the tx conference */ ci.confno = myrpt->txconf; /* use the tx conference */
ci.confmode = ZT_CONF_CONFANN; ci.confmode = ZT_CONF_CONFANN;
/* first put the channel on the conference in announce mode */ /* first put the channel on the conference in announce mode */
if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1) if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
@@ -194,6 +225,89 @@ struct ast_channel *mychannel;
pthread_exit(NULL); pthread_exit(NULL);
} }
static void *rpt_complete(void *this)
{
ZT_CONFINFO ci; /* conference info */
int res;
struct rpt *myrpt = (struct rpt *)this;
struct ast_channel *mychannel;
/* wait a little bit */
usleep(1000000);
/* allocate a pseudo-channel thru asterisk */
mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
if (!mychannel)
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
pthread_exit(NULL);
}
/* make a conference for the tx */
ci.chan = 0;
ci.confno = myrpt->txconf; /* use the tx conference */
ci.confmode = ZT_CONF_CONFANN;
/* first put the channel on the conference in announce mode */
if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
myrpt->comping = 1;
ast_stopstream(mychannel);
res = ast_streamfile(mychannel, "functioncomplete", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
res = 0;
}
myrpt->comping = 0;
ast_stopstream(mychannel);
ast_hangup(mychannel);
pthread_exit(NULL);
}
static void *rpt_remote_telemetry(void *this)
{
ZT_CONFINFO ci; /* conference info */
int res;
struct rpt *myrpt = (struct rpt *)this;
struct ast_channel *mychannel;
/* wait a little bit */
usleep(1000000);
/* allocate a pseudo-channel thru asterisk */
mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
if (!mychannel)
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
pthread_exit(NULL);
}
/* make a conference for the tx */
ci.chan = 0;
ci.confno = myrpt->txconf; /* use the tx conference */
ci.confmode = ZT_CONF_CONFANN;
/* first put the channel on the conference in announce mode */
if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
myrpt->teleing = 1;
ast_stopstream(mychannel);
res = ast_streamfile(mychannel,
((myrpt->remotemode == REM_MONITOR) ? "remote_monitor" : "remote_tx"),
mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
res = 0;
}
myrpt->teleing = 0;
ast_hangup(mychannel);
pthread_exit(NULL);
}
static void *rpt_call(void *this) static void *rpt_call(void *this)
{ {
ZT_CONFINFO ci; /* conference info */ ZT_CONFINFO ci; /* conference info */
@@ -244,6 +358,22 @@ struct ast_channel *mychannel,*genchannel;
myrpt->callmode = 0; myrpt->callmode = 0;
pthread_exit(NULL); pthread_exit(NULL);
} }
if (myrpt->tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->tonezone) == -1))
{
ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
if (myrpt->tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->tonezone) == -1))
{
ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
/* start dialtone */ /* start dialtone */
if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0) if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0)
{ {
@@ -358,14 +488,104 @@ struct ast_channel *mychannel,*genchannel;
pthread_exit(NULL); pthread_exit(NULL);
} }
static void process_dtmf(char *cmd,struct rpt *myrpt)
{
pthread_attr_t attr;
ZT_CONFINFO ci; /* conference info */
switch(atoi(cmd))
{
case 0: /* autopatch on / send asterisk (*) */
/* if on call, force * into current audio stream */
if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
{
myrpt->mydtmf = '*';
break;
}
if (myrpt->callmode) return;
myrpt->callmode = 1;
myrpt->cidx = 0;
myrpt->exten[myrpt->cidx] = 0;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
return;
case 9: /* master reset */
myrpt->callmode = 0;
/* fall thru intentionally */
case 1: /* remote base off */
if (myrpt->rem_rxchannel == NULL) return;
myrpt->remotemode = REM_OFF;
ci.chan = 0;
ci.confno = 0;
ci.confmode = 0;
/* Take off conf */
if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
/* Take off conf */
if (ioctl(myrpt->rem_txchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
break;
case 2: /* remote base monitor */
if (myrpt->rem_rxchannel == NULL) return;
myrpt->remotemode = REM_MONITOR;
if (myrpt->remoterx && (!myrpt->remotetx))
{
ci.chan = 0;
ci.confno = myrpt->pconf;
ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
/* Put on conf */
if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
}
break;
case 3: /* remote base tranceieve */
if (myrpt->rem_rxchannel == NULL) return;
myrpt->remotemode = REM_TX;
if (myrpt->remoterx && (!myrpt->remotetx))
{
ci.chan = 0;
ci.confno = myrpt->pconf;
ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
/* Put on conf */
if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
}
break;
case 8: /* force ID */
myrpt->idtimer = 0;
return;
default:
return;
}
/* send function complete */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&myrpt->rpt_call_thread,&attr,rpt_complete,(void *)myrpt);
}
/* single thread with one file (request) to dial */ /* single thread with one file (request) to dial */
static void *rpt(void *this) static void *rpt(void *this)
{ {
struct rpt *myrpt = (struct rpt *)this; struct rpt *myrpt = (struct rpt *)this;
char *tele; char *tele;
int ms = MSWAIT,lasttx,keyed,val; int ms = MSWAIT,lasttx,keyed,val,dtmfidx;
char dtmfbuf[MAXDTMF];
struct ast_channel *who; struct ast_channel *who;
ZT_CONFINFO ci; /* conference info */ ZT_CONFINFO ci; /* conference info */
time_t dtmf_time,t;
pthread_attr_t attr; pthread_attr_t attr;
tele = strchr(myrpt->rxchanname,'/'); tele = strchr(myrpt->rxchanname,'/');
@@ -390,7 +610,7 @@ pthread_attr_t attr;
} }
else else
{ {
fprintf(stderr,"rpt:Sorry unable to obtain channel\n"); fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
pthread_exit(NULL); pthread_exit(NULL);
} }
if (myrpt->txchanname) if (myrpt->txchanname)
@@ -417,7 +637,7 @@ pthread_attr_t attr;
} }
else else
{ {
fprintf(stderr,"rpt:Sorry unable to obtain channel\n"); fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
pthread_exit(NULL); pthread_exit(NULL);
} }
} }
@@ -425,6 +645,70 @@ pthread_attr_t attr;
{ {
myrpt->txchannel = myrpt->rxchannel; myrpt->txchannel = myrpt->rxchannel;
} }
myrpt->rem_rxchannel = NULL;
myrpt->rem_txchannel = NULL;
myrpt->remoterx = 0;
myrpt->remotemode = REM_OFF;
if (myrpt->rem_rxchanname)
{
tele = strchr(myrpt->rem_rxchanname,'/');
if (!tele)
{
fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
pthread_exit(NULL);
}
*tele++ = 0;
myrpt->rem_rxchannel = ast_request(myrpt->rem_rxchanname,AST_FORMAT_SLINEAR,tele);
if (myrpt->rem_rxchannel)
{
ast_set_read_format(myrpt->rem_rxchannel,AST_FORMAT_SLINEAR);
ast_set_write_format(myrpt->rem_rxchannel,AST_FORMAT_SLINEAR);
myrpt->rem_rxchannel->whentohangup = 0;
myrpt->rem_rxchannel->appl = "Apprpt";
myrpt->rem_rxchannel->data = "(Repeater/Remote Rx)";
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "rpt (RemoteRx) initiating call to %s/%s on %s\n",
myrpt->rem_rxchanname,tele,myrpt->rem_rxchannel->name);
ast_call(myrpt->rem_rxchannel,tele,999);
}
else
{
fprintf(stderr,"rpt:Sorry unable to obtain RemoteRx channel\n");
pthread_exit(NULL);
}
if (myrpt->rem_txchanname) /* if in remote base mode */
{
tele = strchr(myrpt->rem_txchanname,'/');
if (!tele)
{
fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
pthread_exit(NULL);
}
*tele++ = 0;
myrpt->rem_txchannel = ast_request(myrpt->rem_txchanname,AST_FORMAT_SLINEAR,tele);
if (myrpt->rem_txchannel)
{
ast_set_read_format(myrpt->rem_txchannel,AST_FORMAT_SLINEAR);
ast_set_write_format(myrpt->rem_txchannel,AST_FORMAT_SLINEAR);
myrpt->rem_txchannel->whentohangup = 0;
myrpt->rem_txchannel->appl = "Apprpt";
myrpt->rem_txchannel->data = "(Repeater/Remote Tx)";
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "rpt (RemoteTx) initiating call to %s/%s on %s\n",
myrpt->rem_txchanname,tele,myrpt->rem_txchannel->name);
ast_call(myrpt->rem_txchannel,tele,999);
}
else
{
fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
pthread_exit(NULL);
}
}
else
{
myrpt->rem_txchannel = myrpt->rem_rxchannel;
}
}
/* allocate a pseudo-channel thru asterisk */ /* allocate a pseudo-channel thru asterisk */
myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo"); myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
if (!myrpt->pchannel) if (!myrpt->pchannel)
@@ -463,19 +747,39 @@ pthread_attr_t attr;
myrpt->totimer = 0; myrpt->totimer = 0;
myrpt->idtimer = 0; myrpt->idtimer = 0;
lasttx = 0; lasttx = 0;
myrpt->remotetx = 0;
keyed = 0; keyed = 0;
myrpt->callmode = 0; myrpt->callmode = 0;
dtmfidx = -1;
dtmfbuf[0] = 0;
dtmf_time = 0;
val = 0; val = 0;
ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0); ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
val = 1; val = 1;
ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0); ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
if (myrpt->rem_rxchannel)
{
val = 0;
ast_channel_setoption(myrpt->rem_rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
val = 1;
ast_channel_setoption(myrpt->rem_rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
}
while (ms >= 0) while (ms >= 0)
{ {
struct ast_frame *f; struct ast_frame *f;
struct ast_channel *cs[3]; struct ast_channel *cs[5];
int totx,elap; int totx,rem_totx,elap,n;
totx = (keyed || myrpt->callmode || myrpt->iding || myrpt->terming); if (ast_check_hangup(myrpt->rxchannel)) break;
if (ast_check_hangup(myrpt->txchannel)) break;
if (myrpt->rem_rxchannel)
{
if (ast_check_hangup(myrpt->rem_rxchannel)) break;
if (ast_check_hangup(myrpt->rem_txchannel)) break;
}
totx = (keyed || myrpt->callmode || myrpt->iding || myrpt->terming
|| ((myrpt->remotemode != REM_OFF) && myrpt->remoterx) ||
myrpt->teleing || myrpt->comping || myrpt->procing);
if (!totx) myrpt->totimer = myrpt->totime; if (!totx) myrpt->totimer = myrpt->totime;
else myrpt->tailtimer = myrpt->hangtime; else myrpt->tailtimer = myrpt->hangtime;
totx = (totx || myrpt->tailtimer) && myrpt->totimer; totx = (totx || myrpt->tailtimer) && myrpt->totimer;
@@ -486,6 +790,11 @@ pthread_attr_t attr;
myrpt->totimer = myrpt->totime; myrpt->totimer = myrpt->totime;
continue; continue;
} }
/* if timed-out and in circuit busy after call */
if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
{
myrpt->callmode = 0;
}
if (totx && (!myrpt->idtimer)) if (totx && (!myrpt->idtimer))
{ {
myrpt->idtimer = myrpt->idtime; myrpt->idtimer = myrpt->idtime;
@@ -503,12 +812,75 @@ pthread_attr_t attr;
lasttx = 0; lasttx = 0;
ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY); ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
} }
rem_totx = ((keyed && (myrpt->remotemode == REM_TX)) && myrpt->totimer);
cs[0] = myrpt->rxchannel; if (rem_totx && (!myrpt->remotetx))
cs[1] = myrpt->pchannel; {
cs[2] = myrpt->txchannel; myrpt->remotetx = 1;
ci.chan = 0;
ci.confno = 0;
ci.confmode = 0;
/* Take off conf */
if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
ast_indicate(myrpt->rem_txchannel,AST_CONTROL_RADIO_KEY);
ci.chan = 0;
ci.confno = myrpt->txconf;
ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
/* Put the channel on the conference in listener mode */
if (ioctl(myrpt->rem_txchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
}
if ((!rem_totx) && myrpt->remotetx)
{
myrpt->remotetx = 0;
ast_indicate(myrpt->rem_txchannel,AST_CONTROL_RADIO_UNKEY);
ci.chan = 0;
ci.confno = 0;
ci.confmode = 0;
/* Take off conf */
if (ioctl(myrpt->rem_txchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
if (myrpt->remotemode != REM_OFF)
{
ci.chan = 0;
ci.confno = myrpt->pconf;
ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
/* Put on conf */
if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
}
}
time(&t);
/* if DTMF timeout */
if ((dtmfidx >= 0) && ((dtmf_time + DTMF_TIMEOUT) < t))
{
dtmfidx = -1;
dtmfbuf[0] = 0;
}
n = 0;
cs[n++] = myrpt->rxchannel;
cs[n++] = myrpt->pchannel;
if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
if (myrpt->rem_rxchannel)
{
cs[n++] = myrpt->rem_rxchannel;
if (myrpt->rem_txchannel != myrpt->rem_rxchannel)
cs[n++] = myrpt->rem_txchannel;
}
ms = MSWAIT; ms = MSWAIT;
who = ast_waitfor_n(cs,3,&ms); who = ast_waitfor_n(cs,n,&ms);
if (who == NULL) ms = 0; if (who == NULL) ms = 0;
elap = MSWAIT - ms; elap = MSWAIT - ms;
if (myrpt->tailtimer) myrpt->tailtimer -= elap; if (myrpt->tailtimer) myrpt->tailtimer -= elap;
@@ -535,15 +907,44 @@ pthread_attr_t attr;
char c; char c;
c = (char) f->subclass; /* get DTMF char */ c = (char) f->subclass; /* get DTMF char */
if ((!myrpt->callmode) && (c == '*')) if (!myrpt->simple)
{ {
myrpt->callmode = 1; if (c == '*')
myrpt->cidx = 0; {
myrpt->exten[myrpt->cidx] = 0; dtmfidx = 0;
pthread_attr_init(&attr); dtmfbuf[dtmfidx] = 0;
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); time(&dtmf_time);
pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt); continue;
continue; }
else if ((c != '#') && (dtmfidx >= 0))
{
time(&dtmf_time);
if (dtmfidx < MAXDTMF)
{
dtmfbuf[dtmfidx++] = c;
dtmfbuf[dtmfidx] = 0;
}
if (dtmfidx == FUNCTION_LEN)
{
process_dtmf(dtmfbuf,myrpt);
dtmfbuf[0] = 0;
dtmfidx = -1;
continue;
}
}
}
else
{
if ((!myrpt->callmode) && (c == '*'))
{
myrpt->callmode = 1;
myrpt->cidx = 0;
myrpt->exten[myrpt->cidx] = 0;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
continue;
}
} }
if (myrpt->callmode && (c == '#')) if (myrpt->callmode && (c == '#'))
{ {
@@ -595,9 +996,16 @@ pthread_attr_t attr;
{ {
if (debug) printf("@@@@ rx un-key\n"); if (debug) printf("@@@@ rx un-key\n");
keyed = 0; keyed = 0;
if (myrpt->remotemode != REM_OFF)
{
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&myrpt->rpt_proc_thread,&attr,rpt_remote_telemetry,(void *) myrpt);
}
} }
} }
ast_frfree(f); ast_frfree(f);
continue;
} }
if (who == myrpt->pchannel) /* if it was a read from pseudo */ if (who == myrpt->pchannel) /* if it was a read from pseudo */
{ {
@@ -610,6 +1018,8 @@ pthread_attr_t attr;
if (f->frametype == AST_FRAME_VOICE) if (f->frametype == AST_FRAME_VOICE)
{ {
ast_write(myrpt->txchannel,f); ast_write(myrpt->txchannel,f);
if (myrpt->remotemode == REM_TX)
ast_write(myrpt->rem_txchannel,f);
} }
if (f->frametype == AST_FRAME_CONTROL) if (f->frametype == AST_FRAME_CONTROL)
{ {
@@ -621,6 +1031,7 @@ pthread_attr_t attr;
} }
} }
ast_frfree(f); ast_frfree(f);
continue;
} }
if (who == myrpt->txchannel) /* if it was a read from tx */ if (who == myrpt->txchannel) /* if it was a read from tx */
{ {
@@ -640,12 +1051,95 @@ pthread_attr_t attr;
} }
} }
ast_frfree(f); ast_frfree(f);
continue;
}
if (who == myrpt->rem_rxchannel) /* if it was a read from rx */
{
f = ast_read(myrpt->rem_rxchannel);
if (!f)
{
if (debug) printf("@@@@ rpt:Hung Up\n");
break;
}
if (f->frametype == AST_FRAME_CONTROL)
{
if (f->subclass == AST_CONTROL_HANGUP)
{
if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
/* if RX key */
if (f->subclass == AST_CONTROL_RADIO_KEY)
{
if (debug) printf("@@@@ remote rx key\n");
if (!myrpt->remotetx)
{
myrpt->remoterx = 1;
ci.chan = 0;
ci.confno = myrpt->pconf;
ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
/* Put on conf */
if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
}
}
/* if RX un-key */
if (f->subclass == AST_CONTROL_RADIO_UNKEY)
{
if (debug) printf("@@@@ remote rx un-key\n");
if (!myrpt->remotetx)
{
myrpt->remoterx = 0;
ci.chan = 0;
ci.confno = 0;
ci.confmode = 0;
/* Take off conf */
if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
}
}
}
ast_frfree(f);
continue;
}
if (who == myrpt->rem_txchannel) /* if it was a read from remote tx */
{
f = ast_read(myrpt->rem_txchannel);
if (!f)
{
if (debug) printf("@@@@ rpt:Hung Up\n");
break;
}
if (f->frametype == AST_FRAME_CONTROL)
{
if (f->subclass == AST_CONTROL_HANGUP)
{
if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
}
ast_frfree(f);
continue;
} }
} }
ast_hangup(myrpt->pchannel); ast_hangup(myrpt->pchannel);
ast_hangup(myrpt->rxchannel); ast_hangup(myrpt->rxchannel);
ast_hangup(myrpt->txchannel); if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
if (myrpt->rem_rxchannel)
{
ast_hangup(myrpt->rem_rxchannel);
if (myrpt->rem_txchannel != myrpt->rem_rxchannel)
ast_hangup(myrpt->rem_txchannel);
}
if (debug) printf("@@@@ rpt:Hung up channel\n"); if (debug) printf("@@@@ rpt:Hung up channel\n");
pthread_exit(NULL); pthread_exit(NULL);
return NULL; return NULL;
@@ -675,6 +1169,8 @@ int i,n;
rpt_vars[n].name = this; rpt_vars[n].name = this;
rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel"); rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel");
rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel"); rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel");
rpt_vars[n].rem_rxchanname = ast_variable_retrieve(cfg,this,"remote_rxchannel");
rpt_vars[n].rem_txchanname = ast_variable_retrieve(cfg,this,"remote_txchannel");
rpt_vars[n].ourcontext = ast_variable_retrieve(cfg,this,"context"); rpt_vars[n].ourcontext = ast_variable_retrieve(cfg,this,"context");
if (!rpt_vars[n].ourcontext) rpt_vars[n].ourcontext = this; if (!rpt_vars[n].ourcontext) rpt_vars[n].ourcontext = this;
rpt_vars[n].ourcallerid = ast_variable_retrieve(cfg,this,"callerid"); rpt_vars[n].ourcallerid = ast_variable_retrieve(cfg,this,"callerid");
@@ -689,6 +1185,10 @@ int i,n;
val = ast_variable_retrieve(cfg,this,"idtime"); val = ast_variable_retrieve(cfg,this,"idtime");
if (val) rpt_vars[n].idtime = atoi(val); if (val) rpt_vars[n].idtime = atoi(val);
else rpt_vars[n].idtime = IDTIME; else rpt_vars[n].idtime = IDTIME;
val = ast_variable_retrieve(cfg,this,"simple");
if (val) rpt_vars[n].simple = ast_true(val);
else rpt_vars[n].simple = 0;
rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone");
n++; n++;
} }
ast_log(LOG_DEBUG, "Total of %d repeaters configured.\n",n); ast_log(LOG_DEBUG, "Total of %d repeaters configured.\n",n);

View File

@@ -5676,11 +5676,15 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio)
p.debouncetime = cur_debounce; p.debouncetime = cur_debounce;
} }
res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_SET_PARAMS, &p); /* dont set parms on a pseudo-channel */
if (res < 0) { if (tmp->subs[SUB_REAL].zfd >= 0)
ast_log(LOG_ERROR, "Unable to set parameters\n"); {
free(tmp); res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_SET_PARAMS, &p);
return NULL; if (res < 0) {
ast_log(LOG_ERROR, "Unable to set parameters\n");
free(tmp);
return NULL;
}
} }
#if 1 #if 1
if (!here && (tmp->subs[SUB_REAL].zfd > -1)) { if (!here && (tmp->subs[SUB_REAL].zfd > -1)) {

View File

@@ -1,4 +1,4 @@
; Radio Repeater configuration file (for use with app_rpt) ; Radio Repeater / Remote Base configuration file (for use with app_rpt)
; ;
;[oakhurst] ; Name of First Repeater ;[oakhurst] ; Name of First Repeater
@@ -7,8 +7,14 @@
; Note: if you use a unified interface (tx/rx on one channel), only ; Note: if you use a unified interface (tx/rx on one channel), only
; specify the rxchannel and the txchannel will be assumed from the rxchannel ; specify the rxchannel and the txchannel will be assumed from the rxchannel
;txchannel = Zap/2 ; Tx audio/signalling channel ;txchannel = Zap/2 ; Tx audio/signalling channel
;remote_rxchannel = Zap/3 ; Remote Base Rx audio/signalling channel
; Note: if you use a unified interface (tx/rx on one channel), only
; specify the remote_rxchannel and the remote_txchannel will be assumed from the rxchannel
;remote_txchannel = Zap/4 ; Remote Base Tx audio/signalling channel
;tonezone = us ; use US tones
;simple = no ; Not in "simple" mode
;context = default ; dialing context for phone ;context = default ; dialing context for phone
;callerid = "WB6NIL Repeater" <(818) 325-2757> ; Callerid for phone calls ;callerid = "WB6NIL Repeater" <(559) 692-1234> ; Callerid for phone calls
;idrecording = wb6nil ; id recording ;idrecording = wb6nil ; id recording
;accountcode=RADIO ; account code (optional) ;accountcode=RADIO ; account code (optional)
;hangtime=1000 ; squelch tail hang time (in ms) (optional) ;hangtime=1000 ; squelch tail hang time (in ms) (optional)

4
dsp.c
View File

@@ -123,7 +123,11 @@ static struct progress {
#define FAX_THRESHOLD 8.0e7 #define FAX_THRESHOLD 8.0e7
#define FAX_2ND_HARMONIC 2.0 /* 4dB */ #define FAX_2ND_HARMONIC 2.0 /* 4dB */
#define DTMF_NORMAL_TWIST 6.3 /* 8dB */ #define DTMF_NORMAL_TWIST 6.3 /* 8dB */
#ifdef RADIO_RELAX
#define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 6.5 : 2.5) /* 4dB normal */
#else
#define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5) /* 4dB normal */ #define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5) /* 4dB normal */
#endif
#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ #define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ #define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
#define DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5) /* 4dB normal */ #define DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5) /* 4dB normal */