aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/app_rpt.c14977
-rw-r--r--channels/Makefile6
-rw-r--r--channels/chan_usbradio.c3706
-rwxr-xr-xchannels/xpmr/sinetabx.h30
-rwxr-xr-xchannels/xpmr/xpmr.c2254
-rwxr-xr-xchannels/xpmr/xpmr.h620
-rwxr-xr-xchannels/xpmr/xpmr_coef.h344
7 files changed, 16187 insertions, 5750 deletions
diff --git a/apps/app_rpt.c b/apps/app_rpt.c
index cf64d12d4..fa8a563cb 100644
--- a/apps/app_rpt.c
+++ b/apps/app_rpt.c
@@ -1,7 +1,9 @@
+#define NEW_ASTERISK
+/* #define OLD_ASTERISK */
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2002-2005, Jim Dixon, WB6NIL
+ * Copyright (C) 2002-2008, Jim Dixon, WB6NIL
*
* Jim Dixon, WB6NIL <jim@lambdatel.com>
* Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
@@ -16,16 +18,16 @@
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
-
/*! \file
*
* \brief Radio Repeater / Remote Base program
- * version 0.48 06/13/06
+ * version 0.115 5/12/08 2055 EDT
*
* \author Jim Dixon, WB6NIL <jim@lambdatel.com>
*
* \note Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
- *
+ * \note Steven Henke, W9SH, <w9sh@arrl.net> added a few features here and there.
+ *
* See http://www.zapatatelephony.org/app_rpt.html
*
*
@@ -51,18 +53,43 @@
*
* status cmds:
*
- * 1 - Force ID
- * 2 - Give Time of Day
- * 3 - Give software Version
+ * 1 - Force ID (global)
+ * 2 - Give Time of Day (global)
+ * 3 - Give software Version (global)
+ * 11 - Force ID (local only)
+ * 12 - Give Time of Day (local only)
*
* cop (control operator) cmds:
*
* 1 - System warm boot
* 2 - System enable
* 3 - System disable
- * 4 - Test Tone On
+ * 4 - Test Tone On/Off
* 5 - Dump System Variables on Console (debug)
* 6 - PTT (phone mode only)
+ * 7 - Time out timer enable
+ * 8 - Time out timer disable
+ * 9 - Autopatch enable
+ * 10 - Autopatch disable
+ * 11 - Link enable
+ * 12 - Link disable
+ * 13 - Query System State
+ * 14 - Change System State
+ * 15 - Scheduler Enable
+ * 16 - Scheduler Disable
+ * 17 - User functions (time, id, etc) enable
+ * 18 - User functions (time, id, etc) disable
+ * 19 - Select alternate hang timer
+ * 20 - Select standard hang timer
+ * 21 - Enable Parrot Mode
+ * 22 - Disable Parrot Mode
+ * 23 - Birdbath (Current Parrot Cleanup/Flush)
+ * 24 - Flush all telemetry
+ * 25 - Query last node un-keyed
+ * 26 - Query all nodes keyed/unkeyed
+ * 30 - Recall Memory Setting in Attached Xcvr
+ * 31 - Channel Selector for Parallel Programmed Xcvr
+ * 32 - Touchtone pad test: command + Digit string + # to playback all digits pressed
*
* ilink cmds:
*
@@ -72,6 +99,12 @@
* 4 - Enter command mode on specified link
* 5 - System status
* 6 - Disconnect all links
+ * 11 - Disconnect a previously permanently connected link
+ * 12 - Permanently connect specified link -- monitor only
+ * 13 - Permanently connect specified link -- tranceive
+ * 15 - Full system status (all nodes)
+ * 16 - Reconnect links disconnected with "disconnect all links"
+ * 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)
*
* remote cmds:
*
@@ -102,7 +135,10 @@
* 118 - Scan Up Fast
* 119 - Transmit allowing auto-tune
* 140 - Link Status (brief)
+ * 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)
*
+ * playback cmds:
+ * specify the name of the file to be played (for example, 25=rpt/foo)
*
*
* 'duplex' modes: (defaults to duplex=2)
@@ -131,14 +167,33 @@
/* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
+#ifdef OLD_ASTERISK
+#define ast_free free
+#define ast_malloc malloc
+#define ast_strdup strdup
+#endif
+
+
#define MAXDTMF 32
#define MAXMACRO 2048
-#define MAXGOSUB 2048
+#define MAXLINKLIST 512
+#define LINKLISTTIME 10000
+#define LINKLISTSHORTTIME 200
+#define LINKPOSTTIME 30000
+#define LINKPOSTSHORTTIME 200
+#define KEYPOSTTIME 30000
+#define KEYPOSTSHORTTIME 200
#define MACROTIME 100
-#define GOSUBTIME 100
#define MACROPTIME 500
-#define GOSUBPTIME 500
#define DTMF_TIMEOUT 3
+#define KENWOOD_RETRIES 5
+#define TOPKEYN 32
+#define TOPKEYWAIT 3
+#define TOPKEYMAXSTR 30
+
+#define AUTHTELLTIME 7000
+#define AUTHTXTIME 1000
+#define AUTHLOGOUTTIME 25000
#ifdef __RPT_NOTCH
#define MAXFILTERS 10
@@ -146,33 +201,64 @@
#define DISC_TIME 10000 /* report disc after 10 seconds of no connect */
#define MAX_RETRIES 5
+#define MAX_RETRIES_PERM 1000000000
#define REDUNDANT_TX_TIME 2000
#define RETRY_TIMER_MS 5000
+#define PATCH_DIALPLAN_TIMEOUT 1500
+
+#ifdef OLD_ASTERISK
+#define START_DELAY 10
+#else
+#define START_DELAY 2
+#endif
+
+#define RPT_LOCKOUT_SECS 10
+
#define MAXPEERSTR 31
#define MAXREMSTR 15
#define DELIMCHR ','
#define QUOTECHR 34
+#define MONITOR_DISK_BLOCKS_PER_MINUTE 38
+
+#define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
+#define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
+#define DEFAULT_REMOTE_TIMEOUT (60 * 60)
+#define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
+#define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
+
#define NODES "nodes"
+#define EXTNODES "extnodes"
#define MEMORY "memory"
#define MACRO "macro"
-#define GOSUB "gosub"
#define FUNCTIONS "functions"
#define TELEMETRY "telemetry"
#define MORSE "morse"
+#define TONEMACRO "tonemacro"
#define FUNCCHAR '*'
#define ENDCHAR '#'
+#define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
+#define NODENAMES "rpt/nodenames"
+#define PARROTFILE "/tmp/parrot_%s_%u"
+
+#define PARROTTIME 1000
#define DEFAULT_IOBASE 0x378
+#define DEFAULT_CIV_ADDR 0x58
+
#define MAXCONNECTTIME 5000
#define MAXNODESTR 300
+#define MAXNODELEN 16
+
+#define MAXIDENTLEN 32
+
#define MAXPATCHCONTEXT 100
#define ACTIONSIZE 32
@@ -181,69 +267,122 @@
#define REM_SCANTIME 100
+#define DTMF_LOCAL_TIME 250
+#define DTMF_LOCAL_STARTTIME 500
-enum {REM_OFF, REM_MONITOR, REM_TX};
+#define IC706_PL_MEMORY_OFFSET 50
-enum {ID, PROC, TERM, COMPLETE, UNKEY, REMDISC, REMALREADY, REMNOTFOUND, REMGO,
- CONNECTED, CONNFAIL, STATUS, TIMEOUT, ID1, STATS_TIME,
+#define VOX_ON_DEBOUNCE_COUNT 3
+#define VOX_OFF_DEBOUNCE_COUNT 20
+#define VOX_MAX_THRESHOLD 10000.0
+#define VOX_MIN_THRESHOLD 3000.0
+#define VOX_TIMEOUT_MS 5000
+#define VOX_RECOVER_MS 500
+#define SIMPLEX_PATCH_DELAY 25
+#define SIMPLEX_PHONE_DELAY 25
+
+#define STATPOST_PROGRAM "/usr/bin/wget,-q,--output-document=/dev/null,--no-check-certificate"
+
+#define ALLOW_LOCAL_CHANNELS
+
+enum {REM_OFF,REM_MONITOR,REM_TX};
+
+enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
+ CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, PLAYBACK,
STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
- TAILMSG, MACRO_NOTFOUND, GOSUB_NOTFOUND, MACRO_BUSY, GOSUB_BUSY, LASTNODEKEY};
+ TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
+ MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
+ REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE, TOPKEY,
+ TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX, PARROT,
+ STATS_TIME_LOCAL};
-enum {REM_SIMPLEX, REM_MINUS, REM_PLUS};
-enum {REM_LOWPWR, REM_MEDPWR, REM_HIPWR};
+enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
-enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_DOKEY};
+enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
-enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE};
+enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
-enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM};
+enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE, SOURCE_ALT};
-enum {REM_MODE_FM, REM_MODE_USB, REM_MODE_LSB, REM_MODE_AM};
+enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY, DLY_PARROT};
-enum {HF_SCAN_OFF, HF_SCAN_DOWN_SLOW, HF_SCAN_DOWN_QUICK,
- HF_SCAN_DOWN_FAST, HF_SCAN_UP_SLOW, HF_SCAN_UP_QUICK, HF_SCAN_UP_FAST};
+enum {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};
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
#include <search.h>
+#include <sys/types.h>
#include <sys/stat.h>
+#include <errno.h>
#include <dirent.h>
#include <ctype.h>
+#include <sys/stat.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/io.h>
+#include <sys/vfs.h>
#include <math.h>
+#ifdef OLD_ASTERISK
+#include <linux/zaptel.h>
+#include <tonezone.h>
+#else
+#include <zaptel/zaptel.h>
+#include <zaptel/tonezone.h>
+#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
+#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/callerid.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/features.h"
+#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/localtime.h"
-#include "asterisk/app.h"
+#include "asterisk/cdr.h"
+#include "asterisk/options.h"
+#include "asterisk/manager.h"
+#include <termios.h>
+
+#ifdef NEW_ASTERISK
+struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
+#endif
+
-#include "asterisk/zapata.h"
+/* Start a tone-list going */
+int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
+/*! Stop the tones from playing */
+void ast_playtones_stop(struct ast_channel *chan);
+
+static char *tdesc = "Radio Repeater / Remote Base version 0.115 5/12/2008";
static char *app = "Rpt";
static char *synopsis = "Radio Repeater/Remote Base Control System";
static char *descrip =
-" Rpt(nodename[,options]): Radio Remote Link or Remote Base Link Endpoint Process.\n"
+" Rpt(nodename[|options][|M][|*]): \n"
+" Radio Remote Link or Remote Base Link Endpoint Process.\n"
"\n"
" Not specifying an option puts it in normal endpoint mode (where source\n"
" IP and nodename are verified).\n"
@@ -254,7 +393,7 @@ static char *descrip =
" this if you have checked security already (like with an IAX2\n"
" user/password or something).\n"
"\n"
-" Rannounce-string[,timeout[,timeout-destination]] - Amateur Radio\n"
+" Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
" Reverse Autopatch. Caller is put on hold, and announcement (as\n"
" specified by the 'announce-string') is played on radio system.\n"
" Users of radio system can access autopatch, dial specified\n"
@@ -275,17 +414,66 @@ static char *descrip =
" this mode), the 'dphone_functions' parameter must be specified\n"
" for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
" available to the phone user.\n"
+"\n"
+" S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
+" audio-only access to the radio system. In this mode, the\n"
+" transmitter is toggled on and off when the phone user presses the\n"
+" funcchar (*) key on the telephone set. In addition, the transmitter\n"
+" will turn off if the endchar (#) key is pressed. When a user first\n"
+" calls in, the transmitter will be off, and the user can listen for\n"
+" radio traffic. When the user wants to transmit, they press the *\n"
+" key, start talking, then press the * key again or the # key to turn\n"
+" the transmitter off. No other functions can be executed by the\n"
+" user on the phone when this mode is selected. Note: If your\n"
+" radio system is full-duplex, we recommend using either P or D\n"
+" modes as they provide more flexibility.\n"
+"\n"
+" q - Query Status. Sets channel variables and returns + 101 in plan.\n"
+"\n"
+" M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
+"\n"
+" * - Alt Macro to execute (e.g. *7 for status)\n"
"\n";
+;
-static unsigned int vmajor = 0;
-static unsigned int vminor = 47;
-
-static int debug = 0; /* FIXME Set this >0 for extra debug output */
+static int debug = 0; /* Set this >0 for extra debug output */
static int nrpts = 0;
+static char remdtmfstr[] = "0123456789*#ABCD";
+
+enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
+
+int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
+
+#define NRPTSTAT 7
+
+struct rpt_chan_stat
+{
+ struct timeval last;
+ long long total;
+ unsigned long count;
+ unsigned long largest;
+ struct timeval largest_time;
+};
+
char *discstr = "!!DISCONNECT!!";
-static char *remote_rig_ft897 = "ft897";
-static char *remote_rig_rbi = "rbi";
+char *newkeystr = "!NEWKEY!";
+static char *remote_rig_ft897="ft897";
+static char *remote_rig_rbi="rbi";
+static char *remote_rig_kenwood="kenwood";
+static char *remote_rig_tm271="tm271";
+static char *remote_rig_ic706="ic706";
+static char *remote_rig_rtx150="rtx150";
+static char *remote_rig_rtx450="rtx450";
+static char *remote_rig_ppp16="ppp16"; // parallel port programmable 16 channels
+
+#define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
+#define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
+
+#ifdef OLD_ASTERISK
+STANDARD_LOCAL_USER;
+LOCAL_USER_DECL;
+#endif
#define MSWAIT 200
#define HANGTIME 5000
@@ -296,9 +484,44 @@ static char *remote_rig_rbi = "rbi";
#define POLITEID 30000
#define FUNCTDELAY 1500
-static pthread_t rpt_master_thread;
+#define MAXXLAT 20
+#define MAXXLATTIME 3
+
+#define MAX_SYSSTATES 10
+
+struct vox {
+ float speech_energy;
+ float noise_energy;
+ int enacount;
+ char voxena;
+ char lastvox;
+ int offdebcnt;
+ int ondebcnt;
+} ;
+
+#define mymax(x,y) ((x > y) ? x : y)
+#define mymin(x,y) ((x < y) ? x : y)
+
+struct rpt_topkey
+{
+char node[TOPKEYMAXSTR];
+int timesince;
+int keyed;
+} ;
-struct timeval cancel_atimeout = { 0, 0 };
+struct rpt_xlat
+{
+char funccharseq[MAXXLAT];
+char endcharseq[MAXXLAT];
+char passchars[MAXXLAT];
+int funcindex;
+int endindex;
+time_t lastone;
+} ;
+
+static time_t starttime = 0;
+
+static pthread_t rpt_master_thread;
struct rpt;
@@ -309,11 +532,17 @@ struct rpt_link
char mode; /* 1 if in tx mode */
char isremote;
char phonemode;
+ char phonevox; /* vox the phone */
char name[MAXNODESTR]; /* identifier (routing) string */
char lasttx;
+ char lasttx1;
char lastrx;
+ char lastrealrx;
+ char lastrx1;
char connected;
char hasconnected;
+ char perma;
+ char thisconnected;
char outbound;
char disced;
char killme;
@@ -321,11 +550,31 @@ struct rpt_link
long disctime;
long retrytimer;
long retxtimer;
+ long rerxtimer;
int retries;
+ int max_retries;
int reconnects;
long long connecttime;
struct ast_channel *chan;
struct ast_channel *pchan;
+ char linklist[MAXLINKLIST];
+ time_t linklistreceived;
+ long linklisttimer;
+ int dtmfed;
+ int linkunkeytocttimer;
+ struct timeval lastlinktv;
+ struct ast_frame *lastf1,*lastf2;
+ struct rpt_chan_stat chan_stat[NRPTSTAT];
+ struct vox vox;
+ char wasvox;
+ int voxtotimer;
+ char voxtostate;
+ char newkey;
+#ifdef OLD_ASTERISK
+ AST_LIST_HEAD(, ast_frame) rxq;
+#else
+ AST_LIST_HEAD_NOLOCK(, ast_frame) rxq;
+#endif
} ;
struct rpt_lstat
@@ -337,7 +586,9 @@ struct rpt_lstat
char mode;
char outbound;
char reconnects;
+ char thisconnected;
long long connecttime;
+ struct rpt_chan_stat chan_stat[NRPTSTAT];
} ;
struct rpt_tele
@@ -349,6 +600,8 @@ struct rpt_tele
int mode;
struct rpt_link mylink;
char param[TELEPARAMSIZE];
+ int submode;
+ unsigned int parrot;
pthread_t threadid;
} ;
@@ -374,85 +627,163 @@ struct telem_defaults
} ;
+struct sysstate
+{
+ char txdisable;
+ char totdisable;
+ char linkfundisable;
+ char autopatchdisable;
+ char schedulerdisable;
+ char userfundisable;
+ char alternatetail;
+};
+
+/* rpt cmd support */
+#define CMD_DEPTH 1
+#define CMD_STATE_IDLE 0
+#define CMD_STATE_BUSY 1
+#define CMD_STATE_READY 2
+#define CMD_STATE_EXECUTING 3
+
+struct rpt_cmd_struct
+{
+ int state;
+ int functionNumber;
+ char param[MAXDTMF];
+ char digits[MAXDTMF];
+ int command_source;
+};
+
static struct rpt
{
ast_mutex_t lock;
+ ast_mutex_t remlock;
+ ast_mutex_t statpost_lock;
struct ast_config *cfg;
char reload;
+ char xlink; // cross link state of a share repeater/remote radio
+ unsigned int statpost_seqno;
char *name;
char *rxchanname;
char *txchanname;
- char *remote;
+ char remote;
+ char *remoterig;
+ struct rpt_chan_stat chan_stat[NRPTSTAT];
+ unsigned int scram;
struct {
- char ourcontext[80];
- char ourcallerid[80];
- char acctcode[21];
- char ident[80];
- char tonezone[80];
+ char *ourcontext;
+ char *ourcallerid;
+ char *acctcode;
+ char *ident;
+ char *tonezone;
char simple;
- char functions[80];
- char link_functions[80];
- char phone_functions[80];
- char dphone_functions[80];
- char nodes[80];
+ char *functions;
+ char *link_functions;
+ char *phone_functions;
+ char *dphone_functions;
+ char *alt_functions;
+ char *nodes;
+ char *extnodes;
+ char *extnodefile;
int hangtime;
+ int althangtime;
int totime;
int idtime;
int tailmessagetime;
int tailsquashedtime;
int duplex;
int politeid;
- char *tailmsgbuf;
- AST_DECLARE_APP_ARGS(tailmsg,
- AST_APP_ARG(msgs)[100];
- );
- char memory[80];
- char macro[80];
- char gosub[80];
- char startupmacro[80];
- char startupgosub[80];
+ char *tailmessages[500];
+ int tailmessagemax;
+ char *memory;
+ char *macro;
+ char *tonemacro;
+ char *startupmacro;
int iobase;
+ char *ioport;
char funcchar;
char endchar;
char nobusyout;
+ char notelemtx;
+ char propagate_dtmf;
+ char propagate_phonedtmf;
+ char linktolink;
+ unsigned char civaddr;
+ struct rpt_xlat inxlat;
+ struct rpt_xlat outxlat;
+ char *archivedir;
+ int authlevel;
+ char *csstanzaname;
+ char *skedstanzaname;
+ char *txlimitsstanzaname;
+ long monminblocks;
+ int remoteinacttimeout;
+ int remotetimeout;
+ int remotetimeoutwarning;
+ int remotetimeoutwarningfreq;
+ int sysstate_cur;
+ struct sysstate s[MAX_SYSSTATES];
+ char parrotmode;
+ int parrottime;
+ char *rptnode;
+ char remote_mars;
+ int voxtimeout_ms;
+ int voxrecover_ms;
+ int simplexpatchdelay;
+ int simplexphonedelay;
+ char *statpost_program;
+ char *statpost_url;
} p;
struct rpt_link links;
int unkeytocttimer;
+ time_t lastkeyedtime;
+ time_t lasttxkeyedtime;
char keyed;
+ char txkeyed;
char exttx;
char localtx;
char remoterx;
char remotetx;
char remoteon;
+ char remtxfreqok;
char tounkeyed;
char tonotify;
- char enable;
char dtmfbuf[MAXDTMF];
char macrobuf[MAXMACRO];
- char gosubbuf[MAXGOSUB];
char rem_dtmfbuf[MAXDTMF];
char lastdtmfcommand[MAXDTMF];
char cmdnode[50];
- struct ast_channel *rxchannel, *txchannel;
- struct ast_channel *pchannel, *txpchannel, *remchannel;
+ char nowchan; // channel now
+ char waschan; // channel selected initially or by command
+ char bargechan; // barge in channel
+ char macropatch; // autopatch via tonemacro state
+ char parrotstate;
+ int parrottimer;
+ unsigned int parrotcnt;
+ struct ast_channel *rxchannel,*txchannel, *monchannel, *parrotchannel;
+ struct ast_channel *pchannel,*txpchannel, *zaprxchannel, *zaptxchannel;
+ struct ast_channel *voxchannel;
+ struct ast_frame *lastf1,*lastf2;
struct rpt_tele tele;
- struct timeval lasttv, curtv;
- pthread_t rpt_call_thread, rpt_thread;
- time_t dtmf_time, rem_dtmf_time, dtmf_time_rem;
- int tailtimer, totimer, idtimer, txconf, conf, callmode, cidx, scantimer, tmsgtimer, skedtimer;
- int mustid, tailid;
+ struct timeval lasttv,curtv;
+ pthread_t rpt_call_thread,rpt_thread;
+ time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
+ int calldigittimer;
+ int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
+ int mustid,tailid;
int tailevent;
int telemrefcount;
- int dtmfidx, rem_dtmfidx;
- int dailytxtime, dailykerchunks, totalkerchunks, dailykeyups, totalkeyups, timeouts;
+ int dtmfidx,rem_dtmfidx;
+ int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
int totalexecdcommands, dailyexecdcommands;
- long retxtimer;
+ long retxtimer;
+ long rerxtimer;
long long totaltxtime;
char mydtmf;
char exten[AST_MAX_EXTENSION];
- char freq[MAXREMSTR], rxpl[MAXREMSTR], txpl[MAXREMSTR];
+ char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
char offset;
char powerlevel;
char txplon;
@@ -461,16 +792,18 @@ static struct rpt
char tunerequest;
char hfscanmode;
int hfscanstatus;
+ char hfscanstop;
char lastlinknode[MAXNODESTR];
- char stopgen;
+ char savednodes[MAXNODESTR];
+ int stopgen;
char patchfarenddisconnect;
char patchnoct;
char patchquiet;
char patchcontext[MAXPATCHCONTEXT];
int patchdialtime;
int macro_longest;
- int gosub_longest;
int phone_longestfunc;
+ int alt_longestfunc;
int dphone_longestfunc;
int link_longestfunc;
int longestfunc;
@@ -479,31 +812,80 @@ static struct rpt
int tailmessagen;
time_t disgorgetime;
time_t lastthreadrestarttime;
- long macrotimer;
- long gosubtimer;
- char lastnodewhichkeyedusup[MAXNODESTR];
+ long macrotimer;
+ char lastnodewhichkeyedusup[MAXNODESTR];
+ int dtmf_local_timer;
+ char dtmf_local_str[100];
+ struct ast_filestream *monstream,*parrotstream;
+ char loginuser[50];
+ char loginlevel[10];
+ long authtelltimer;
+ long authtimer;
+ int iofd;
+ time_t start_time,last_activity_time;
+ char lasttone[32];
+ struct rpt_tele *active_telem;
+ struct rpt_topkey topkey[TOPKEYN];
+ int topkeystate;
+ time_t topkeytime;
+ int topkeylong;
+ struct vox vox;
+ char wasvox;
+ int voxtotimer;
+ char voxtostate;
+ int linkposttimer;
+ int keyposttimer;
+ char newkey;
+ char inpadtest;
+#ifdef OLD_ASTERISK
+ AST_LIST_HEAD(, ast_frame) txq;
+#else
+ AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
+#endif
+ char txrealkeyed;
#ifdef __RPT_NOTCH
struct rptfilter
{
- char desc[100];
- float x0;
- float x1;
- float x2;
- float y0;
- float y1;
- float y2;
- float gain;
- float const0;
- float const1;
- float const2;
+ char desc[100];
+ float x0;
+ float x1;
+ float x2;
+ float y0;
+ float y1;
+ float y2;
+ float gain;
+ float const0;
+ float const1;
+ float const2;
} filters[MAXFILTERS];
#endif
#ifdef _MDC_DECODE_H_
mdc_decoder_t *mdc;
unsigned short lastunit;
#endif
+ struct rpt_cmd_struct cmdAction;
} rpt_vars[MAXRPTS];
+struct nodelog {
+struct nodelog *next;
+struct nodelog *prev;
+time_t timestamp;
+char archivedir[MAXNODESTR];
+char str[MAXNODESTR * 2];
+} nodelog;
+
+static int service_scan(struct rpt *myrpt);
+static int set_mode_ft897(struct rpt *myrpt, char newmode);
+static int set_mode_ic706(struct rpt *myrpt, char newmode);
+static int simple_command_ft897(struct rpt *myrpt, char command);
+static int setrem(struct rpt *myrpt);
+static int setrtx_check(struct rpt *myrpt);
+static int channel_revert(struct rpt *myrpt);
+static int channel_steer(struct rpt *myrpt, char *data);
+
+AST_MUTEX_DEFINE_STATIC(nodeloglock);
+
+AST_MUTEX_DEFINE_STATIC(nodelookuplock);
#ifdef APP_RPT_LOCK_DEBUG
@@ -511,8 +893,8 @@ static struct rpt
#define MAXLOCKTHREAD 100
-#define rpt_mutex_lock(x) _rpt_mutex_lock(x, myrpt, __LINE__)
-#define rpt_mutex_unlock(x) _rpt_mutex_unlock(x, myrpt, __LINE__)
+#define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
+#define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
struct lockthread
{
@@ -531,40 +913,42 @@ struct by_lightning
struct lockthread lockthread;
} lock_ring[32];
-
int lock_ring_index = 0;
AST_MUTEX_DEFINE_STATIC(locklock);
static struct lockthread *get_lockthread(pthread_t id)
{
- int i;
+int i;
- for (i = 0; i < MAXLOCKTHREAD; i++) {
- if (lockthreads[i].id == id)
- return(&lockthreads[i]);
+ for(i = 0; i < MAXLOCKTHREAD; i++)
+ {
+ if (lockthreads[i].id == id) return(&lockthreads[i]);
}
- return NULL;
+ return(NULL);
}
static struct lockthread *put_lockthread(pthread_t id)
{
- int i;
+int i;
- for (i = 0; i < MAXLOCKTHREAD; i++) {
+ for(i = 0; i < MAXLOCKTHREAD; i++)
+ {
if (lockthreads[i].id == id)
return(&lockthreads[i]);
}
- for (i = 0; i < MAXLOCKTHREAD; i++) {
- if (!lockthreads[i].id) {
+ for(i = 0; i < MAXLOCKTHREAD; i++)
+ {
+ if (!lockthreads[i].id)
+ {
lockthreads[i].lockcount = 0;
lockthreads[i].lastlock = 0;
lockthreads[i].lastunlock = 0;
lockthreads[i].id = id;
- return &lockthreads[i];
+ return(&lockthreads[i]);
}
}
- return NULL;
+ return(NULL);
}
@@ -572,10 +956,9 @@ static void rpt_mutex_spew(void)
{
struct by_lightning lock_ring_copy[32];
int lock_ring_index_copy;
- int i, j;
+ int i,j;
long long diff;
- char a[100] = "";
- struct ast_tm tm;
+ char a[100];
struct timeval lasttv;
ast_mutex_lock(&locklock);
@@ -584,27 +967,30 @@ static void rpt_mutex_spew(void)
ast_mutex_unlock(&locklock);
lasttv.tv_sec = lasttv.tv_usec = 0;
- for (i = 0; i < 32; i++) {
+ for(i = 0 ; i < 32 ; i++)
+ {
j = (i + lock_ring_index_copy) % 32;
- ast_strftime(a, sizeof(a) - 1, "%m/%d/%Y %H:%M:%S",
- ast_localtime(&lock_ring_copy[j].tv, &tm, NULL));
+ strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
+ localtime(&lock_ring_copy[j].tv.tv_sec));
diff = 0;
- if (lasttv.tv_sec) {
- diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec) * 1000000;
+ if(lasttv.tv_sec)
+ {
+ diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
+ * 1000000;
diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
}
lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
- if (!lock_ring_copy[j].tv.tv_sec)
- continue;
- if (lock_ring_copy[j].line < 0) {
- ast_log(LOG_NOTICE, "LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
- i - 31, -lock_ring_copy[j].line, lock_ring_copy[j].rpt->name,
- (int) lock_ring_copy[j].lockthread.id, diff, a, (int)lock_ring_copy[j].tv.tv_usec);
- } else {
- ast_log(LOG_NOTICE, "LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
- i - 31, lock_ring_copy[j].line, lock_ring_copy[j].rpt->name,
- (int) lock_ring_copy[j].lockthread.id, diff, a, (int)lock_ring_copy[j].tv.tv_usec);
+ if (!lock_ring_copy[j].tv.tv_sec) continue;
+ if (lock_ring_copy[j].line < 0)
+ {
+ ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
+ i - 31,-lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
+ }
+ else
+ {
+ ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
+ i - 31,lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
}
}
}
@@ -612,21 +998,22 @@ static void rpt_mutex_spew(void)
static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
{
- struct lockthread *t;
- pthread_t id;
+struct lockthread *t;
+pthread_t id;
id = pthread_self();
ast_mutex_lock(&locklock);
t = put_lockthread(id);
- if (!t) {
+ if (!t)
+ {
ast_mutex_unlock(&locklock);
return;
}
- if (t->lockcount) {
+ if (t->lockcount)
+ {
int lastline = t->lastlock;
ast_mutex_unlock(&locklock);
- ast_log(LOG_NOTICE, "rpt_mutex_lock: Double lock request line %d node %s pid %x, last lock was line %d\n",
- line, myrpt->name, (int) t->id, lastline);
+ ast_log(LOG_NOTICE,"rpt_mutex_lock: Double lock request line %d node %s pid %x, last lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
rpt_mutex_spew();
return;
}
@@ -634,9 +1021,9 @@ static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
t->lockcount = 1;
gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
lock_ring[lock_ring_index].rpt = myrpt;
- memcpy(&lock_ring[lock_ring_index].lockthread, t, sizeof(struct lockthread));
+ memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
lock_ring[lock_ring_index++].line = line;
- if (lock_ring_index == 32)
+ if(lock_ring_index == 32)
lock_ring_index = 0;
ast_mutex_unlock(&locklock);
ast_mutex_lock(lockp);
@@ -645,21 +1032,22 @@ static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
{
- struct lockthread *t;
- pthread_t id;
+struct lockthread *t;
+pthread_t id;
id = pthread_self();
ast_mutex_lock(&locklock);
t = put_lockthread(id);
- if (!t) {
+ if (!t)
+ {
ast_mutex_unlock(&locklock);
return;
}
- if (!t->lockcount) {
+ if (!t->lockcount)
+ {
int lastline = t->lastunlock;
ast_mutex_unlock(&locklock);
- ast_log(LOG_NOTICE, "rpt_mutex_lock: Double un-lock request line %d node %s pid %x, last un-lock was line %d\n",
- line, myrpt->name, (int) t->id, lastline);
+ ast_log(LOG_NOTICE,"rpt_mutex_lock: Double un-lock request line %d node %s pid %x, last un-lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
rpt_mutex_spew();
return;
}
@@ -667,9 +1055,9 @@ static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
t->lockcount = 0;
gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
lock_ring[lock_ring_index].rpt = myrpt;
- memcpy(&lock_ring[lock_ring_index].lockthread, t, sizeof(struct lockthread));
+ memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
lock_ring[lock_ring_index++].line = -line;
- if (lock_ring_index == 32)
+ if(lock_ring_index == 32)
lock_ring_index = 0;
ast_mutex_unlock(&locklock);
ast_mutex_unlock(lockp);
@@ -683,25 +1071,205 @@ static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
#endif /* APP_RPT_LOCK_DEBUG */
/*
+* Return 1 if rig is multimode capable
+*/
+
+static int multimode_capable(struct rpt *myrpt)
+{
+ if(!strcmp(myrpt->remoterig, remote_rig_ft897))
+ return 1;
+ if(!strcmp(myrpt->remoterig, remote_rig_ic706))
+ return 1;
+ return 0;
+}
+
+static void voxinit_rpt(struct rpt *myrpt,char enable)
+{
+
+ myrpt->vox.speech_energy = 0.0;
+ myrpt->vox.noise_energy = 0.0;
+ myrpt->vox.enacount = 0;
+ myrpt->vox.voxena = 0;
+ if (!enable) myrpt->vox.voxena = -1;
+ myrpt->vox.lastvox = 0;
+ myrpt->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
+ myrpt->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
+ myrpt->wasvox = 0;
+ myrpt->voxtotimer = 0;
+ myrpt->voxtostate = 0;
+}
+
+static void voxinit_link(struct rpt_link *mylink,char enable)
+{
+
+ mylink->vox.speech_energy = 0.0;
+ mylink->vox.noise_energy = 0.0;
+ mylink->vox.enacount = 0;
+ mylink->vox.voxena = 0;
+ if (!enable) mylink->vox.voxena = -1;
+ mylink->vox.lastvox = 0;
+ mylink->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
+ mylink->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
+ mylink->wasvox = 0;
+ mylink->voxtotimer = 0;
+ mylink->voxtostate = 0;
+}
+
+static int dovox(struct vox *v,short *buf,int bs)
+{
+
+ int i;
+ float esquare = 0.0;
+ float energy = 0.0;
+ float threshold = 0.0;
+
+ if (v->voxena < 0) return(v->lastvox);
+ for(i = 0; i < bs; i++)
+ {
+ esquare += (float) buf[i] * (float) buf[i];
+ }
+ energy = sqrt(esquare);
+
+ if (energy >= v->speech_energy)
+ v->speech_energy += (energy - v->speech_energy) / 4;
+ else
+ v->speech_energy += (energy - v->speech_energy) / 64;
+
+ if (energy >= v->noise_energy)
+ v->noise_energy += (energy - v->noise_energy) / 64;
+ else
+ v->noise_energy += (energy - v->noise_energy) / 4;
+
+ if (v->voxena) threshold = v->speech_energy / 8;
+ else
+ {
+ threshold = mymax(v->speech_energy / 16,v->noise_energy * 2);
+ threshold = mymin(threshold,VOX_MAX_THRESHOLD);
+ }
+ threshold = mymax(threshold,VOX_MIN_THRESHOLD);
+ if (energy > threshold)
+ {
+ if (v->voxena) v->noise_energy *= 0.75;
+ v->voxena = 1;
+ } else v->voxena = 0;
+ if (v->lastvox != v->voxena)
+ {
+ if (v->enacount++ >= ((v->lastvox) ? v->offdebcnt : v->ondebcnt))
+ {
+ v->lastvox = v->voxena;
+ v->enacount = 0;
+ }
+ } else v->enacount = 0;
+ return(v->lastvox);
+}
+
+
+
+
+/*
* CLI extensions
*/
/* Debug mode */
-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_stats(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 struct ast_cli_entry cli_rpt[] = {
- AST_CLI_DEFINE(handle_cli_rpt_debug_level, "Enable app_rpt debuggin"),
- AST_CLI_DEFINE(handle_cli_rpt_dump, "Dump app_rpt structs for debugging"),
- AST_CLI_DEFINE(handle_cli_rpt_stats, "Dump node statistics"),
- AST_CLI_DEFINE(handle_cli_rpt_lstats, "Dump link statistics"),
- AST_CLI_DEFINE(handle_cli_rpt_reload, "Reload app_rpt config"),
- AST_CLI_DEFINE(handle_cli_rpt_restart, "Restart app_rpt")
-};
+static int rpt_do_debug(int fd, int argc, char *argv[]);
+static int rpt_do_dump(int fd, int argc, char *argv[]);
+static int rpt_do_stats(int fd, int argc, char *argv[]);
+static int rpt_do_lstats(int fd, int argc, char *argv[]);
+static int rpt_do_nodes(int fd, int argc, char *argv[]);
+static int rpt_do_local_nodes(int fd, int argc, char *argv[]);
+static int rpt_do_reload(int fd, int argc, char *argv[]);
+static int rpt_do_restart(int fd, int argc, char *argv[]);
+static int rpt_do_fun(int fd, int argc, char *argv[]);
+static int rpt_do_fun1(int fd, int argc, char *argv[]);
+static int rpt_do_cmd(int fd, int argc, char *argv[]);
+
+static char debug_usage[] =
+"Usage: rpt debug level {0-7}\n"
+" Enables debug messages in app_rpt\n";
+
+static char dump_usage[] =
+"Usage: rpt dump <nodename>\n"
+" Dumps struct debug info to log\n";
+
+static char dump_stats[] =
+"Usage: rpt stats <nodename>\n"
+" Dumps node statistics to console\n";
+
+static char dump_lstats[] =
+"Usage: rpt lstats <nodename>\n"
+" Dumps link statistics to console\n";
+
+static char dump_nodes[] =
+"Usage: rpt nodes <nodename>\n"
+" Dumps a list of directly and indirectly connected nodes to the console\n";
+
+static char usage_local_nodes[] =
+"Usage: rpt localnodes\n"
+" Dumps a list of the locally configured node numbers to the console.\n";
+
+static char reload_usage[] =
+"Usage: rpt reload\n"
+" Reloads app_rpt running config parameters\n";
+
+static char restart_usage[] =
+"Usage: rpt restart\n"
+" Restarts app_rpt\n";
+
+static char fun_usage[] =
+"Usage: rpt fun <nodename> <command>\n"
+" Send a DTMF function to a node\n";
+
+static char cmd_usage[] =
+"Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
+" Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
+
+#ifndef NEW_ASTERISK
+
+static struct ast_cli_entry cli_debug =
+ { { "rpt", "debug", "level" }, rpt_do_debug,
+ "Enable app_rpt debugging", debug_usage };
+
+static struct ast_cli_entry cli_dump =
+ { { "rpt", "dump" }, rpt_do_dump,
+ "Dump app_rpt structs for debugging", dump_usage };
+
+static struct ast_cli_entry cli_stats =
+ { { "rpt", "stats" }, rpt_do_stats,
+ "Dump node statistics", dump_stats };
+
+static struct ast_cli_entry cli_nodes =
+ { { "rpt", "nodes" }, rpt_do_nodes,
+ "Dump node list", dump_nodes };
+
+static struct ast_cli_entry cli_local_nodes =
+ { { "rpt", "localnodes" }, rpt_do_local_nodes,
+ "Dump list of local node numbers", usage_local_nodes };
+
+static struct ast_cli_entry cli_lstats =
+ { { "rpt", "lstats" }, rpt_do_lstats,
+ "Dump link statistics", dump_lstats };
+
+static struct ast_cli_entry cli_reload =
+ { { "rpt", "reload" }, rpt_do_reload,
+ "Reload app_rpt config", reload_usage };
+
+static struct ast_cli_entry cli_restart =
+ { { "rpt", "restart" }, rpt_do_restart,
+ "Restart app_rpt", restart_usage };
+
+static struct ast_cli_entry cli_fun =
+ { { "rpt", "fun" }, rpt_do_fun,
+ "Execute a DTMF function", fun_usage };
+
+static struct ast_cli_entry cli_fun1 =
+ { { "rpt", "fun1" }, rpt_do_fun1,
+ "Execute a DTMF function", fun_usage };
+
+static struct ast_cli_entry cli_cmd =
+ { { "rpt", "cmd" }, rpt_do_cmd,
+ "Execute a DTMF function", cmd_usage };
+
+#endif
/*
* Telemetry defaults
@@ -709,25 +1277,30 @@ static struct ast_cli_entry cli_rpt[] = {
static struct telem_defaults tele_defs[] = {
- {"ct1", "|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
- {"ct2", "|t(660,880,150,3072)"},
- {"ct3", "|t(440,0,150,3072)"},
- {"ct4", "|t(550,0,150,3072)"},
- {"ct5", "|t(660,0,150,3072)"},
- {"ct6", "|t(880,0,150,3072)"},
- {"ct7", "|t(660,440,150,3072)"},
- {"ct8", "|t(700,1100,150,3072)"},
- {"remotemon", "|t(1600,0,75,2048)"},
- {"remotetx", "|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
- {"cmdmode", "|t(900,904,200,2048)"},
- {"functcomplete", "|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
+ {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
+ {"ct2","|t(660,880,150,3072)"},
+ {"ct3","|t(440,0,150,3072)"},
+ {"ct4","|t(550,0,150,3072)"},
+ {"ct5","|t(660,0,150,3072)"},
+ {"ct6","|t(880,0,150,3072)"},
+ {"ct7","|t(660,440,150,3072)"},
+ {"ct8","|t(700,1100,150,3072)"},
+ {"remotemon","|t(1600,0,75,2048)"},
+ {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
+ {"cmdmode","|t(900,904,200,2048)"},
+ {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
} ;
/*
-* Forward decl's - these suppress compiler warnings when funcs coded further down the file than their invocation
+* Forward decl's - these suppress compiler warnings when funcs coded further down the file than thier invokation
*/
static int setrbi(struct rpt *myrpt);
+static int set_ft897(struct rpt *myrpt);
+static int set_ic706(struct rpt *myrpt);
+static int setkenwood(struct rpt *myrpt);
+static int set_tm271(struct rpt *myrpt);
+static int setrbi_check(struct rpt *myrpt);
@@ -742,7 +1315,7 @@ static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int c
static int function_cop(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_macro(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_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
/*
* Function table
*/
@@ -755,30 +1328,747 @@ static struct function_table_tag function_table[] = {
{"status", function_status},
{"remote", function_remote},
{"macro", function_macro},
- {"gosub", function_gosub},
+ {"playback", function_playback}
} ;
+static long diskavail(struct rpt *myrpt)
+{
+struct statfs statfsbuf;
+
+ if (!myrpt->p.archivedir) return(0);
+ if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
+ {
+ ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
+ myrpt->p.archivedir,myrpt->name);
+ return(-1);
+ }
+ return(statfsbuf.f_bavail);
+}
+
+static void flush_telem(struct rpt *myrpt)
+{
+ struct rpt_tele *telem;
+ if(debug > 2)
+ ast_log(LOG_NOTICE, "flush_telem()!!");
+ rpt_mutex_lock(&myrpt->lock);
+ telem = myrpt->tele.next;
+ while(telem != &myrpt->tele)
+ {
+ if (telem->mode != SETREMOTE) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
+ telem = telem->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+}
+/*
+ return via error priority
+*/
+static int priority_jump(struct rpt *myrpt, struct ast_channel *chan)
+{
+ int res=0;
+
+ // if (ast_test_flag(&flags,OPT_JUMP) && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
+ if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
+ res = 0;
+ } else {
+ res = -1;
+ }
+ return res;
+}
+/*
+*/
+static int linkcount(struct rpt *myrpt)
+{
+ struct rpt_link *l;
+ char *reverse_patch_state;
+ int numoflinks;
+
+ reverse_patch_state = "DOWN";
+ numoflinks = 0;
+ l = myrpt->links.next;
+ while(l && (l != &myrpt->links)){
+ if(numoflinks >= MAX_STAT_LINKS){
+ ast_log(LOG_WARNING,
+ "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
+ break;
+ }
+ //if (l->name[0] == '0'){ /* Skip '0' nodes */
+ // reverse_patch_state = "UP";
+ // l = l->next;
+ // continue;
+ //}
+ numoflinks++;
+
+ l = l->next;
+ }
+ ast_log(LOG_NOTICE, "numoflinks=%i\n",numoflinks);
+ return numoflinks;
+}
+/*
+ * Retrieve a memory channel
+ * Return 0 if sucessful,
+ * -1 if channel not found,
+ * 1 if parse error
+ */
+static int retreive_memory(struct rpt *myrpt, char *memory)
+{
+ char tmp[30], *s, *s1, *val;
+
+ if (debug)ast_log(LOG_NOTICE, "memory=%s block=%s\n",memory,myrpt->p.memory);
+
+ val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
+ if (!val){
+ return -1;
+ }
+ strncpy(tmp,val,sizeof(tmp) - 1);
+ tmp[sizeof(tmp)-1] = 0;
+
+ s = strchr(tmp,',');
+ if (!s)
+ return 1;
+ *s++ = 0;
+ s1 = strchr(s,',');
+ if (!s1)
+ return 1;
+ *s1++ = 0;
+ strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
+ strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
+ strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
+ myrpt->remmode = REM_MODE_FM;
+ myrpt->offset = REM_SIMPLEX;
+ myrpt->powerlevel = REM_MEDPWR;
+ myrpt->txplon = myrpt->rxplon = 0;
+ while(*s1){
+ switch(*s1++){
+ case 'A':
+ case 'a':
+ strcpy(myrpt->rxpl, "100.0");
+ strcpy(myrpt->txpl, "100.0");
+ myrpt->remmode = REM_MODE_AM;
+ break;
+ case 'B':
+ case 'b':
+ strcpy(myrpt->rxpl, "100.0");
+ strcpy(myrpt->txpl, "100.0");
+ myrpt->remmode = REM_MODE_LSB;
+ break;
+ case 'F':
+ myrpt->remmode = REM_MODE_FM;
+ break;
+ case 'L':
+ case 'l':
+ myrpt->powerlevel = REM_LOWPWR;
+ break;
+ case 'H':
+ case 'h':
+ myrpt->powerlevel = REM_HIPWR;
+ break;
+
+ case 'M':
+ case 'm':
+ myrpt->powerlevel = REM_MEDPWR;
+ break;
+
+ case '-':
+ myrpt->offset = REM_MINUS;
+ break;
+
+ case '+':
+ myrpt->offset = REM_PLUS;
+ break;
+
+ case 'S':
+ case 's':
+ myrpt->offset = REM_SIMPLEX;
+ break;
+
+ case 'T':
+ case 't':
+ myrpt->txplon = 1;
+ break;
+
+ case 'R':
+ case 'r':
+ myrpt->rxplon = 1;
+ break;
+
+ case 'U':
+ case 'u':
+ strcpy(myrpt->rxpl, "100.0");
+ strcpy(myrpt->txpl, "100.0");
+ myrpt->remmode = REM_MODE_USB;
+ break;
+ default:
+ return 1;
+ }
+ }
+ return 0;
+}
/*
-* Match a keyword in a list, and return index of string plus 1 if there was a match,
-* else return 0. If param is passed in non-null, then it will be set to the first character past the match
+
+*/
+static void birdbath(struct rpt *myrpt)
+{
+ struct rpt_tele *telem;
+ if(debug > 2)
+ ast_log(LOG_NOTICE, "birdbath!!");
+ rpt_mutex_lock(&myrpt->lock);
+ telem = myrpt->tele.next;
+ while(telem != &myrpt->tele)
+ {
+ if (telem->mode == PARROT) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
+ telem = telem->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+}
+
+static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
+{
+struct rpt_link *l;
+
+ l = myrpt->links.next;
+ /* go thru all the links */
+ while(l != &myrpt->links)
+ {
+ if (!l->phonemode)
+ {
+ l = l->next;
+ continue;
+ }
+ /* dont send to self */
+ if (mylink && (l == mylink))
+ {
+ l = l->next;
+ continue;
+ }
+#ifdef NEW_ASTERISK
+ if (l->chan) ast_senddigit(l->chan,c,0);
+#else
+ if (l->chan) ast_senddigit(l->chan,c);
+#endif
+ l = l->next;
+ }
+ return;
+}
+
+/* node logging function */
+static void donodelog(struct rpt *myrpt,char *str)
+{
+struct nodelog *nodep;
+char datestr[100];
+
+ if (!myrpt->p.archivedir) return;
+ nodep = (struct nodelog *)ast_malloc(sizeof(struct nodelog));
+ if (nodep == NULL)
+ {
+ ast_log(LOG_ERROR,"Cannot get memory for node log");
+ return;
+ }
+ time(&nodep->timestamp);
+ strncpy(nodep->archivedir,myrpt->p.archivedir,
+ sizeof(nodep->archivedir) - 1);
+ strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
+ localtime(&nodep->timestamp));
+ snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
+ myrpt->name,datestr,str);
+ ast_mutex_lock(&nodeloglock);
+ insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
+ ast_mutex_unlock(&nodeloglock);
+}
+
+/* must be called locked */
+static void do_dtmf_local(struct rpt *myrpt, char c)
+{
+int i;
+char digit;
+static const char* dtmf_tones[] = {
+ "!941+1336/200,!0/200", /* 0 */
+ "!697+1209/200,!0/200", /* 1 */
+ "!697+1336/200,!0/200", /* 2 */
+ "!697+1477/200,!0/200", /* 3 */
+ "!770+1209/200,!0/200", /* 4 */
+ "!770+1336/200,!0/200", /* 5 */
+ "!770+1477/200,!0/200", /* 6 */
+ "!852+1209/200,!0/200", /* 7 */
+ "!852+1336/200,!0/200", /* 8 */
+ "!852+1477/200,!0/200", /* 9 */
+ "!697+1633/200,!0/200", /* A */
+ "!770+1633/200,!0/200", /* B */
+ "!852+1633/200,!0/200", /* C */
+ "!941+1633/200,!0/200", /* D */
+ "!941+1209/200,!0/200", /* * */
+ "!941+1477/200,!0/200" }; /* # */
+
+
+ if (c)
+ {
+ snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
+ if (!myrpt->dtmf_local_timer)
+ myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
+ }
+ /* if at timeout */
+ if (myrpt->dtmf_local_timer == 1)
+ {
+ if(debug > 6)
+ ast_log(LOG_NOTICE,"time out dtmf_local_timer=%i\n",myrpt->dtmf_local_timer);
+
+ /* if anything in the string */
+ if (myrpt->dtmf_local_str[0])
+ {
+ digit = myrpt->dtmf_local_str[0];
+ myrpt->dtmf_local_str[0] = 0;
+ for(i = 1; myrpt->dtmf_local_str[i]; i++)
+ {
+ myrpt->dtmf_local_str[i - 1] =
+ myrpt->dtmf_local_str[i];
+ }
+ myrpt->dtmf_local_str[i - 1] = 0;
+ myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
+ rpt_mutex_unlock(&myrpt->lock);
+ if (digit >= '0' && digit <='9')
+ ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
+ else if (digit >= 'A' && digit <= 'D')
+ ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
+ else if (digit == '*')
+ ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
+ else if (digit == '#')
+ ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
+ else {
+ /* not handled */
+ ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
+ }
+ rpt_mutex_lock(&myrpt->lock);
+ }
+ else
+ {
+ myrpt->dtmf_local_timer = 0;
+ }
+ }
+}
+
+static int setdtr(int fd, int enable)
+{
+struct termios mode;
+
+ if (fd < 0) return -1;
+ if (tcgetattr(fd, &mode)) {
+ ast_log(LOG_WARNING, "Unable to get serial parameters for dtr: %s\n", strerror(errno));
+ return -1;
+ }
+ if (enable)
+ {
+ cfsetspeed(&mode, B9600);
+ }
+ else
+ {
+ cfsetspeed(&mode, B0);
+ usleep(100000);
+ }
+ if (tcsetattr(fd, TCSADRAIN, &mode)) {
+ ast_log(LOG_WARNING, "Unable to set serial parameters for dtr: %s\n", strerror(errno));
+ return -1;
+ }
+ if (enable) usleep(100000);
+ return 0;
+}
+
+static int openserial(struct rpt *myrpt,char *fname)
+{
+ struct termios mode;
+ int fd;
+
+ fd = open(fname,O_RDWR);
+ if (fd == -1)
+ {
+ ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
+ return -1;
+ }
+ memset(&mode, 0, sizeof(mode));
+ if (tcgetattr(fd, &mode)) {
+ ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
+ return -1;
+ }
+#ifndef SOLARIS
+ cfmakeraw(&mode);
+#else
+ mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+ |INLCR|IGNCR|ICRNL|IXON);
+ mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
+ mode.c_cflag |= CS8;
+ mode.c_cc[VTIME] = 3;
+ mode.c_cc[VMIN] = 1;
+#endif
+
+ cfsetispeed(&mode, B9600);
+ cfsetospeed(&mode, B9600);
+ if (tcsetattr(fd, TCSANOW, &mode))
+ ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
+ if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) setdtr(fd,0);
+ usleep(100000);
+ if (debug)ast_log(LOG_NOTICE,"Opened serial port %s\n",fname);
+ return(fd);
+}
+
+static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
+{
+ if (!fromnode)
+ {
+ ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
+ unit,myrpt->name);
+ }
+ else
+ {
+ ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
+ unit,fromnode,myrpt->name);
+ }
+}
+
+#ifdef _MDC_DECODE_H_
+
+static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
+{
+struct rpt_link *l;
+struct ast_frame wf;
+char str[200];
+
+
+ sprintf(str,"I %s %04X",myrpt->name,unit);
+
+ wf.frametype = AST_FRAME_TEXT;
+ wf.subclass = 0;
+ wf.offset = 0;
+ wf.mallocd = 0;
+ wf.datalen = strlen(str) + 1;
+ wf.samples = 0;
+
+
+ l = myrpt->links.next;
+ /* otherwise, send it to all of em */
+ while(l != &myrpt->links)
+ {
+ if (l->name[0] == '0')
+ {
+ l = l->next;
+ continue;
+ }
+ wf.data = str;
+ if (l->chan) ast_write(l->chan,&wf);
+ l = l->next;
+ }
+ return;
+}
+
+#endif
+
+static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
+{
+time_t now;
+int gotone;
+
+ time(&now);
+ gotone = 0;
+ /* if too much time, reset the skate machine */
+ if ((now - xlat->lastone) > MAXXLATTIME)
+ {
+ xlat->funcindex = xlat->endindex = 0;
+ }
+ if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
+ {
+ time(&xlat->lastone);
+ gotone = 1;
+ if (!xlat->funccharseq[xlat->funcindex])
+ {
+ xlat->funcindex = xlat->endindex = 0;
+ return(myrpt->p.funcchar);
+ }
+ } else xlat->funcindex = 0;
+ if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
+ {
+ time(&xlat->lastone);
+ gotone = 1;
+ if (!xlat->endcharseq[xlat->endindex])
+ {
+ xlat->funcindex = xlat->endindex = 0;
+ return(myrpt->p.endchar);
+ }
+ } else xlat->endindex = 0;
+ /* if in middle of decode seq, send nothing back */
+ if (gotone) return(0);
+ /* if no pass chars specified, return em all */
+ if (!xlat->passchars[0]) return(c);
+ /* if a "pass char", pass it */
+ if (strchr(xlat->passchars,c)) return(c);
+ return(0);
+}
+
+/*
+ * Return a pointer to the first non-whitespace character
+ */
+
+static char *eatwhite(char *s)
+{
+ while((*s == ' ') || (*s == 0x09)){ /* get rid of any leading white space */
+ if(!*s)
+ break;
+ s++;
+ }
+ return s;
+}
+
+/*
+* Break up a delimited string into a table of substrings
+*
+* str - delimited string ( will be modified )
+* strp- list of pointers to substrings (this is built by this function), NULL will be placed at end of list
+* limit- maximum number of substrings to process
+*/
+
+
+
+static int finddelim(char *str, char *strp[], int limit)
+{
+int i,l,inquo;
+
+ inquo = 0;
+ i = 0;
+ strp[i++] = str;
+ if (!*str)
+ {
+ strp[0] = 0;
+ return(0);
+ }
+ for(l = 0; *str && (l < limit) ; str++)
+ {
+ if (*str == QUOTECHR)
+ {
+ if (inquo)
+ {
+ *str = 0;
+ inquo = 0;
+ }
+ else
+ {
+ strp[i - 1] = str + 1;
+ inquo = 1;
+ }
+ }
+ if ((*str == DELIMCHR) && (!inquo))
+ {
+ *str = 0;
+ l++;
+ strp[i++] = str + 1;
+ }
+ }
+ strp[i] = 0;
+ return(i);
+
+}
+/*
+ send asterisk frame text message on the current tx channel
+*/
+static int send_usb_txt(struct rpt *myrpt, char *txt)
+{
+ struct ast_frame wf;
+
+ if (debug)ast_log(LOG_NOTICE, "send_usb_txt %s\n",txt);
+ wf.frametype = AST_FRAME_TEXT;
+ wf.subclass = 0;
+ wf.offset = 0;
+ wf.mallocd = 0;
+ wf.datalen = strlen(txt) + 1;
+ wf.data = txt;
+ wf.samples = 0;
+ ast_write(myrpt->txchannel,&wf);
+ return 0;
+}
+/* must be called locked */
+static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
+{
+struct rpt_link *l;
+char mode;
+int i,spos;
+
+ buf[0] = 0; /* clear output buffer */
+ if (myrpt->remote) return;
+ /* go thru all links */
+ for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
+ {
+ /* if is not a real link, ignore it */
+ if (l->name[0] == '0') continue;
+ /* dont count our stuff */
+ if (l == mylink) continue;
+ if (mylink && (!strcmp(l->name,mylink->name))) continue;
+ /* figure out mode to report */
+ mode = 'T'; /* use Tranceive by default */
+ if (!l->mode) mode = 'R'; /* indicate RX for our mode */
+ if (!l->thisconnected) mode = 'C'; /* indicate connecting */
+ spos = strlen(buf); /* current buf size (b4 we add our stuff) */
+ if (spos)
+ {
+ strcat(buf,",");
+ spos++;
+ }
+ /* add nodes into buffer */
+ if (l->linklist[0])
+ {
+ snprintf(buf + spos,MAXLINKLIST - spos,
+ "%c%s,%s",mode,l->name,l->linklist);
+ }
+ else /* if no nodes, add this node into buffer */
+ {
+ snprintf(buf + spos,MAXLINKLIST - spos,
+ "%c%s",mode,l->name);
+ }
+ /* if we are in tranceive mode, let all modes stand */
+ if (mode == 'T') continue;
+ /* downgrade everyone on this node if appropriate */
+ for(i = spos; buf[i]; i++)
+ {
+ if (buf[i] == 'T') buf[i] = mode;
+ if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
+ }
+ }
+ return;
+}
+
+/* must be called locked */
+static void __kickshort(struct rpt *myrpt)
+{
+struct rpt_link *l;
+
+ for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
+ {
+ /* if is not a real link, ignore it */
+ if (l->name[0] == '0') continue;
+ l->linklisttimer = LINKLISTSHORTTIME;
+ }
+ myrpt->linkposttimer = LINKPOSTSHORTTIME;
+ return;
+}
+
+static void statpost(struct rpt *myrpt,char *pairs)
+{
+char *str,*astr;
+char *astrs[100];
+int n,pid;
+time_t now;
+unsigned int seq;
+
+ if (!myrpt->p.statpost_url) return;
+ str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
+ astr = ast_strdup(myrpt->p.statpost_program);
+ if ((!str) || (!astr)) return;
+ n = finddelim(astr,astrs,100);
+ if (n < 1) return;
+ ast_mutex_lock(&myrpt->statpost_lock);
+ seq = ++myrpt->statpost_seqno;
+ ast_mutex_unlock(&myrpt->statpost_lock);
+ astrs[n++] = str;
+ astrs[n] = NULL;
+ time(&now);
+ sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
+ myrpt->name,(unsigned int) now,seq);
+ if (pairs) sprintf(str + strlen(str),"&%s",pairs);
+ if (!(pid = fork()))
+ {
+ execv(astrs[0],astrs);
+ ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
+ perror("asterisk");
+ exit(0);
+ }
+ ast_free(astr);
+ ast_free(str);
+ return;
+}
+
+static char *node_lookup(struct rpt *myrpt,char *digitbuf)
+{
+
+char *val;
+int longestnode,j;
+struct stat mystat;
+static time_t last = 0;
+static struct ast_config *ourcfg = NULL;
+struct ast_variable *vp;
+
+ /* try to look it up locally first */
+ val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
+ if (val) return(val);
+ ast_mutex_lock(&nodelookuplock);
+ /* if file does not exist */
+ if (stat(myrpt->p.extnodefile,&mystat) == -1)
+ {
+ if (ourcfg) ast_config_destroy(ourcfg);
+ ourcfg = NULL;
+ ast_mutex_unlock(&nodelookuplock);
+ return(NULL);
+ }
+ /* if we need to reload */
+ if (mystat.st_mtime > last)
+ {
+ if (ourcfg) ast_config_destroy(ourcfg);
+#ifdef NEW_ASTERISK
+ ourcfg = ast_config_load(myrpt->p.extnodefile,config_flags);
+#else
+ ourcfg = ast_config_load(myrpt->p.extnodefile);
+#endif
+ /* if file not there, just bail */
+ if (!ourcfg)
+ {
+ ast_mutex_unlock(&nodelookuplock);
+ return(NULL);
+ }
+ /* reset "last" time */
+ last = mystat.st_mtime;
+
+ /* determine longest node length again */
+ longestnode = 0;
+ vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > longestnode)
+ longestnode = j;
+ vp = vp->next;
+ }
+
+ vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > longestnode)
+ longestnode = j;
+ vp = vp->next;
+ }
+
+ myrpt->longestnode = longestnode;
+ }
+ val = NULL;
+ if (ourcfg)
+ val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
+ ast_mutex_unlock(&nodelookuplock);
+ return(val);
+}
+
+/*
+* Match a keyword in a list, and return index of string plus 1 if there was a match,* else return 0.
+* If param is passed in non-null, then it will be set to the first character past the match
*/
static int matchkeyword(char *string, char **param, char *keywords[])
{
- int i, ls;
- for (i = 0; keywords[i]; i++) {
+int i,ls;
+ for( i = 0 ; keywords[i] ; i++){
ls = strlen(keywords[i]);
- if (!ls) {
+ if(!ls){
*param = NULL;
return 0;
}
- if (!strncmp(string, keywords[i], ls)) {
- if (param)
+ if(!strncmp(string, keywords[i], ls)){
+ if(param)
*param = string + ls;
return i + 1;
}
}
- param = NULL;
+ *param = NULL;
return 0;
}
@@ -789,15 +2079,15 @@ static int matchkeyword(char *string, char **param, char *keywords[])
static char *skipchars(char *string, char *charlist)
{
- int i;
- while (*string) {
- for (i = 0; charlist[i] ; i++) {
- if (*string == charlist[i]) {
+int i;
+ while(*string){
+ for(i = 0; charlist[i] ; i++){
+ if(*string == charlist[i]){
string++;
break;
}
}
- if (!charlist[i])
+ if(!charlist[i])
return string;
}
return string;
@@ -805,37 +2095,54 @@ static char *skipchars(char *string, char *charlist)
-static int myatoi(const char *str)
+static int myatoi(char *str)
{
- int ret;
+int ret;
- if (str == NULL)
- return -1;
+ if (str == NULL) return -1;
/* leave this %i alone, non-base-10 input is useful here */
- if (sscanf(str, "%i", &ret) != 1)
- return -1;
+ if (sscanf(str,"%i",&ret) != 1) return -1;
return ret;
}
+static int mycompar(const void *a, const void *b)
+{
+char **x = (char **) a;
+char **y = (char **) b;
+int xoff,yoff;
+
+ if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
+ if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
+ return(strcmp((*x) + xoff,(*y) + yoff));
+}
+
+static int topcompar(const void *a, const void *b)
+{
+struct rpt_topkey *x = (struct rpt_topkey *) a;
+struct rpt_topkey *y = (struct rpt_topkey *) b;
+
+ return(x->timesince - y->timesince);
+}
#ifdef __RPT_NOTCH
/* rpt filter routine */
static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
{
- int i, j;
- struct rptfilter *f;
+int i,j;
+struct rptfilter *f;
- for (i = 0; i < len; i++) {
- for (j = 0; j < MAXFILTERS; j++) {
+ for(i = 0; i < len; i++)
+ {
+ for(j = 0; j < MAXFILTERS; j++)
+ {
f = &myrpt->filters[j];
- if (!*f->desc)
- continue;
+ if (!*f->desc) continue;
f->x0 = f->x1; f->x1 = f->x2;
- f->x2 = ((float)buf[i]) / f->gain;
- f->y0 = f->y1; f->y1 = f->y2;
- f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
- + (f->const1 * f->y0) + (f->const2 * f->y1);
+ f->x2 = ((float)buf[i]) / f->gain;
+ f->y0 = f->y1; f->y1 = f->y2;
+ f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
+ + (f->const1 * f->y0) + (f->const2 * f->y1);
buf[i] = (short)f->y2;
}
}
@@ -843,55 +2150,112 @@ static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
#endif
-/* Retrieve an int from a config file */
-static int retrieve_astcfgint(struct rpt *myrpt, const char *category, const char *name, int min, int max, int defl)
+
+/*
+ Get the time for the machine's time zone
+ Note: Asterisk requires a copy of localtime
+ in the /etc directory for this to work properly.
+ If /etc/localtime is not present, you will get
+ GMT time! This is especially important on systems
+ running embedded linux distributions as they don't usually
+ have support for locales.
+
+ If OLD_ASTERISK is defined, then the older localtime_r
+ function will be used. The /etc/localtime file is not
+ required in this case. This provides backward compatibility
+ with Asterisk 1.2 systems.
+
+*/
+
+#ifdef NEW_ASTERISK
+static void rpt_localtime( time_t * t, struct ast_tm *lt)
{
- const char *var = ast_variable_retrieve(myrpt->cfg, category, name);
- int ret;
+struct timeval tv;
- if (var) {
- ret = myatoi(var);
- if (ret < min)
- ret = min;
- else if (ret > max)
- ret = max;
- } else
- ret = defl;
- return ret;
-}
+ tv.tv_sec = *t;
+ tv.tv_usec = 0;
+ ast_localtime(&tv, lt, NULL);
+}
-static void load_rpt_vars(int n, int init)
+#else
+static void rpt_localtime( time_t * t, struct tm *lt)
{
- int j;
- struct ast_variable *vp, *var;
- struct ast_config *cfg;
- struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
-#ifdef __RPT_NOTCH
- AST_DECLARE_APP_ARGS(strs,
- AST_APP_ARG(str)[100];
- );
+#ifdef OLD_ASTERISK
+ localtime_r(t, lt);
+#else
+ ast_localtime(t, lt, NULL);
+#endif
+}
#endif
- ast_verb(3, "%s config for repeater %s\n",
- (init) ? "Loading initial" : "Re-Loading", rpt_vars[n].name);
+
+/* Retrieve an int from a config file */
+
+static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
+{
+ char *var;
+ int ret;
+ char include_zero = 0;
+
+ if(min < 0){ /* If min is negative, this means include 0 as a valid entry */
+ min = -min;
+ include_zero = 1;
+ }
+
+ var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
+ if(var){
+ ret = myatoi(var);
+ if(include_zero && !ret)
+ return 0;
+ if(ret < min)
+ ret = min;
+ if(ret > max)
+ ret = max;
+ }
+ else
+ ret = defl;
+ return ret;
+}
+
+
+static void load_rpt_vars(int n,int init)
+{
+char *this,*val;
+int i,j,longestnode;
+struct ast_variable *vp;
+struct ast_config *cfg;
+char *strs[100];
+char s1[256];
+static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
+ "ufena","ufdis","atena","atdis",NULL};
+
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
+ (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
ast_mutex_lock(&rpt_vars[n].lock);
- if (rpt_vars[n].cfg)
- ast_config_destroy(rpt_vars[n].cfg);
- cfg = ast_config_load("rpt.conf", config_flags);
+ if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
+#ifdef NEW_ASTERISK
+ cfg = ast_config_load("rpt.conf",config_flags);
+#else
+ cfg = ast_config_load("rpt.conf");
+#endif
if (!cfg) {
ast_mutex_unlock(&rpt_vars[n].lock);
- ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
+ ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
pthread_exit(NULL);
}
- rpt_vars[n].cfg = cfg;
- /* Free previously malloc'ed buffer */
- if (!init && rpt_vars[n].p.tailmsgbuf)
- ast_free(rpt_vars[n].p.tailmsgbuf);
- memset(&rpt_vars[n].p, 0, sizeof(rpt_vars[n].p));
- if (init) {
- /* clear all the fields in the structure after 'p' */
- 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));
+ rpt_vars[n].cfg = cfg;
+ this = rpt_vars[n].name;
+ memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
+ if (init)
+ {
+ char *cp;
+ int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
+
+ cp = (char *) &rpt_vars[n].p;
+ memset(cp + sizeof(rpt_vars[n].p),0,
+ sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
rpt_vars[n].tele.next = &rpt_vars[n].tele;
rpt_vars[n].tele.prev = &rpt_vars[n].tele;
rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
@@ -899,174 +2263,352 @@ static void load_rpt_vars(int n, int init)
}
#ifdef __RPT_NOTCH
/* zot out filters stuff */
- memset(&rpt_vars[n].filters, 0, sizeof(rpt_vars[n].filters));
+ memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
#endif
-
- /* Defaults */
- ast_copy_string(rpt_vars[n].p.ourcontext, rpt_vars[n].name, sizeof(rpt_vars[n].p.ourcontext));
- rpt_vars[n].p.hangtime = HANGTIME;
- rpt_vars[n].p.totime = TOTIME;
- rpt_vars[n].p.duplex = 2;
- rpt_vars[n].p.idtime = IDTIME;
- rpt_vars[n].p.politeid = POLITEID;
- ast_copy_string(rpt_vars[n].p.memory, MEMORY, sizeof(rpt_vars[n].p.memory));
- ast_copy_string(rpt_vars[n].p.macro, MACRO, sizeof(rpt_vars[n].p.macro));
- ast_copy_string(rpt_vars[n].p.gosub, GOSUB, sizeof(rpt_vars[n].p.gosub));
- rpt_vars[n].p.iobase = DEFAULT_IOBASE;
- ast_copy_string(rpt_vars[n].p.functions, FUNCTIONS, sizeof(rpt_vars[n].p.functions));
- rpt_vars[n].p.simple = 1;
- rpt_vars[n].p.funcchar = FUNCCHAR;
- rpt_vars[n].p.endchar = ENDCHAR;
- ast_copy_string(rpt_vars[n].p.nodes, NODES, sizeof(rpt_vars[n].p.nodes));
-
- for (var = ast_variable_browse(cfg, rpt_vars[n].name); var; var = var->next) {
- if (!strcmp(var->name, "context")) {
- ast_copy_string(rpt_vars[n].p.ourcontext, var->value, sizeof(rpt_vars[n].p.ourcontext));
- } else if (!strcmp(var->name, "callerid")) {
- ast_copy_string(rpt_vars[n].p.ourcallerid, var->value, sizeof(rpt_vars[n].p.ourcallerid));
- } else if (!strcmp(var->name, "accountcode")) {
- ast_copy_string(rpt_vars[n].p.acctcode, var->value, sizeof(rpt_vars[n].p.acctcode));
- } else if (!strcmp(var->name, "idrecording")) {
- ast_copy_string(rpt_vars[n].p.ident, var->value, sizeof(rpt_vars[n].p.ident));
- } else if (!strcmp(var->name, "hangtime")) {
- rpt_vars[n].p.hangtime = atoi(var->value);
- } else if (!strcmp(var->name, "totime")) {
- rpt_vars[n].p.totime = atoi(var->value);
- } else if (!strcmp(var->name, "tailmessagetime")) {
- rpt_vars[n].p.tailmessagetime = atoi(var->value);
- if (rpt_vars[n].p.tailmessagetime < 0)
- rpt_vars[n].p.tailmessagetime = 0;
- else if (rpt_vars[n].p.tailmessagetime > 2400000)
- rpt_vars[n].p.tailmessagetime = 2400000;
- } else if (!strcmp(var->name, "tailsquashedtime")) {
- rpt_vars[n].p.tailsquashedtime = atoi(var->value);
- if (rpt_vars[n].p.tailsquashedtime < 0)
- rpt_vars[n].p.tailsquashedtime = 0;
- else if (rpt_vars[n].p.tailsquashedtime > 2400000)
- rpt_vars[n].p.tailsquashedtime = 2400000;
- } else if (!strcmp(var->name, "duplex")) {
- rpt_vars[n].p.duplex = atoi(var->value);
- if (rpt_vars[n].p.duplex < 0)
- rpt_vars[n].p.duplex = 0;
- else if (rpt_vars[n].p.duplex > 4)
- rpt_vars[n].p.duplex = 4;
- } else if (!strcmp(var->name, "idtime")) {
- rpt_vars[n].p.idtime = atoi(var->value);
- if (rpt_vars[n].p.idtime < 60000)
- rpt_vars[n].p.idtime = 60000;
- else if (rpt_vars[n].p.idtime > 2400000)
- rpt_vars[n].p.idtime = 2400000;
- } else if (!strcmp(var->name, "politeid")) {
- rpt_vars[n].p.politeid = atoi(var->value);
- if (rpt_vars[n].p.politeid < 30000)
- rpt_vars[n].p.politeid = 30000;
- else if (rpt_vars[n].p.politeid > 300000)
- rpt_vars[n].p.politeid = 300000;
- } else if (!strcmp(var->name, "tonezone")) {
- ast_copy_string(rpt_vars[n].p.tonezone, var->value, sizeof(rpt_vars[n].p.tonezone));
- } else if (!strcmp(var->name, "tailmessagelist")) {
- rpt_vars[n].p.tailmsgbuf = ast_strdup(var->value);
- AST_STANDARD_APP_ARGS(rpt_vars[n].p.tailmsg, rpt_vars[n].p.tailmsgbuf);
- } else if (!strcmp(var->name, "memory")) {
- ast_copy_string(rpt_vars[n].p.memory, var->value, sizeof(rpt_vars[n].p.memory));
- } else if (!strcmp(var->name, "macro")) {
- ast_copy_string(rpt_vars[n].p.macro, var->value, sizeof(rpt_vars[n].p.macro));
- } else if (!strcmp(var->name, "gosub")) {
- ast_copy_string(rpt_vars[n].p.gosub, var->value, sizeof(rpt_vars[n].p.gosub));
- } else if (!strcmp(var->name, "startup_macro")) {
- ast_copy_string(rpt_vars[n].p.startupmacro, var->value, sizeof(rpt_vars[n].p.startupmacro));
- } else if (!strcmp(var->name, "startup_gosub")) {
- ast_copy_string(rpt_vars[n].p.startupgosub, var->value, sizeof(rpt_vars[n].p.startupgosub));
- } else if (!strcmp(var->name, "iobase")) {
- /* do not use atoi() here, we need to be able to have
- the input specified in hex or decimal so we use
- sscanf with a %i */
- if (sscanf(var->value, "%i", &rpt_vars[n].p.iobase) != 1)
- rpt_vars[n].p.iobase = DEFAULT_IOBASE;
- } else if (!strcmp(var->name, "functions")) {
- rpt_vars[n].p.simple = 0;
- ast_copy_string(rpt_vars[n].p.functions, var->value, sizeof(rpt_vars[n].p.functions));
- } else if (!strcmp(var->name, "link_functions")) {
- ast_copy_string(rpt_vars[n].p.link_functions, var->value, sizeof(rpt_vars[n].p.link_functions));
- } else if (!strcmp(var->name, "phone_functions")) {
- ast_copy_string(rpt_vars[n].p.phone_functions, var->value, sizeof(rpt_vars[n].p.phone_functions));
- } else if (!strcmp(var->name, "dphone_functions")) {
- ast_copy_string(rpt_vars[n].p.dphone_functions, var->value, sizeof(rpt_vars[n].p.dphone_functions));
- } else if (!strcmp(var->name, "funcchar")) {
- rpt_vars[n].p.funcchar = *var->value;
- } else if (!strcmp(var->name, "endchar")) {
- rpt_vars[n].p.endchar = *var->value;
- } else if (!strcmp(var->name, "nobusyout")) {
- rpt_vars[n].p.nobusyout = ast_true(var->value);
- } else if (!strcmp(var->name, "nodes")) {
- ast_copy_string(rpt_vars[n].p.nodes, var->value, sizeof(rpt_vars[n].p.nodes));
+ val = (char *) ast_variable_retrieve(cfg,this,"context");
+ if (val) rpt_vars[n].p.ourcontext = val;
+ else rpt_vars[n].p.ourcontext = this;
+ val = (char *) ast_variable_retrieve(cfg,this,"callerid");
+ if (val) rpt_vars[n].p.ourcallerid = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
+ if (val) rpt_vars[n].p.acctcode = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
+ if (val) rpt_vars[n].p.ident = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
+ if (val) rpt_vars[n].p.hangtime = atoi(val);
+ else rpt_vars[n].p.hangtime = HANGTIME;
+ val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
+ if (val) rpt_vars[n].p.althangtime = atoi(val);
+ else rpt_vars[n].p.althangtime = HANGTIME;
+ val = (char *) ast_variable_retrieve(cfg,this,"totime");
+ if (val) rpt_vars[n].p.totime = atoi(val);
+ else rpt_vars[n].p.totime = TOTIME;
+ val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
+ if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
+ else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
+ val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
+ if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
+ else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
+ val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
+ if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
+ else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
+ val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
+ if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
+ else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
+ val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
+ if (val) rpt_vars[n].p.statpost_program = val;
+ else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
+ rpt_vars[n].p.statpost_url =
+ (char *) ast_variable_retrieve(cfg,this,"statpost_url");
+ rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
+ rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
+ rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
+ rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME); /* Enforce a min max including zero */
+ rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID); /* Enforce a min max */
+ val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
+ if (val) rpt_vars[n].p.tonezone = val;
+ rpt_vars[n].p.tailmessages[0] = 0;
+ rpt_vars[n].p.tailmessagemax = 0;
+ val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
+ if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
+ val = (char *) ast_variable_retrieve(cfg,this,"memory");
+ if (!val) val = MEMORY;
+ rpt_vars[n].p.memory = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"macro");
+ if (!val) val = MACRO;
+ rpt_vars[n].p.macro = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
+ if (!val) val = TONEMACRO;
+ rpt_vars[n].p.tonemacro = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
+ if (val) rpt_vars[n].p.startupmacro = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"iobase");
+ /* do not use atoi() here, we need to be able to have
+ the input specified in hex or decimal so we use
+ sscanf with a %i */
+ if ((!val) || (sscanf(val,"%i",&rpt_vars[n].p.iobase) != 1))
+ rpt_vars[n].p.iobase = DEFAULT_IOBASE;
+ val = (char *) ast_variable_retrieve(cfg,this,"ioport");
+ rpt_vars[n].p.ioport = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"functions");
+ if (!val)
+ {
+ val = FUNCTIONS;
+ rpt_vars[n].p.simple = 1;
+ }
+ rpt_vars[n].p.functions = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
+ if (val) rpt_vars[n].p.link_functions = val;
+ else
+ rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
+ val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
+ if (val) rpt_vars[n].p.phone_functions = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
+ if (val) rpt_vars[n].p.dphone_functions = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
+ if (val) rpt_vars[n].p.alt_functions = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
+ if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
+ rpt_vars[n].p.funcchar = *val;
+ val = (char *) ast_variable_retrieve(cfg,this,"endchar");
+ if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
+ rpt_vars[n].p.endchar = *val;
+ val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
+ if (val) rpt_vars[n].p.nobusyout = ast_true(val);
+ val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
+ if (val) rpt_vars[n].p.notelemtx = ast_true(val);
+ val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
+ if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
+ val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
+ if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
+ val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
+ if (val) rpt_vars[n].p.linktolink = ast_true(val);
+ val = (char *) ast_variable_retrieve(cfg,this,"nodes");
+ if (!val) val = NODES;
+ rpt_vars[n].p.nodes = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
+ if (!val) val = EXTNODES;
+ rpt_vars[n].p.extnodes = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
+ if (!val) val = EXTNODEFILE;
+ rpt_vars[n].p.extnodefile = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
+ if (val) rpt_vars[n].p.archivedir = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
+ if (val) rpt_vars[n].p.authlevel = atoi(val);
+ else rpt_vars[n].p.authlevel = 0;
+ val = (char *) ast_variable_retrieve(cfg,this,"parrot");
+ if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
+ else rpt_vars[n].p.parrotmode = 0;
+ val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
+ if (val) rpt_vars[n].p.parrottime = atoi(val);
+ else rpt_vars[n].p.parrottime = PARROTTIME;
+ val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
+ rpt_vars[n].p.rptnode = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"mars");
+ if (val) rpt_vars[n].p.remote_mars = atoi(val);
+ else rpt_vars[n].p.remote_mars = 0;
+ val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
+ if (val) rpt_vars[n].p.monminblocks = atol(val);
+ else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
+ val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
+ if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
+ else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
+ val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
+ if (val) rpt_vars[n].p.civaddr = atoi(val);
+ else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
+ val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
+ if (val) rpt_vars[n].p.remotetimeout = atoi(val);
+ else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
+ val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
+ if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
+ else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
+ val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
+ if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
+ else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
#ifdef __RPT_NOTCH
- } else if (!strcmp(var->name, "rxnotch")) {
- char *tmp = ast_strdupa(val);
- AST_STANDARD_APP_ARGS(strs, tmp);
- strs.argc &= ~1; /* force an even number, rounded down */
- if (strs.argc >= 2) {
- for (j = 0; j < strs.argc; j += 2) {
- rpt_mknotch(atof(strs.str[j]), atof(strs.str[j + 1]),
- &rpt_vars[n].filters[j >> 1].gain,
- &rpt_vars[n].filters[j >> 1].const0,
- &rpt_vars[n].filters[j >> 1].const1,
- &rpt_vars[n].filters[j >> 1].const2);
- sprintf(rpt_vars[n].filters[j >> 1].desc, "%s Hz, BW = %s",
- strs.str[j], strs.str[j + 1]);
- }
- }
-#endif
+ val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
+ if (val) {
+ i = finddelim(val,strs,MAXFILTERS * 2);
+ i &= ~1; /* force an even number, rounded down */
+ if (i >= 2) for(j = 0; j < i; j += 2)
+ {
+ rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
+ &rpt_vars[n].filters[j >> 1].gain,
+ &rpt_vars[n].filters[j >> 1].const0,
+ &rpt_vars[n].filters[j >> 1].const1,
+ &rpt_vars[n].filters[j >> 1].const2);
+ sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
+ strs[j],strs[j + 1]);
}
+
}
+#endif
+ val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
+ if (val) {
+ memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
+ i = finddelim(val,strs,3);
+ if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
+ if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
+ if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
+ }
+ val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
+ if (val) {
+ memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
+ i = finddelim(val,strs,3);
+ if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
+ if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
+ if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
+ }
+ /* retreive the stanza name for the control states if there is one */
+ val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
+ rpt_vars[n].p.csstanzaname = val;
+
+ /* retreive the stanza name for the scheduler if there is one */
+ val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
+ rpt_vars[n].p.skedstanzaname = val;
+
+ /* retreive the stanza name for the txlimits */
+ val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
+ rpt_vars[n].p.txlimitsstanzaname = val;
- /* If these aren't specified, copy them from the functions property. */
- if (ast_strlen_zero(rpt_vars[n].p.link_functions))
- ast_copy_string(rpt_vars[n].p.link_functions, rpt_vars[n].p.functions, sizeof(rpt_vars[n].p.link_functions));
+ longestnode = 0;
- rpt_vars[n].longestnode = 0;
- for (vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes); vp; vp = vp->next) {
- if ((j = strlen(vp->name)) > rpt_vars[n].longestnode)
- rpt_vars[n].longestnode = j;
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
+
+ while(vp){
+ j = strlen(vp->name);
+ if (j > longestnode)
+ longestnode = j;
+ vp = vp->next;
}
+ rpt_vars[n].longestnode = longestnode;
+
/*
* For this repeater, Determine the length of the longest function
*/
rpt_vars[n].longestfunc = 0;
- for (vp = ast_variable_browse(cfg, rpt_vars[n].p.functions); vp; vp = vp->next) {
- if ((j = strlen(vp->name)) > rpt_vars[n].longestfunc)
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].longestfunc)
rpt_vars[n].longestfunc = j;
+ vp = vp->next;
}
-
+ /*
+ * For this repeater, Determine the length of the longest function
+ */
rpt_vars[n].link_longestfunc = 0;
- for (vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions); vp; vp = vp->next) {
- if ((j = strlen(vp->name)) > rpt_vars[n].link_longestfunc)
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].link_longestfunc)
rpt_vars[n].link_longestfunc = j;
+ vp = vp->next;
}
-
rpt_vars[n].phone_longestfunc = 0;
- for (vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions); vp; vp = vp->next) {
- if ((j = strlen(vp->name)) > rpt_vars[n].phone_longestfunc)
- rpt_vars[n].phone_longestfunc = j;
+ if (rpt_vars[n].p.phone_functions)
+ {
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].phone_longestfunc)
+ rpt_vars[n].phone_longestfunc = j;
+ vp = vp->next;
+ }
}
-
rpt_vars[n].dphone_longestfunc = 0;
- for (vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions); vp; vp = vp->next) {
- if ((j = strlen(vp->name)) > rpt_vars[n].dphone_longestfunc)
- rpt_vars[n].dphone_longestfunc = j;
+ if (rpt_vars[n].p.dphone_functions)
+ {
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].dphone_longestfunc)
+ rpt_vars[n].dphone_longestfunc = j;
+ vp = vp->next;
+ }
+ }
+ rpt_vars[n].alt_longestfunc = 0;
+ if (rpt_vars[n].p.alt_functions)
+ {
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].alt_longestfunc)
+ rpt_vars[n].alt_longestfunc = j;
+ vp = vp->next;
+ }
}
-
rpt_vars[n].macro_longest = 1;
- for (vp = ast_variable_browse(cfg, rpt_vars[n].p.macro); vp; vp = vp->next) {
- if ((j = strlen(vp->name)) > rpt_vars[n].macro_longest)
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].macro_longest)
rpt_vars[n].macro_longest = j;
+ vp = vp->next;
}
+
+ /* Browse for control states */
+ if(rpt_vars[n].p.csstanzaname)
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
+ else
+ vp = NULL;
+ for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){ /* Iterate over the number of control state lines in the stanza */
+ int k,nukw,statenum;
+ statenum=atoi(vp->name);
+ strncpy(s1, vp->value, 255);
+ s1[255] = 0;
+ nukw = finddelim(s1,strs,32);
+
+ for (k = 0 ; k < nukw ; k++){ /* for each user specified keyword */
+ for(j = 0 ; cs_keywords[j] != NULL ; j++){ /* try to match to one in our internal table */
+ if(!strcmp(strs[k],cs_keywords[j])){
+ switch(j){
+ case 0: /* rptena */
+ rpt_vars[n].p.s[statenum].txdisable = 0;
+ break;
+ case 1: /* rptdis */
+ rpt_vars[n].p.s[statenum].txdisable = 1;
+ break;
+
+ case 2: /* apena */
+ rpt_vars[n].p.s[statenum].autopatchdisable = 0;
+ break;
+
+ case 3: /* apdis */
+ rpt_vars[n].p.s[statenum].autopatchdisable = 1;
+ break;
+
+ case 4: /* lnkena */
+ rpt_vars[n].p.s[statenum].linkfundisable = 0;
+ break;
+
+ case 5: /* lnkdis */
+ rpt_vars[n].p.s[statenum].linkfundisable = 1;
+ break;
+
+ case 6: /* totena */
+ rpt_vars[n].p.s[statenum].totdisable = 0;
+ break;
+
+ case 7: /* totdis */
+ rpt_vars[n].p.s[statenum].totdisable = 1;
+ break;
+
+ case 8: /* skena */
+ rpt_vars[n].p.s[statenum].schedulerdisable = 0;
+ break;
+
+ case 9: /* skdis */
+ rpt_vars[n].p.s[statenum].schedulerdisable = 1;
+ break;
+
+ case 10: /* ufena */
+ rpt_vars[n].p.s[statenum].userfundisable = 0;
+ break;
+
+ case 11: /* ufdis */
+ rpt_vars[n].p.s[statenum].userfundisable = 1;
+ break;
+
+ case 12: /* atena */
+ rpt_vars[n].p.s[statenum].alternatetail = 1;
+ break;
- rpt_vars[n].gosub_longest = 1;
- for (vp = ast_variable_browse(cfg, rpt_vars[n].p.gosub); vp; vp = vp->next) {
- if ((j = strlen(vp->name)) > rpt_vars[n].gosub_longest)
- rpt_vars[n].gosub_longest = j;
+ case 13: /* atdis */
+ rpt_vars[n].p.s[statenum].alternatetail = 0;
+ break;
+
+ default:
+ ast_log(LOG_WARNING,
+ "Unhandled control state keyword %s", cs_keywords[i]);
+ break;
+ }
+ }
+ }
+ }
+ vp = vp->next;
}
ast_mutex_unlock(&rpt_vars[n].lock);
}
@@ -1074,113 +2616,87 @@ static void load_rpt_vars(int n, int init)
/*
* Enable or disable debug output at a given level at the console
*/
-static char *handle_cli_rpt_debug_level(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+
+static int rpt_do_debug(int fd, int argc, char *argv[])
{
int newlevel;
- switch (cmd) {
- case CLI_INIT:
- e->command = "rpt debug level";
- e->usage =
- "Usage: rpt debug level {0-7}\n"
- " Enables debug messages in app_rpt\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
- if (a->argc != e->args)
- return CLI_SHOWUSAGE;
- newlevel = myatoi(a->argv[3]);
- if ((newlevel < 0) || (newlevel > 7))
- return CLI_SHOWUSAGE;
- if (newlevel)
- ast_cli(a->fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
- else
- ast_cli(a->fd, "app_rpt Debugging disabled\n");
-
- debug = newlevel;
-
- return CLI_SUCCESS;
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+ newlevel = myatoi(argv[3]);
+ if((newlevel < 0) || (newlevel > 7))
+ return RESULT_SHOWUSAGE;
+ if(newlevel)
+ ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
+ else
+ ast_cli(fd, "app_rpt Debugging disabled\n");
+
+ debug = newlevel;
+ return RESULT_SUCCESS;
}
/*
* Dump rpt struct debugging onto console
*/
-static char *handle_cli_rpt_dump(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+
+static int rpt_do_dump(int fd, int argc, char *argv[])
{
int i;
- switch (cmd) {
- case CLI_INIT:
- e->command = "rpt dump";
- e->usage =
- "Usage: rpt dump <nodename>\n"
- " Dumps struct debug info to log\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 3)
- return CLI_SHOWUSAGE;
+ if (argc != 3)
+ return RESULT_SHOWUSAGE;
- for (i = 0; i < nrpts; i++) {
- if (!strcmp(a->argv[2], rpt_vars[i].name)) {
+ for(i = 0; i < nrpts; i++)
+ {
+ if (!strcmp(argv[2],rpt_vars[i].name))
+ {
rpt_vars[i].disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
- ast_cli(a->fd, "app_rpt struct dump requested for node %s\n", a->argv[2]);
- return CLI_SUCCESS;
+ ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
+ return RESULT_SUCCESS;
}
}
- return CLI_FAILURE;
+ return RESULT_FAILURE;
}
/*
* Dump statistics onto console
*/
-static char *handle_cli_rpt_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+
+static int rpt_do_stats(int fd, int argc, char *argv[])
{
- int i, j;
+ int i,j,numoflinks;
int dailytxtime, dailykerchunks;
+ time_t now;
int totalkerchunks, dailykeyups, totalkeyups, timeouts;
int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
+ int uptime;
long long totaltxtime;
- struct rpt_link *l;
+ struct rpt_link *l;
char *listoflinks[MAX_STAT_LINKS];
- char *lastnodewhichkeyedusup, *lastdtmfcommand;
+ char *lastdtmfcommand,*parrot_ena;
char *tot_state, *ider_state, *patch_state;
- char *reverse_patch_state, *enable_state, *input_signal, *called_number;
+ char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
+ char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
struct rpt *myrpt;
static char *not_applicable = "N/A";
- switch (cmd) {
- case CLI_INIT:
- e->command = "rpt stats";
- e->usage =
- "Usage: rpt stats <nodename>\n"
- " Dumps node statistics to console\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 3)
- return CLI_SHOWUSAGE;
-
- for (i = 0 ; i <= MAX_STAT_LINKS; i++)
- listoflinks[i] = NULL;
+ if(argc != 3)
+ return RESULT_SHOWUSAGE;
tot_state = ider_state =
patch_state = reverse_patch_state =
- input_signal = called_number =
- lastdtmfcommand = not_applicable;
+ input_signal = not_applicable;
+ called_number = lastdtmfcommand = NULL;
- for (i = 0; i < nrpts; i++) {
- if (!strcmp(a->argv[2], rpt_vars[i].name)) {
+ time(&now);
+ for(i = 0; i < nrpts; i++)
+ {
+ if (!strcmp(argv[2],rpt_vars[i].name)){
/* Make a copy of all stat variables while locked */
myrpt = &rpt_vars[i];
rpt_mutex_lock(&myrpt->lock); /* LOCK */
-
+ uptime = (int)(now - starttime);
dailytxtime = myrpt->dailytxtime;
totaltxtime = myrpt->totaltxtime;
dailykeyups = myrpt->dailykeyups;
@@ -1193,293 +2709,555 @@ static char *handle_cli_rpt_stats(struct ast_cli_entry *e, int cmd, struct ast_c
/* Traverse the list of connected nodes */
reverse_patch_state = "DOWN";
- j = 0;
+ numoflinks = 0;
l = myrpt->links.next;
- while (l != &myrpt->links) {
- if (l->name[0] == '0') { /* Skip '0' nodes */
+ while(l && (l != &myrpt->links)){
+ if(numoflinks >= MAX_STAT_LINKS){
+ ast_log(LOG_NOTICE,
+ "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
+ break;
+ }
+ if (l->name[0] == '0'){ /* Skip '0' nodes */
reverse_patch_state = "UP";
l = l->next;
continue;
}
- listoflinks[j] = ast_strdupa(l->name);
- if (listoflinks[j])
- j++;
+ listoflinks[numoflinks] = ast_strdup(l->name);
+ if(listoflinks[numoflinks] == NULL){
+ break;
+ }
+ else{
+ numoflinks++;
+ }
l = l->next;
}
- lastnodewhichkeyedusup = ast_strdupa(myrpt->lastnodewhichkeyedusup);
- if ((!lastnodewhichkeyedusup) || (ast_strlen_zero(lastnodewhichkeyedusup)))
- lastnodewhichkeyedusup = not_applicable;
-
- if (myrpt->keyed)
+ if(myrpt->keyed)
input_signal = "YES";
else
input_signal = "NO";
- if (myrpt->enable)
- enable_state = "YES";
+ if(myrpt->p.parrotmode)
+ parrot_ena = "ENABLED";
+ else
+ parrot_ena = "DISABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
+ sys_ena = "DISABLED";
+ else
+ sys_ena = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
+ tot_ena = "DISABLED";
+ else
+ tot_ena = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
+ link_ena = "DISABLED";
+ else
+ link_ena = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
+ patch_ena = "DISABLED";
+ else
+ patch_ena = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
+ sch_ena = "DISABLED";
+ else
+ sch_ena = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
+ user_funs = "DISABLED";
+ else
+ user_funs = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
+ tail_type = "ALTERNATE";
else
- enable_state = "NO";
+ tail_type = "STANDARD";
- if (!myrpt->totimer)
+ if(!myrpt->totimer)
tot_state = "TIMED OUT!";
- else if (myrpt->totimer != myrpt->p.totime)
+ else if(myrpt->totimer != myrpt->p.totime)
tot_state = "ARMED";
else
tot_state = "RESET";
- if (myrpt->tailid)
+ if(myrpt->tailid)
ider_state = "QUEUED IN TAIL";
- else if (myrpt->mustid)
+ else if(myrpt->mustid)
ider_state = "QUEUED FOR CLEANUP";
else
ider_state = "CLEAN";
- switch (myrpt->callmode) {
- case 1:
- patch_state = "DIALING";
- break;
- case 2:
- patch_state = "CONNECTING";
- break;
- case 3:
- patch_state = "UP";
- break;
- case 4:
- patch_state = "CALL FAILED";
- break;
- default:
- patch_state = "DOWN";
- }
+ switch(myrpt->callmode){
+ case 1:
+ patch_state = "DIALING";
+ break;
+ case 2:
+ patch_state = "CONNECTING";
+ break;
+ case 3:
+ patch_state = "UP";
+ break;
- if (!ast_strlen_zero(myrpt->exten))
- called_number = ast_strdupa(myrpt->exten);
+ case 4:
+ patch_state = "CALL FAILED";
+ break;
+
+ default:
+ patch_state = "DOWN";
+ }
- if (!ast_strlen_zero(myrpt->lastdtmfcommand))
- lastdtmfcommand = ast_strdupa(myrpt->lastdtmfcommand);
+ if(strlen(myrpt->exten)){
+ called_number = ast_strdup(myrpt->exten);
+ }
+ if(strlen(myrpt->lastdtmfcommand)){
+ lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
+ }
rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
- ast_cli(a->fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
- ast_cli(a->fd, "Signal on input..................................: %s\n", input_signal);
- ast_cli(a->fd, "Transmitter enabled..............................: %s\n", enable_state);
- ast_cli(a->fd, "Time out timer state.............................: %s\n", tot_state);
- ast_cli(a->fd, "Time outs since system initialization............: %d\n", timeouts);
- ast_cli(a->fd, "Identifier state.................................: %s\n", ider_state);
- ast_cli(a->fd, "Kerchunks today..................................: %d\n", dailykerchunks);
- ast_cli(a->fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
- ast_cli(a->fd, "Keyups today.....................................: %d\n", dailykeyups);
- ast_cli(a->fd, "Keyups since system initialization...............: %d\n", totalkeyups);
- ast_cli(a->fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
- ast_cli(a->fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
- ast_cli(a->fd, "Last DTMF command executed.......................: %s\n", lastdtmfcommand);
-
- hours = dailytxtime / 3600000;
+ ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
+ ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
+ ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
+ ast_cli(fd, "System...........................................: %s\n", sys_ena);
+ ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
+ ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
+ ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
+ ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
+ ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
+ ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
+ ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
+ ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
+ ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
+ ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
+ ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
+ ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
+ ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
+ ast_cli(fd, "Last DTMF command executed.......................: %s\n",
+ (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
+ hours = dailytxtime/3600000;
dailytxtime %= 3600000;
- minutes = dailytxtime / 60000;
+ minutes = dailytxtime/60000;
dailytxtime %= 60000;
- seconds = dailytxtime / 1000;
+ seconds = dailytxtime/1000;
dailytxtime %= 1000;
- ast_cli(a->fd, "TX time today ...................................: %02d:%02d:%02d.%d\n",
+ ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
hours, minutes, seconds, dailytxtime);
- hours = (int) totaltxtime / 3600000;
+ hours = (int) totaltxtime/3600000;
totaltxtime %= 3600000;
- minutes = (int) totaltxtime / 60000;
+ minutes = (int) totaltxtime/60000;
totaltxtime %= 60000;
- seconds = (int) totaltxtime / 1000;
+ seconds = (int) totaltxtime/1000;
totaltxtime %= 1000;
- ast_cli(a->fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
+ ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
hours, minutes, seconds, (int) totaltxtime);
- ast_cli(a->fd, "Nodes currently connected to us..................: ");
- for (j = 0;; j++) {
- if (!listoflinks[j]) {
- if (!j) {
- ast_cli(a->fd, "<NONE>");
+
+ hours = uptime/3600;
+ uptime %= 3600;
+ minutes = uptime/60;
+ uptime %= 60;
+
+ ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
+ hours, minutes, uptime);
+
+ ast_cli(fd, "Nodes currently connected to us..................: ");
+ if(!numoflinks){
+ ast_cli(fd,"<NONE>");
+ }
+ else{
+ for(j = 0 ;j < numoflinks; j++){
+ ast_cli(fd, "%s", listoflinks[j]);
+ if(j % 4 == 3){
+ ast_cli(fd, "\n");
+ ast_cli(fd, " : ");
+ }
+ else{
+ if((numoflinks - 1) - j > 0)
+ ast_cli(fd, ", ");
}
- break;
- }
- ast_cli(a->fd, "%s", listoflinks[j]);
- if (j % 4 == 3) {
- ast_cli(a->fd, "\n");
- ast_cli(a->fd, " : ");
- } else {
- if (listoflinks[j + 1])
- ast_cli(a->fd, ", ");
}
}
- ast_cli(a->fd, "\n");
-
- ast_cli(a->fd, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup);
- ast_cli(a->fd, "Autopatch state..................................: %s\n", patch_state);
- ast_cli(a->fd, "Autopatch called number..........................: %s\n", called_number);
- ast_cli(a->fd, "Reverse patch/IAXRPT connected...................: %s\n\n", reverse_patch_state);
-
- return CLI_SUCCESS;
+ ast_cli(fd,"\n");
+
+ ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
+ ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
+ ast_cli(fd, "Autopatch called number..........................: %s\n",
+ (called_number && strlen(called_number)) ? called_number : not_applicable);
+ ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
+ ast_cli(fd, "User linking commands............................: %s\n", link_ena);
+ ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
+
+ for(j = 0; j < numoflinks; j++){ /* ast_free() all link names */
+ ast_free(listoflinks[j]);
+ }
+ if(called_number){
+ ast_free(called_number);
+ }
+ if(lastdtmfcommand){
+ ast_free(lastdtmfcommand);
+ }
+ return RESULT_SUCCESS;
}
}
- return CLI_FAILURE;
+ return RESULT_FAILURE;
}
/*
* Link stats function
*/
-static char *handle_cli_rpt_lstats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+
+static int rpt_do_lstats(int fd, int argc, char *argv[])
{
- int i, j;
+ int i,j;
+ char *connstate;
struct rpt *myrpt;
struct rpt_link *l;
- struct rpt_lstat *s, *t;
+ struct rpt_lstat *s,*t;
struct rpt_lstat s_head;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "rpt lstats";
- e->usage =
- "Usage: rpt lstats <nodename>\n"
- " Dumps link statistics to console\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 3)
- return CLI_SHOWUSAGE;
+ if(argc != 3)
+ return RESULT_SHOWUSAGE;
s = NULL;
s_head.next = &s_head;
s_head.prev = &s_head;
- for (i = 0; i < nrpts; i++) {
- if (!strcmp(a->argv[2], rpt_vars[i].name)) {
+ for(i = 0; i < nrpts; i++)
+ {
+ if (!strcmp(argv[2],rpt_vars[i].name)){
/* Make a copy of all stat variables while locked */
myrpt = &rpt_vars[i];
rpt_mutex_lock(&myrpt->lock); /* LOCK */
/* Traverse the list of connected nodes */
j = 0;
l = myrpt->links.next;
- while (l != &myrpt->links) {
- if (l->name[0] == '0') { /* Skip '0' nodes */
+ while(l && (l != &myrpt->links)){
+ if (l->name[0] == '0'){ /* Skip '0' nodes */
l = l->next;
continue;
}
- if ((s = ast_calloc(1, sizeof(*s))) == NULL) {
+ if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
- return CLI_FAILURE;
+ return RESULT_FAILURE;
}
- ast_copy_string(s->name, l->name, MAXREMSTR);
- pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
+ memset(s, 0, sizeof(struct rpt_lstat));
+ strncpy(s->name, l->name, MAXREMSTR - 1);
+ if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
+ else strcpy(s->peer,"(none)");
s->mode = l->mode;
s->outbound = l->outbound;
s->reconnects = l->reconnects;
s->connecttime = l->connecttime;
+ s->thisconnected = l->thisconnected;
+ memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
insque((struct qelem *) s, (struct qelem *) s_head.next);
+ memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
l = l->next;
}
rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
- ast_cli(a->fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME\n");
- ast_cli(a->fd, "---- ---- ---------- --------- ------------\n");
+ ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
+ ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
- for (s = s_head.next; s != &s_head; s = s->next) {
+ for(s = s_head.next; s != &s_head; s = s->next){
int hours, minutes, seconds;
long long connecttime = s->connecttime;
- char conntime[31];
+ char conntime[21];
hours = (int) connecttime/3600000;
connecttime %= 3600000;
minutes = (int) connecttime/60000;
connecttime %= 60000;
seconds = (int) connecttime/1000;
connecttime %= 1000;
- snprintf(conntime, sizeof(conntime), "%02d:%02d:%02d.%d",
+ snprintf(conntime, 20, "%02d:%02d:%02d.%d",
hours, minutes, seconds, (int) connecttime);
- ast_cli(a->fd, "%-10s%-20s%-12d%-11s%-30s\n",
- s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime);
+ conntime[20] = 0;
+ if(s->thisconnected)
+ connstate = "ESTABLISHED";
+ else
+ connstate = "CONNECTING";
+ ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
+ s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
}
/* destroy our local link queue */
s = s_head.next;
- while (s != &s_head) {
+ while(s != &s_head){
t = s;
s = s->next;
remque((struct qelem *)t);
ast_free(t);
}
- return CLI_SUCCESS;
+ return RESULT_SUCCESS;
}
}
+ return RESULT_FAILURE;
+}
+
+/*
+* List all nodes connected, directly or indirectly
+*/
+
+static int rpt_do_nodes(int fd, int argc, char *argv[])
+{
+ int i,j;
+ char ns;
+ char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
+ struct rpt *myrpt;
+ if(argc != 3)
+ return RESULT_SHOWUSAGE;
- return CLI_FAILURE;
+ for(i = 0; i < nrpts; i++)
+ {
+ if (!strcmp(argv[2],rpt_vars[i].name)){
+ /* Make a copy of all stat variables while locked */
+ myrpt = &rpt_vars[i];
+ rpt_mutex_lock(&myrpt->lock); /* LOCK */
+ __mklinklist(myrpt,NULL,lbuf);
+ rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
+ /* parse em */
+ ns = finddelim(lbuf,strs,MAXLINKLIST);
+ /* sort em */
+ if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
+ ast_cli(fd,"\n");
+ ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
+ for(j = 0 ;; j++){
+ if(!strs[j]){
+ if(!j){
+ ast_cli(fd,"<NONE>");
+ }
+ break;
+ }
+ ast_cli(fd, "%s", strs[j]);
+ if(j % 8 == 7){
+ ast_cli(fd, "\n");
+ }
+ else{
+ if(strs[j + 1])
+ ast_cli(fd, ", ");
+ }
+ }
+ ast_cli(fd,"\n\n");
+ return RESULT_SUCCESS;
+ }
+ }
+ return RESULT_FAILURE;
}
/*
+* List all locally configured nodes
+*/
+
+static int rpt_do_local_nodes(int fd, int argc, char *argv[])
+{
+
+ int i;
+ ast_cli(fd, "\nNode\n----\n");
+ for (i=0; i< nrpts; i++)
+ {
+ ast_cli(fd, "%s\n", rpt_vars[i].name);
+ } /* for i */
+ ast_cli(fd,"\n");
+ return RESULT_SUCCESS;
+}
+
+
+/*
* reload vars
*/
-static char *handle_cli_rpt_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+
+static int rpt_do_reload(int fd, int argc, char *argv[])
+{
+int n;
+
+ if (argc > 2) return RESULT_SHOWUSAGE;
+
+ for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
+
+ return RESULT_FAILURE;
+}
+
+/*
+* restart app_rpt
+*/
+
+static int rpt_do_restart(int fd, int argc, char *argv[])
{
- int n;
+int i;
- switch (cmd) {
- case CLI_INIT:
- e->command = "rpt reload";
- e->usage =
- "Usage: rpt reload\n"
- " Reloads app_rpt running config parameters\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
+ if (argc > 2) return RESULT_SHOWUSAGE;
+ for(i = 0; i < nrpts; i++)
+ {
+ if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
}
+ return RESULT_FAILURE;
+}
- if (a->argc > 2)
- return CLI_SHOWUSAGE;
- for (n = 0; n < nrpts; n++)
- rpt_vars[n].reload = 1;
+/*
+* send an app_rpt DTMF function from the CLI
+*/
+
+static int rpt_do_fun(int fd, int argc, char *argv[])
+{
+ int i,busy=0;
+
+ if (argc != 4) return RESULT_SHOWUSAGE;
- return CLI_SUCCESS;
+ for(i = 0; i < nrpts; i++){
+ if(!strcmp(argv[2], rpt_vars[i].name)){
+ struct rpt *myrpt = &rpt_vars[i];
+ rpt_mutex_lock(&myrpt->lock);
+ if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
+ rpt_mutex_unlock(&myrpt->lock);
+ busy=1;
+ }
+ if(!busy){
+ myrpt->macrotimer = MACROTIME;
+ strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ }
+ }
+ if(busy){
+ ast_cli(fd, "Function decoder busy");
+ }
+ return RESULT_FAILURE;
}
+/*
+ the convention is that macros in the data from the rpt() application
+ are all at the end of the data, separated by the | and start with a *
+ when put into the macro buffer, the characters have their high bit
+ set so the macro processor knows they came from the application data
+ and to use the alt-functions table.
+ sph:
+*/
+static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
+{
+ int busy=0;
+
+ rpt_mutex_lock(&myrpt->lock);
+ if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
+ rpt_mutex_unlock(&myrpt->lock);
+ busy=1;
+ }
+ if(!busy){
+ int x;
+ if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
+ myrpt->macrotimer = MACROTIME;
+ for(x = 0; *(sptr + x); x++)
+ myrpt->macrobuf[x] = *(sptr + x) | 0x80;
+ *(sptr + x) = 0;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
+
+ return busy;
+}
/*
-* restart app_rpt
+ allows us to test rpt() application data commands
*/
-static char *handle_cli_rpt_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static int rpt_do_fun1(int fd, int argc, char *argv[])
{
int i;
- switch (cmd) {
- case CLI_INIT:
- e->command = "rpt restart";
- e->usage =
- "Usage: rpt restart\n"
- " Restarts app_rpt\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
+ if (argc != 4) return RESULT_SHOWUSAGE;
- if (a->argc > 2)
- return CLI_SHOWUSAGE;
- for (i = 0; i < nrpts; i++) {
- if (rpt_vars[i].rxchannel)
- ast_softhangup(rpt_vars[i].rxchannel, AST_SOFTHANGUP_DEV);
+ for(i = 0; i < nrpts; i++){
+ if(!strcmp(argv[2], rpt_vars[i].name)){
+ struct rpt *myrpt = &rpt_vars[i];
+ rpt_push_alt_macro(myrpt,argv[3]);
+ }
}
- return CLI_SUCCESS;
+ return RESULT_FAILURE;
}
+/*
+* send an app_rpt **command** from the CLI
+*/
+
+static int rpt_do_cmd(int fd, int argc, char *argv[])
+{
+ int i, l;
+ int busy=0;
+ int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
+
+ int thisRpt = -1;
+ int thisAction = -1;
+ struct rpt *myrpt = NULL;
+ if (argc != 6) return RESULT_SHOWUSAGE;
+
+ for(i = 0; i < nrpts; i++)
+ {
+ if(!strcmp(argv[2], rpt_vars[i].name))
+ {
+ thisRpt = i;
+ myrpt = &rpt_vars[i];
+ break;
+ } /* if !strcmp... */
+ } /* for i */
+
+ if (thisRpt < 0)
+ {
+ ast_cli(fd, "Unknown node number %s.\n", argv[2]);
+ return RESULT_FAILURE;
+ } /* if thisRpt < 0 */
+
+ /* Look up the action */
+ l = strlen(argv[3]);
+ for(i = 0 ; i < maxActions; i++)
+ {
+ if(!strncasecmp(argv[3], function_table[i].action, l))
+ {
+ thisAction = i;
+ break;
+ } /* if !strncasecmp... */
+ } /* for i */
+
+ if (thisAction < 0)
+ {
+ ast_cli(fd, "Unknown action name %s.\n", argv[3]);
+ return RESULT_FAILURE;
+ } /* if thisAction < 0 */
+
+ /* at this point, it looks like all the arguments make sense... */
+
+ rpt_mutex_lock(&myrpt->lock);
+
+ if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
+ {
+ rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
+ rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
+ strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
+ strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
+ rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
+ rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
+ } /* if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE */
+ else
+ {
+ busy = 1;
+ } /* if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE */
+ rpt_mutex_unlock(&myrpt->lock);
+
+ return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
+} /* rpt_do_cmd() */
static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
{
int res;
- if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
- return res;
-
- while (chan->generatordata) {
- if (ast_safe_sleep(chan, 1))
- return -1;
+ if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
+ return res;
+
+ while(chan->generatordata) {
+ if (ast_safe_sleep(chan,1)) return -1;
}
- return 0;
+ return 0;
}
static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
@@ -1492,11 +3270,197 @@ static int play_silence(struct ast_channel *chan, int duration)
return play_tone_pair(chan, 0, 0, duration, 0);
}
+#ifdef NEW_ASTERISK
+
+static char *res2cli(int r)
+
+{
+ switch (r)
+ {
+ case RESULT_SUCCESS:
+ return(CLI_SUCCESS);
+ case RESULT_SHOWUSAGE:
+ return(CLI_SHOWUSAGE);
+ default:
+ return(CLI_FAILURE);
+ }
+}
+
+static char *handle_cli_debug(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt debug level";
+ e->usage = debug_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_debug(a->fd,a->argc,a->argv));
+}
+
+static char *handle_cli_dump(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt dump level";
+ e->usage = dump_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
+}
+
+
+static char *handle_cli_stats(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt stats";
+ e->usage = dump_stats;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
+}
+
+static char *handle_cli_nodes(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt nodes";
+ e->usage = dump_nodes;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
+}
+
+static char *handle_cli_local_nodes(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt localnodes";
+ e->usage = usage_local_nodes;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
+}
+
+static char *handle_cli_lstats(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt lstats";
+ e->usage = dump_lstats;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
+}
+
+static char *handle_cli_reload(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt reload";
+ e->usage = reload_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
+}
+
+static char *handle_cli_restart(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt restart";
+ e->usage = restart_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
+}
+
+static char *handle_cli_fun(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt fun";
+ e->usage = fun_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
+}
+
+static char *handle_cli_fun1(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt fun1";
+ e->usage = fun_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
+}
+
+static char *handle_cli_cmd(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "rpt cmd";
+ e->usage = cmd_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
+}
+
+static struct ast_cli_entry rpt_cli[] = {
+ AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
+ AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
+ AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
+ AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
+ AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
+ AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
+ AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
+ AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
+ AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
+ AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
+ AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
+};
+
+#endif
-static int send_morse(struct ast_channel *chan, const char *string, int speed, int freq, int amplitude)
+static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
{
- static struct morse_bits mbits[] = {
+static struct morse_bits mbits[] = {
{0, 0}, /* SPACE */
{0, 0},
{6, 18},/* " */
@@ -1530,8 +3494,8 @@ static int send_morse(struct ast_channel *chan, const char *string, int speed, i
{0, 0},
{6, 12},/* ? */
{0, 0},
- {2, 2}, /* A */
- {4, 1}, /* B */
+ {2, 2}, /* A */
+ {4, 1}, /* B */
{4, 5}, /* C */
{3, 1}, /* D */
{1, 0}, /* E */
@@ -1558,6 +3522,7 @@ static int send_morse(struct ast_channel *chan, const char *string, int speed, i
{4, 3} /* Z */
};
+
int dottime;
int dashtime;
int intralettertime;
@@ -1573,33 +3538,33 @@ static int send_morse(struct ast_channel *chan, const char *string, int speed, i
/* Approximate the dot time from the speed arg. */
- dottime = 900 / speed;
+ dottime = 900/speed;
- /* Establish timing relationships */
+ /* Establish timing releationships */
dashtime = 3 * dottime;
intralettertime = dottime;
interlettertime = dottime * 4 ;
interwordtime = dottime * 7;
- for (; (*string) && (!res); string++) {
+ for(;(*string) && (!res); string++){
c = *string;
/* Convert lower case to upper case */
- if ((c >= 'a') && (c <= 'z'))
+ if((c >= 'a') && (c <= 'z'))
c -= 0x20;
/* Can't deal with any char code greater than Z, skip it */
- if (c > 'Z')
+ if(c > 'Z')
continue;
/* If space char, wait the inter word time */
- if (c == ' ') {
- if (!res)
+ if(c == ' '){
+ if(!res)
res = play_silence(chan, interwordtime);
continue;
}
@@ -1615,17 +3580,17 @@ static int send_morse(struct ast_channel *chan, const char *string, int speed, i
/* Send the character */
- for (; len ; len--) {
- if (!res)
+ for(; len ; len--){
+ if(!res)
res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
- if (!res)
+ if(!res)
res = play_silence(chan, intralettertime);
ddcomb >>= 1;
}
/* Wait the interletter time */
- if (!res)
+ if(!res)
res = play_silence(chan, interlettertime - intralettertime);
}
@@ -1639,12 +3604,12 @@ static int send_morse(struct ast_channel *chan, const char *string, int speed, i
* Wait for the zaptel driver to physically write the tone blocks to the hardware
*/
- for (i = 0; i < 20 ; i++) {
+ for(i = 0; i < 20 ; i++){
flags = ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT;
res = ioctl(chan->fds[0], ZT_IOMUX, &flags);
- if (flags & ZT_IOMUX_WRITEEMPTY)
+ if(flags & ZT_IOMUX_WRITEEMPTY)
break;
- if ( ast_safe_sleep(chan, 50)) {
+ if( ast_safe_sleep(chan, 50)){
res = -1;
break;
}
@@ -1654,11 +3619,11 @@ static int send_morse(struct ast_channel *chan, const char *string, int speed, i
return res;
}
-static int send_tone_telemetry(struct ast_channel *chan, const char *tonestring)
+static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
{
- char *stringp;
+ char *p,*stringp;
char *tonesubset;
- int f1, f2;
+ int f1,f2;
int duration;
int amplitude;
int res;
@@ -1666,48 +3631,54 @@ static int send_tone_telemetry(struct ast_channel *chan, const char *tonestring)
int flags;
res = 0;
+
+ if(!tonestring)
+ return res;
- stringp = ast_strdupa(tonestring);
+ p = stringp = ast_strdup(tonestring);
- for (;tonestring;) {
- tonesubset = strsep(&stringp, ")");
- if (!tonesubset)
+ for(;tonestring;){
+ tonesubset = strsep(&stringp,")");
+ if(!tonesubset)
break;
- if (sscanf(tonesubset, "(%d,%d,%d,%d", &f1, &f2, &duration, &amplitude) != 4)
+ if(sscanf(tonesubset,"(%d,%d,%d,%d", &f1, &f2, &duration, &amplitude) != 4)
break;
res = play_tone_pair(chan, f1, f2, duration, amplitude);
- if (res)
+ if(res)
break;
}
- if (!res)
+ if(p)
+ ast_free(p);
+ if(!res)
res = play_tone_pair(chan, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */
if (!res)
res = ast_waitstream(chan, "");
+
ast_stopstream(chan);
/*
* Wait for the zaptel driver to physically write the tone blocks to the hardware
*/
- for (i = 0; i < 20 ; i++) {
+ for(i = 0; i < 20 ; i++){
flags = ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT;
res = ioctl(chan->fds[0], ZT_IOMUX, &flags);
- if (flags & ZT_IOMUX_WRITEEMPTY)
+ if(flags & ZT_IOMUX_WRITEEMPTY)
break;
- if (ast_safe_sleep(chan, 50)) {
+ if( ast_safe_sleep(chan, 50)){
res = -1;
break;
}
}
return res;
+
}
-
-static int sayfile(struct ast_channel *mychannel, const char *fname)
+static int sayfile(struct ast_channel *mychannel,char *fname)
{
- int res;
+int res;
res = ast_streamfile(mychannel, fname, mychannel->language);
if (!res)
@@ -1718,11 +3689,11 @@ static int sayfile(struct ast_channel *mychannel, const char *fname)
return res;
}
-static int saycharstr(struct ast_channel *mychannel, char *str)
+static int saycharstr(struct ast_channel *mychannel,char *str)
{
- int res;
+int res;
- res = ast_say_character_str(mychannel, str, NULL, mychannel->language);
+ res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
@@ -1735,7 +3706,7 @@ static int saynum(struct ast_channel *mychannel, int num)
{
int res;
res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
- if (!res)
+ if(!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
@@ -1743,20 +3714,26 @@ static int saynum(struct ast_channel *mychannel, int num)
return res;
}
-static int saydigits(struct ast_channel *mychannel, int num)
+/* say a node and nodename. Try to look in dir referred to by nodenames in
+config, and see if there's a custom node file to play, and if so, play it */
+
+static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
{
- int res;
- res = ast_say_digits(mychannel, num, NULL, mychannel->language);
- if (!res)
- res = ast_waitstream(mychannel, "");
- else
- ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
- ast_stopstream(mychannel);
+int res;
+char *val,fname[300];
+
+ val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
+ if (!val) val = NODENAMES;
+ snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
+ if (ast_fileexists(fname,NULL,mychannel->language) > 0)
+ return(sayfile(mychannel,fname));
+ res = sayfile(mychannel,"rpt/node");
+ if (!res)
+ res = ast_say_character_str(mychannel,name,NULL,mychannel->language);
return res;
}
-
-static int telem_any(struct rpt *myrpt, struct ast_channel *chan, const char *entry)
+static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
{
int res;
char c;
@@ -1770,35 +3747,38 @@ static int telem_any(struct rpt *myrpt, struct ast_channel *chan, const char *en
res = 0;
- if (!morseidfreq) { /* Get the morse parameters if not already loaded */
+ if(!morseidfreq){ /* Get the morse parameters if not already loaded */
morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
- morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
- morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
+ morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
+ morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
}
/* Is it a file, or a tone sequence? */
- if (entry[0] == '|') {
+ if(entry[0] == '|'){
c = entry[1];
- if ((c >= 'a') && (c <= 'z'))
+ if((c >= 'a')&&(c <= 'z'))
c -= 0x20;
- switch (c) {
- case 'I': /* Morse ID */
- res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
- break;
- case 'M': /* Morse Message */
- res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
- break;
- case 'T': /* Tone sequence */
- res = send_tone_telemetry(chan, entry + 2);
- break;
- default:
- res = -1;
+ switch(c){
+ case 'I': /* Morse ID */
+ res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
+ break;
+
+ case 'M': /* Morse Message */
+ res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
+ break;
+
+ case 'T': /* Tone sequence */
+ res = send_tone_telemetry(chan, entry + 2);
+ break;
+ default:
+ res = -1;
}
- } else
+ }
+ else
res = sayfile(chan, entry); /* File */
return res;
}
@@ -1809,32 +3789,48 @@ static int telem_any(struct rpt *myrpt, struct ast_channel *chan, const char *en
* 4 types of telemtry are handled: Morse ID, Morse Message, Tone Sequence, and a File containing a recording.
*/
-static int telem_lookup(struct rpt *myrpt, struct ast_channel *chan, const char *node, const char *name)
+static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
{
- int res = 0;
+
+ int res;
int i;
- const char *entry = NULL;
- const char *telemetry;
+ char *entry;
+ char *telemetry;
+ char *telemetry_save;
+ res = 0;
+ telemetry_save = NULL;
+ entry = NULL;
+
/* Retrieve the section name for telemetry from the node section */
- if ((telemetry = ast_variable_retrieve(myrpt->cfg, node, TELEMETRY)))
- entry = ast_variable_retrieve(myrpt->cfg, telemetry, name);
-
+ telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
+ if(telemetry ){
+ telemetry_save = ast_strdup(telemetry);
+ if(!telemetry_save){
+ ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
+ return res;
+ }
+ entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
+ }
+
/* Try to look up the telemetry name */
- if (!entry) {
+ if(!entry){
/* Telemetry name wasn't found in the config file, use the default */
- for (i = 0; i < sizeof(tele_defs) / sizeof(struct telem_defaults); i++) {
- if (!strcasecmp(tele_defs[i].name, name))
+ for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
+ if(!strcasecmp(tele_defs[i].name, name))
entry = tele_defs[i].value;
}
}
- if (entry) {
- if (!ast_strlen_zero(entry))
- telem_any(myrpt, chan, entry);
- } else {
+ if(entry){
+ if(strlen(entry))
+ if (chan) telem_any(myrpt,chan, entry);
+ }
+ else{
res = -1;
}
+ if(telemetry_save)
+ ast_free(telemetry_save);
return res;
}
@@ -1844,175 +3840,285 @@ static int telem_lookup(struct rpt *myrpt, struct ast_channel *chan, const char
static int get_wait_interval(struct rpt *myrpt, int type)
{
- int interval = 1000;
- const char *wait_times = ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
-
- switch (type) {
- case DLY_TELEM:
- if (wait_times)
- interval = retrieve_astcfgint(myrpt, wait_times, "telemwait", 500, 5000, 1000);
- break;
- case DLY_ID:
- if (wait_times)
- interval = retrieve_astcfgint(myrpt, wait_times, "idwait", 250, 5000, 500);
- else
- interval = 500;
- break;
- case DLY_UNKEY:
- if (wait_times)
- interval = retrieve_astcfgint(myrpt, wait_times, "unkeywait", 500, 5000, 1000);
- break;
- case DLY_CALLTERM:
- if (wait_times)
- interval = retrieve_astcfgint(myrpt, wait_times, "calltermwait", 500, 5000, 1500);
- break;
- default:
- return 0;
- }
+ int interval;
+ char *wait_times;
+ char *wait_times_save;
+
+ wait_times_save = NULL;
+ wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
+
+ if(wait_times){
+ wait_times_save = ast_strdup(wait_times);
+ if(!wait_times_save)
+ return 0;
+
+ }
+
+ switch(type){
+ case DLY_TELEM:
+ if(wait_times)
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
+ else
+ interval = 1000;
+ break;
+
+ case DLY_ID:
+ if(wait_times)
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
+ else
+ interval = 500;
+ break;
+
+ case DLY_UNKEY:
+ if(wait_times)
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
+ else
+ interval = 1000;
+ break;
+
+ case DLY_LINKUNKEY:
+ if(wait_times)
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
+ else
+ interval = 1000;
+ break;
+
+ case DLY_CALLTERM:
+ if(wait_times)
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
+ else
+ interval = 1500;
+ break;
+
+ case DLY_COMP:
+ if(wait_times)
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
+ else
+ interval = 200;
+ break;
+
+ case DLY_PARROT:
+ if(wait_times)
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
+ else
+ interval = 200;
+ break;
+
+ default:
+ interval = 0;
+ break;
+ }
+ if(wait_times_save)
+ ast_free(wait_times_save);
return interval;
-}
+}
/*
* Wait a configurable interval of time
*/
-
-
static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
{
int interval;
interval = get_wait_interval(myrpt, type);
- if (debug)
- ast_log(LOG_NOTICE, " Delay interval = %d\n", interval);
- if (interval)
- ast_safe_sleep(chan, interval);
- if (debug)
- ast_log(LOG_NOTICE, "Delay complete\n");
+ if(debug)
+ ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
+ if(interval)
+ ast_safe_sleep(chan,interval);
+ if(debug)
+ ast_log(LOG_NOTICE,"Delay complete\n");
return;
}
+static int split_freq(char *mhz, char *decimals, char *freq);
static void *rpt_tele_thread(void *this)
{
- ZT_CONFINFO ci; /* conference info */
- int res = 0, haslink, hastx, hasremote, imdone = 0, unkeys_queued, x;
- struct rpt_tele *mytele = (struct rpt_tele *)this;
- struct rpt_tele *tlist;
- struct rpt *myrpt;
- struct rpt_link *l, *m, linkbase;
- struct ast_channel *mychannel;
- const char *p, *ct;
- struct timeval tv;
- struct ast_tm localtm;
-#ifdef APP_RPT_LOCK_DEBUG
- struct lockthread *t;
+ZT_CONFINFO ci; /* conference info */
+int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
+struct rpt_tele *mytele = (struct rpt_tele *)this;
+struct rpt_tele *tlist;
+struct rpt *myrpt;
+struct rpt_link *l,*l1,linkbase;
+struct ast_channel *mychannel;
+int id_malloc, vmajor, vminor, m;
+char *p,*ct,*ct_copy,*ident, *nodename,*cp;
+time_t t;
+#ifdef NEW_ASTERISK
+struct ast_tm localtm;
+#else
+struct tm localtm;
#endif
+char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
+int i,ns,rbimode;
+char mhz[MAXREMSTR];
+char decimals[MAXREMSTR];
+char mystr[200];
+struct zt_params par;
+
/* get a pointer to myrpt */
myrpt = mytele->rpt;
/* Snag copies of a few key myrpt variables */
rpt_mutex_lock(&myrpt->lock);
+ nodename = ast_strdup(myrpt->name);
+ if(!nodename)
+ {
+ fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
+ rpt_mutex_lock(&myrpt->lock);
+ remque((struct qelem *)mytele);
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_free(mytele);
+ pthread_exit(NULL);
+ }
+
+ if (myrpt->p.ident){
+ ident = ast_strdup(myrpt->p.ident);
+ if(!ident)
+ {
+ fprintf(stderr,"rpt:Sorry unable strdup ident\n");
+ rpt_mutex_lock(&myrpt->lock);
+ remque((struct qelem *)mytele);
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
+ __LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_free(nodename);
+ ast_free(mytele);
+ pthread_exit(NULL);
+ }
+ else{
+ id_malloc = 1;
+ }
+ }
+ else
+ {
+ ident = "";
+ id_malloc = 0;
+ }
rpt_mutex_unlock(&myrpt->lock);
-
+
+
+
/* allocate a pseudo-channel thru asterisk */
- mychannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
- if (!mychannel) {
- ast_log(LOG_WARNING, "rpt: unable to obtain pseudo channel\n");
+ mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!mychannel)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
rpt_mutex_lock(&myrpt->lock);
remque((struct qelem *)mytele);
- ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
rpt_mutex_unlock(&myrpt->lock);
- ast_free(mytele);
+ ast_free(nodename);
+ if(id_malloc)
+ ast_free(ident);
+ ast_free(mytele);
pthread_exit(NULL);
}
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (mychannel->cdr)
+ ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
rpt_mutex_lock(&myrpt->lock);
- mytele->chan = mychannel; /* Save a copy of the channel so we can access it externally if need be */
+ mytele->chan = mychannel;
rpt_mutex_unlock(&myrpt->lock);
-
+
+ while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
+ (mytele->mode != LINKUNKEY))
+ {
+ rpt_mutex_lock(&myrpt->lock);
+ if (!myrpt->active_telem)
+ {
+ myrpt->active_telem = mytele;
+ rpt_mutex_unlock(&myrpt->lock);
+ break;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ usleep(100000);
+ }
+
/* make a conference for the tx */
ci.chan = 0;
- /* If there's an ID queued, or tail message queued, */
+ /* If the telemetry is only intended for a local audience, */
/* only connect the ID audio to the local tx conference so */
/* linked systems can't hear it */
ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
- (mytele->mode == TAILMSG)) ?
+ (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
+ (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
myrpt->txconf : myrpt->conf);
ci.confmode = ZT_CONF_CONFANN;
/* 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)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
rpt_mutex_lock(&myrpt->lock);
+ myrpt->active_telem = NULL;
remque((struct qelem *)mytele);
rpt_mutex_unlock(&myrpt->lock);
- ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
- ast_free(mytele);
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ ast_free(nodename);
+ if(id_malloc)
+ ast_free(ident);
+ ast_free(mytele);
ast_hangup(mychannel);
pthread_exit(NULL);
}
ast_stopstream(mychannel);
- switch (mytele->mode) {
- case ID:
- case ID1:
+ switch(mytele->mode)
+ {
+ case ID:
+ case ID1:
/* wait a bit */
- wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM, mychannel);
- res = telem_any(myrpt, mychannel, myrpt->p.ident);
+ wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
+ res = telem_any(myrpt,mychannel, ident);
imdone=1;
break;
- case TAILMSG:
- res = ast_streamfile(mychannel, myrpt->p.tailmsg.msgs[myrpt->tailmessagen], mychannel->language);
+ case TAILMSG:
+ res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
break;
- case IDTALKOVER:
- p = ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
- if (p)
- res = telem_any(myrpt, mychannel, p);
- imdone = 1;
- break;
- case PROC:
+ case IDTALKOVER:
+ p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
+ if(p)
+ res = telem_any(myrpt,mychannel, p);
+ imdone=1;
+ break;
+
+ case PROC:
/* wait a little bit longer */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
- if (res < 0) { /* Then default message */
+ if(res < 0){ /* Then default message */
res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
}
break;
- case TERM:
+ case TERM:
/* wait a little bit longer */
wait_interval(myrpt, DLY_CALLTERM, mychannel);
res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
- if (res < 0) { /* Then default message */
+ if(res < 0){ /* Then default message */
res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
}
break;
- case COMPLETE:
+ case COMPLETE:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
- res = telem_lookup(myrpt, mychannel, myrpt->name, "functcomplete");
+ res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
break;
- case MACRO_NOTFOUND:
+ case MACRO_NOTFOUND:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
break;
- case GOSUB_NOTFOUND:
- /* wait a little bit */
- wait_interval(myrpt, DLY_TELEM, mychannel);
- res = ast_streamfile(mychannel, "rpt/gosub_notfound", mychannel->language);
- break;
- case MACRO_BUSY:
+ case MACRO_BUSY:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
break;
- case GOSUB_BUSY:
- /* wait a little bit */
- wait_interval(myrpt, DLY_TELEM, mychannel);
- res = ast_streamfile(mychannel, "rpt/gosub_busy", mychannel->language);
- break;
- case UNKEY:
- if (myrpt->patchnoct && myrpt->callmode) { /* If no CT during patch configured, then don't send one */
+ case UNKEY:
+ if(myrpt->patchnoct && myrpt->callmode){ /* If no CT during patch configured, then don't send one */
imdone = 1;
break;
}
@@ -2032,31 +4138,32 @@ static void *rpt_tele_thread(void *this)
tlist = myrpt->tele.next;
unkeys_queued = 0;
- if (tlist != &myrpt->tele) {
- rpt_mutex_lock(&myrpt->lock);
- while (tlist != &myrpt->tele) {
- if (tlist->mode == UNKEY)
- unkeys_queued++;
- tlist = tlist->next;
- }
- rpt_mutex_unlock(&myrpt->lock);
- }
- if (unkeys_queued > 1) {
+ if (tlist != &myrpt->tele)
+ {
+ rpt_mutex_lock(&myrpt->lock);
+ while(tlist != &myrpt->tele){
+ if (tlist->mode == UNKEY) unkeys_queued++;
+ tlist = tlist->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ }
+ if( unkeys_queued > 1){
imdone = 1;
break;
}
/* Wait for the telemetry timer to expire */
/* Periodically check the timer since it can be re-initialized above */
- while (myrpt->unkeytocttimer) {
+ while(myrpt->unkeytocttimer)
+ {
int ctint;
- if (myrpt->unkeytocttimer > 100)
+ if(myrpt->unkeytocttimer > 100)
ctint = 100;
else
ctint = myrpt->unkeytocttimer;
ast_safe_sleep(mychannel, ctint);
rpt_mutex_lock(&myrpt->lock);
- if (myrpt->unkeytocttimer < ctint)
+ if(myrpt->unkeytocttimer < ctint)
myrpt->unkeytocttimer = 0;
else
myrpt->unkeytocttimer -= ctint;
@@ -2067,7 +4174,7 @@ static void *rpt_tele_thread(void *this)
* Now, the carrier on the rptr rx should be gone.
* If it re-appeared, then forget about sending the CT
*/
- if (myrpt->keyed) {
+ if(myrpt->keyed){
imdone = 1;
break;
}
@@ -2081,143 +4188,609 @@ static void *rpt_tele_thread(void *this)
hastx = 0;
hasremote = 0;
l = myrpt->links.next;
- if (l != &myrpt->links) {
+ if (l != &myrpt->links)
+ {
rpt_mutex_lock(&myrpt->lock);
- while (l != &myrpt->links) {
- if (l->name[0] == '0') {
+ while(l != &myrpt->links)
+ {
+ if (l->name[0] == '0')
+ {
l = l->next;
continue;
}
haslink = 1;
if (l->mode) {
hastx++;
- if (l->isremote)
- hasremote++;
+ if (l->isremote) hasremote++;
}
l = l->next;
}
rpt_mutex_unlock(&myrpt->lock);
}
- if (haslink) {
- res = telem_lookup(myrpt, mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
- if (res)
- ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
+ if (haslink)
+ {
+ res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
+ if(res)
+ ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
+
+
/* if in remote cmd mode, indicate it */
- if (myrpt->cmdnode[0]) {
- ast_safe_sleep(mychannel, 200);
- res = telem_lookup(myrpt, mychannel, myrpt->name, "cmdmode");
- if (res)
+ if (myrpt->cmdnode[0])
+ {
+ ast_safe_sleep(mychannel,200);
+ res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
+ if(res)
ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
}
- } else if ((ct = ast_variable_retrieve(myrpt->cfg, myrpt->name, "unlinkedct"))) { /* Unlinked Courtesy Tone */
- res = telem_lookup(myrpt, mychannel, myrpt->name, ct);
- if (res)
+ }
+ else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */
+ ct_copy = ast_strdup(ct);
+ if(ct_copy)
+ {
+ res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
+ ast_free(ct_copy);
+ }
+ else
+ res = -1;
+ if(res)
ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
}
- if (hasremote && (!myrpt->cmdnode[0])) {
+ if (hasremote && (!myrpt->cmdnode[0]))
+ {
/* set for all to hear */
ci.chan = 0;
ci.confno = myrpt->conf;
ci.confmode = ZT_CONF_CONFANN;
/* 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)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
rpt_mutex_lock(&myrpt->lock);
+ myrpt->active_telem = NULL;
remque((struct qelem *)mytele);
rpt_mutex_unlock(&myrpt->lock);
- ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
- ast_free(mytele);
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ ast_free(nodename);
+ if(id_malloc)
+ ast_free(ident);
+ ast_free(mytele);
ast_hangup(mychannel);
pthread_exit(NULL);
}
- if ((ct = ast_variable_retrieve(myrpt->cfg, myrpt->name, "remotect"))) { /* Unlinked Courtesy Tone */
- ast_safe_sleep(mychannel, 200);
- res = telem_lookup(myrpt, mychannel, myrpt->name, ct);
- if (res)
+ if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){ /* Unlinked Courtesy Tone */
+ ast_safe_sleep(mychannel,200);
+ ct_copy = ast_strdup(ct);
+ if(ct_copy)
+ {
+ res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
+ ast_free(ct_copy);
+ }
+ else
+ res = -1;
+
+ if(res)
ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
}
}
-#ifdef _MDC_DECODE_H_
- if (myrpt->lastunit) {
+#if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
+ if (myrpt->lastunit)
+ {
char mystr[10];
- ast_safe_sleep(mychannel, 200);
+ ast_safe_sleep(mychannel,200);
/* set for all to hear */
ci.chan = 0;
ci.confno = myrpt->txconf;
ci.confmode = ZT_CONF_CONFANN;
/* 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)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
rpt_mutex_lock(&myrpt->lock);
+ myrpt->active_telem = NULL;
remque((struct qelem *)mytele);
rpt_mutex_unlock(&myrpt->lock);
- ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ ast_free(nodename);
+ if(id_malloc)
+ ast_free(ident);
ast_free(mytele);
ast_hangup(mychannel);
pthread_exit(NULL);
}
- snprintf(mystr, sizeof(mystr), "%04x", myrpt->lastunit);
+ sprintf(mystr,"%04x",myrpt->lastunit);
myrpt->lastunit = 0;
- ast_say_character_str(mychannel, mystr, NULL, mychannel->language);
+ ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
break;
}
#endif
imdone = 1;
break;
- case REMDISC:
+ case LINKUNKEY:
+ if(myrpt->patchnoct && myrpt->callmode){ /* If no CT during patch configured, then don't send one */
+ imdone = 1;
+ break;
+ }
+
+ /*
+ * Reset the Unkey to CT timer
+ */
+
+ x = get_wait_interval(myrpt, DLY_LINKUNKEY);
+ mytele->mylink.linkunkeytocttimer = x; /* Must be protected as it is changed below */
+
+ /*
+ * If there's one already queued, don't do another
+ */
+
+ tlist = myrpt->tele.next;
+ unkeys_queued = 0;
+ if (tlist != &myrpt->tele)
+ {
+ rpt_mutex_lock(&myrpt->lock);
+ while(tlist != &myrpt->tele){
+ if (tlist->mode == LINKUNKEY) unkeys_queued++;
+ tlist = tlist->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ }
+ if( unkeys_queued > 1){
+ imdone = 1;
+ break;
+ }
+
+ /* Wait for the telemetry timer to expire */
+ /* Periodically check the timer since it can be re-initialized above */
+ while(mytele->mylink.linkunkeytocttimer)
+ {
+ int ctint;
+ if(mytele->mylink.linkunkeytocttimer > 100)
+ ctint = 100;
+ else
+ ctint = mytele->mylink.linkunkeytocttimer;
+ ast_safe_sleep(mychannel, ctint);
+ rpt_mutex_lock(&myrpt->lock);
+ if(mytele->mylink.linkunkeytocttimer < ctint)
+ mytele->mylink.linkunkeytocttimer = 0;
+ else
+ mytele->mylink.linkunkeytocttimer -= ctint;
+ rpt_mutex_unlock(&myrpt->lock);
+ }
+
+ if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){ /* Unlinked Courtesy Tone */
+ ct_copy = ast_strdup(ct);
+ if(ct_copy){
+ res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
+ ast_free(ct_copy);
+ }
+ else
+ res = -1;
+ if(res)
+ ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
+ }
+ imdone = 1;
+ break;
+ case REMDISC:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
- res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
+ l = myrpt->links.next;
+ haslink = 0;
+ /* dont report if a link for this one still on system */
+ if (l != &myrpt->links)
+ {
+ rpt_mutex_lock(&myrpt->lock);
+ while(l != &myrpt->links)
+ {
+ if (l->name[0] == '0')
+ {
+ l = l->next;
+ continue;
+ }
+ if (!strcmp(l->name,mytele->mylink.name))
+ {
+ haslink = 1;
+ break;
+ }
+ l = l->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ }
+ if (haslink)
+ {
+ imdone = 1;
+ break;
+ }
+ res = saynode(myrpt,mychannel,mytele->mylink.name);
if (!res)
- res = ast_waitstream(mychannel, "");
- else
- ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
- ast_stopstream(mychannel);
- ast_say_character_str(mychannel, mytele->mylink.name, NULL, mychannel->language);
- res = ast_streamfile(mychannel, ((mytele->mylink.connected) ?
+ res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
"rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
break;
- case REMALREADY:
+ case REMALREADY:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
break;
- case REMNOTFOUND:
+ case REMNOTFOUND:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
break;
- case REMGO:
+ case REMGO:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
break;
- case CONNECTED:
+ case CONNECTED:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
- res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
+ res = saynode(myrpt,mychannel,mytele->mylink.name);
+ if (!res)
+ res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
- ast_say_character_str(mychannel, mytele->mylink.name, NULL, mychannel->language);
- res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
- break;
- case CONNFAIL:
- res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
+ res = ast_streamfile(mychannel, "digits/2", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
- ast_say_character_str(mychannel, mytele->mylink.name, NULL, mychannel->language);
- res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
+ res = saynode(myrpt,mychannel,myrpt->name);
+ imdone = 1;
+ break;
+ case CONNFAIL:
+ res = saynode(myrpt,mychannel,mytele->mylink.name);
+ if (!res)
+ res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
+ break;
+ case MEMNOTFOUND:
+ /* wait a little bit */
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
+ break;
+ case PLAYBACK:
+ /* wait a little bit */
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ res = ast_streamfile(mychannel, mytele->param, mychannel->language);
+ break;
+ case TOPKEY:
+ /* wait a little bit */
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ for(i = 0; i < TOPKEYN; i++)
+ {
+ if (!myrpt->topkey[i].node[0]) continue;
+ if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
+ res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
+ if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
+ "rpt/keyedfor" : "rpt/unkeyedfor");
+ if (!res) res = saynum(mychannel,
+ myrpt->topkey[i].timesince);
+ if (!res) res = sayfile(mychannel,"rpt/seconds");
+ if (!myrpt->topkeylong) break;
+ }
+ imdone = 1;
+ break;
+ case SETREMOTE:
+ ast_mutex_lock(&myrpt->remlock);
+ res = 0;
+ if(!strcmp(myrpt->remoterig, remote_rig_ft897))
+ {
+ res = set_ft897(myrpt);
+ }
+ else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
+ {
+ res = set_tm271(myrpt);
+ }
+ else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
+ {
+ res = set_ic706(myrpt);
+ }
+ else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
+ {
+ if (ioperm(myrpt->p.iobase,1,1) == -1)
+ {
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
+ res = -1;
+ }
+ else res = setrbi(myrpt);
+ }
+ else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
+ {
+ if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
+ res = setkenwood(myrpt);
+ if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
+ if (ast_safe_sleep(mychannel,200) == -1)
+ {
+ ast_mutex_unlock(&myrpt->remlock);
+ res = -1;
+ break;
+ }
+ if (myrpt->iofd < 0)
+ {
+ i = ZT_FLUSH_EVENT;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_FLUSH,&i) == -1)
+ {
+ ast_mutex_unlock(&myrpt->remlock);
+ ast_log(LOG_ERROR,"Cant flush events");
+ res = -1;
+ break;
+ }
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_GET_PARAMS,&par) == -1)
+ {
+ ast_mutex_unlock(&myrpt->remlock);
+ ast_log(LOG_ERROR,"Cant get params");
+ res = -1;
+ break;
+ }
+ myrpt->remoterx =
+ (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
+ }
+ }
+
+ ast_mutex_unlock(&myrpt->remlock);
+ if (!res)
+ {
+ imdone = 1;
+ break;
+ }
+ /* fall thru to invalid freq */
+ case INVFREQ:
+ /* wait a little bit */
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
+ break;
+ case REMMODE:
+ cp = 0;
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ switch(myrpt->remmode)
+ {
+ case REM_MODE_FM:
+ saycharstr(mychannel,"FM");
+ break;
+ case REM_MODE_USB:
+ saycharstr(mychannel,"USB");
+ break;
+ case REM_MODE_LSB:
+ saycharstr(mychannel,"LSB");
+ break;
+ case REM_MODE_AM:
+ saycharstr(mychannel,"AM");
+ break;
+ }
+ wait_interval(myrpt, DLY_COMP, mychannel);
+ if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
+ break;
+ case LOGINREQ:
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ sayfile(mychannel,"rpt/login");
+ saycharstr(mychannel,myrpt->name);
+ break;
+ case REMLOGIN:
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ saycharstr(mychannel,myrpt->loginuser);
+ saynode(myrpt,mychannel,myrpt->name);
+ wait_interval(myrpt, DLY_COMP, mychannel);
+ if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
+ break;
+ case REMXXX:
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ res = 0;
+ switch(mytele->submode)
+ {
+ case 100: /* RX PL Off */
+ sayfile(mychannel, "rpt/rxpl");
+ sayfile(mychannel, "rpt/off");
+ break;
+ case 101: /* RX PL On */
+ sayfile(mychannel, "rpt/rxpl");
+ sayfile(mychannel, "rpt/on");
+ break;
+ case 102: /* TX PL Off */
+ sayfile(mychannel, "rpt/txpl");
+ sayfile(mychannel, "rpt/off");
+ break;
+ case 103: /* TX PL On */
+ sayfile(mychannel, "rpt/txpl");
+ sayfile(mychannel, "rpt/on");
+ break;
+ case 104: /* Low Power */
+ sayfile(mychannel, "rpt/lopwr");
+ break;
+ case 105: /* Medium Power */
+ sayfile(mychannel, "rpt/medpwr");
+ break;
+ case 106: /* Hi Power */
+ sayfile(mychannel, "rpt/hipwr");
+ break;
+ case 113: /* Scan down slow */
+ sayfile(mychannel,"rpt/down");
+ sayfile(mychannel, "rpt/slow");
+ break;
+ case 114: /* Scan down quick */
+ sayfile(mychannel,"rpt/down");
+ sayfile(mychannel, "rpt/quick");
+ break;
+ case 115: /* Scan down fast */
+ sayfile(mychannel,"rpt/down");
+ sayfile(mychannel, "rpt/fast");
+ break;
+ case 116: /* Scan up slow */
+ sayfile(mychannel,"rpt/up");
+ sayfile(mychannel, "rpt/slow");
+ break;
+ case 117: /* Scan up quick */
+ sayfile(mychannel,"rpt/up");
+ sayfile(mychannel, "rpt/quick");
+ break;
+ case 118: /* Scan up fast */
+ sayfile(mychannel,"rpt/up");
+ sayfile(mychannel, "rpt/fast");
+ break;
+ default:
+ res = -1;
+ }
+ wait_interval(myrpt, DLY_COMP, mychannel);
+ if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
+ break;
+ case SCAN:
+ ast_mutex_lock(&myrpt->remlock);
+ if (myrpt->hfscanstop)
+ {
+ myrpt->hfscanstatus = 0;
+ myrpt->hfscanmode = 0;
+ myrpt->hfscanstop = 0;
+ mytele->mode = SCANSTAT;
+ ast_mutex_unlock(&myrpt->remlock);
+ if (ast_safe_sleep(mychannel,1000) == -1) break;
+ sayfile(mychannel, "rpt/stop");
+ imdone = 1;
+ break;
+ }
+ if (myrpt->hfscanstatus > -2) service_scan(myrpt);
+ i = myrpt->hfscanstatus;
+ myrpt->hfscanstatus = 0;
+ if (i) mytele->mode = SCANSTAT;
+ ast_mutex_unlock(&myrpt->remlock);
+ if (i < 0) sayfile(mychannel, "rpt/stop");
+ else if (i > 0) saynum(mychannel,i);
+ imdone = 1;
+ break;
+ case TUNE:
+ ast_mutex_lock(&myrpt->remlock);
+ if (!strcmp(myrpt->remoterig,remote_rig_ic706))
+ {
+ set_mode_ic706(myrpt, REM_MODE_AM);
+ if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
+ ast_safe_sleep(mychannel,500);
+ set_mode_ic706(myrpt, myrpt->remmode);
+ myrpt->tunerequest = 0;
+ ast_mutex_unlock(&myrpt->remlock);
+ imdone = 1;
+ break;
+ }
+ set_mode_ft897(myrpt, REM_MODE_AM);
+ simple_command_ft897(myrpt, 8);
+ if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
+ simple_command_ft897(myrpt, 0x88);
+ ast_safe_sleep(mychannel,500);
+ set_mode_ft897(myrpt, myrpt->remmode);
+ myrpt->tunerequest = 0;
+ ast_mutex_unlock(&myrpt->remlock);
+ imdone = 1;
+ break;
+ case REMSHORTSTATUS:
+ case REMLONGSTATUS:
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ res = saynode(myrpt,mychannel,myrpt->name);
+ if(!res)
+ res = sayfile(mychannel,"rpt/frequency");
+ if(!res)
+ res = split_freq(mhz, decimals, myrpt->freq);
+ if (!multimode_capable(myrpt)) decimals[3] = 0;
+ if(!res){
+ m = atoi(mhz);
+ if(m < 100)
+ res = saynum(mychannel, m);
+ else
+ res = saycharstr(mychannel, mhz);
+ }
+ if(!res)
+ res = sayfile(mychannel, "letters/dot");
+ if(!res)
+ res = saycharstr(mychannel, decimals);
+
+ if(res) break;
+ if(myrpt->remmode == REM_MODE_FM){ /* Mode FM? */
+ switch(myrpt->offset){
+
+ case REM_MINUS:
+ res = sayfile(mychannel,"rpt/minus");
+ break;
+
+ case REM_SIMPLEX:
+ res = sayfile(mychannel,"rpt/simplex");
+ break;
+
+ case REM_PLUS:
+ res = sayfile(mychannel,"rpt/plus");
+ break;
+
+ default:
+ break;
+ }
+ }
+ else{ /* Must be USB, LSB, or AM */
+ switch(myrpt->remmode){
+
+ case REM_MODE_USB:
+ res = saycharstr(mychannel, "USB");
+ break;
+
+ case REM_MODE_LSB:
+ res = saycharstr(mychannel, "LSB");
+ break;
+
+ case REM_MODE_AM:
+ res = saycharstr(mychannel, "AM");
+ break;
+
+
+ default:
+ break;
+ }
+ }
+
+ if (res == -1) break;
+
+ if(mytele->mode == REMSHORTSTATUS){ /* Short status? */
+ wait_interval(myrpt, DLY_COMP, mychannel);
+ if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
+ break;
+ }
+
+ if (strcmp(myrpt->remoterig,remote_rig_ic706))
+ {
+ switch(myrpt->powerlevel){
+
+ case REM_LOWPWR:
+ res = sayfile(mychannel,"rpt/lopwr") ;
+ break;
+ case REM_MEDPWR:
+ res = sayfile(mychannel,"rpt/medpwr");
+ break;
+ case REM_HIPWR:
+ res = sayfile(mychannel,"rpt/hipwr");
+ break;
+ }
+ }
+
+ rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
+ || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
+ if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
+ if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
+ if ((sayfile(mychannel,"rpt/frequency") == -1) ||
+ (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
+ if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
+ (sayfile(mychannel,"rpt/frequency") == -1) ||
+ (saycharstr(mychannel,myrpt->txpl) == -1))) break;
+ if(myrpt->remmode == REM_MODE_FM){ /* Mode FM? */
+ if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
+ (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
+ (sayfile(mychannel,"rpt/txpl") == -1) ||
+ (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
+ {
+ break;
+ }
+ }
+ wait_interval(myrpt, DLY_COMP, mychannel);
+ if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
break;
- case STATUS:
+ case STATUS:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
hastx = 0;
@@ -2226,73 +4799,132 @@ static void *rpt_tele_thread(void *this)
rpt_mutex_lock(&myrpt->lock);
/* make our own list of links */
l = myrpt->links.next;
- while (l != &myrpt->links) {
- if (l->name[0] == '0') {
+ while(l != &myrpt->links)
+ {
+ if (l->name[0] == '0')
+ {
l = l->next;
continue;
}
- m = ast_malloc(sizeof(*m));
- if (!m) {
+ l1 = ast_malloc(sizeof(struct rpt_link));
+ if (!l1)
+ {
ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
remque((struct qelem *)mytele);
+ myrpt->active_telem = NULL;
rpt_mutex_unlock(&myrpt->lock);
- ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
- ast_free(mytele);
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ ast_free(nodename);
+ if(id_malloc)
+ ast_free(ident);
+ ast_free(mytele);
ast_hangup(mychannel);
pthread_exit(NULL);
}
- memcpy(m, l, sizeof(struct rpt_link));
- m->next = m->prev = NULL;
- insque((struct qelem *)m, (struct qelem *)linkbase.next);
+ memcpy(l1,l,sizeof(struct rpt_link));
+ l1->next = l1->prev = NULL;
+ insque((struct qelem *)l1,(struct qelem *)linkbase.next);
l = l->next;
}
rpt_mutex_unlock(&myrpt->lock);
- res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
- if (!res)
- res = ast_waitstream(mychannel, "");
- else
- ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
- ast_stopstream(mychannel);
- ast_say_character_str(mychannel, myrpt->name, NULL, mychannel->language);
- if (!res)
- res = ast_waitstream(mychannel, "");
- else
- ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
- ast_stopstream(mychannel);
- if (myrpt->callmode) {
+ res = saynode(myrpt,mychannel,myrpt->name);
+ if (myrpt->callmode)
+ {
hastx = 1;
res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
- if (!res)
+ if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
}
l = linkbase.next;
- while (l != &linkbase) {
+ while(l != &linkbase)
+ {
+ char *s;
+
hastx = 1;
- res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
+ res = saynode(myrpt,mychannel,l->name);
+ s = "rpt/tranceive";
+ if (!l->mode) s = "rpt/monitor";
+ if (!l->thisconnected) s = "rpt/connecting";
+ res = ast_streamfile(mychannel, s, mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
- ast_say_character_str(mychannel, l->name, NULL, mychannel->language);
+ l = l->next;
+ }
+ if (!hastx)
+ {
+ res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
- res = ast_streamfile(mychannel, ((l->mode) ?
- "rpt/tranceive" : "rpt/monitor"), mychannel->language);
+ }
+ /* destroy our local link queue */
+ l = linkbase.next;
+ while(l != &linkbase)
+ {
+ l1 = l;
+ l = l->next;
+ remque((struct qelem *)l1);
+ ast_free(l1);
+ }
+ imdone = 1;
+ break;
+ case FULLSTATUS:
+ rpt_mutex_lock(&myrpt->lock);
+ /* get all the nodes */
+ __mklinklist(myrpt,NULL,lbuf);
+ rpt_mutex_unlock(&myrpt->lock);
+ /* parse em */
+ ns = finddelim(lbuf,strs,MAXLINKLIST);
+ /* sort em */
+ if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
+ /* wait a little bit */
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ hastx = 0;
+ res = saynode(myrpt,mychannel,myrpt->name);
+ if (myrpt->callmode)
+ {
+ hastx = 1;
+ res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
+ if (!res)
+ res = ast_waitstream(mychannel, "");
+ else
+ ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
+ ast_stopstream(mychannel);
+ }
+ /* go thru all the nodes in list */
+ for(i = 0; i < ns; i++)
+ {
+ char *s,mode = 'T';
+
+ /* if a mode spec at first, handle it */
+ if ((*strs[i] < '0') || (*strs[i] > '9'))
+ {
+ mode = *strs[i];
+ strs[i]++;
+ }
+
+ hastx = 1;
+ res = saynode(myrpt,mychannel,strs[i]);
+ s = "rpt/tranceive";
+ if (mode == 'R') s = "rpt/monitor";
+ if (mode == 'C') s = "rpt/connecting";
+ res = ast_streamfile(mychannel, s, mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
- l = l->next;
}
- if (!hastx) {
+ if (!hastx)
+ {
res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
@@ -2300,139 +4932,210 @@ static void *rpt_tele_thread(void *this)
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
}
- /* destroy our local link queue */
- l = linkbase.next;
- while (l != &linkbase) {
- m = l;
- l = l->next;
- remque((struct qelem *)m);
- ast_free(m);
- }
imdone = 1;
break;
- case LASTNODEKEY: /* Identify last node which keyed us up */
+ case LASTNODEKEY: /* Identify last node which keyed us up */
rpt_mutex_lock(&myrpt->lock);
- if (myrpt->lastnodewhichkeyedusup)
- p = ast_strdupa(myrpt->lastnodewhichkeyedusup); /* Make a local copy of the node name */
+ if(myrpt->lastnodewhichkeyedusup){
+ p = ast_strdup(myrpt->lastnodewhichkeyedusup); /* Make a local copy of the node name */
+ if(!p){
+ ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
+ imdone = 1;
+ break;
+ }
+ }
else
p = NULL;
rpt_mutex_unlock(&myrpt->lock);
- if (!p) {
+ if(!p){
imdone = 1; /* no node previously keyed us up, or the node which did has been disconnected */
break;
}
wait_interval(myrpt, DLY_TELEM, mychannel);
- res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
+ res = saynode(myrpt,mychannel,p);
+ ast_free(p);
+ imdone = 1;
+ break;
+
+ case UNAUTHTX: /* Say unauthorized transmit frequency */
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
- ast_say_character_str(mychannel, p, NULL, mychannel->language);
+ imdone = 1;
+ break;
+
+ case PARROT: /* Repeat stuff */
+
+ sprintf(mystr,PARROTFILE,myrpt->name,mytele->parrot);
+ if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
+ {
+ imdone = 1;
+ myrpt->parrotstate = 0;
+ break;
+ }
+ wait_interval(myrpt, DLY_PARROT, mychannel);
+ sprintf(mystr,PARROTFILE,myrpt->name,mytele->parrot);
+ res = ast_streamfile(mychannel, mystr, mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
- ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
+ ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
+ sprintf(mystr,PARROTFILE,myrpt->name,mytele->parrot);
+ strcat(mystr,".wav");
+ unlink(mystr);
imdone = 1;
- break;
+ myrpt->parrotstate = 0;
+ break;
+
+ case TIMEOUT:
+ res = saynode(myrpt,mychannel,myrpt->name);
+ if (!res)
+ res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
+ break;
+
+ case TIMEOUT_WARNING:
+ time(&t);
+ res = saynode(myrpt,mychannel,myrpt->name);
+ if (!res)
+ res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
+ if (!res)
+ res = ast_waitstream(mychannel, "");
+ else
+ ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
+ ast_stopstream(mychannel);
+ if(!res) /* Say number of seconds */
+ ast_say_number(mychannel, myrpt->p.remotetimeout -
+ (t - myrpt->last_activity_time),
+ "", mychannel->language, (char *) NULL);
+ if (!res)
+ res = ast_waitstream(mychannel, "");
+ ast_stopstream(mychannel);
+ res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
+ break;
- case TIMEOUT:
- res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
+ case ACT_TIMEOUT_WARNING:
+ time(&t);
+ res = saynode(myrpt,mychannel,myrpt->name);
+ if (!res)
+ res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
- ast_say_character_str(mychannel, myrpt->name, NULL, mychannel->language);
- res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
+ if(!res) /* Say number of seconds */
+ ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
+ (t - myrpt->last_activity_time),
+ "", mychannel->language, (char *) NULL);
+ if (!res)
+ res = ast_waitstream(mychannel, "");
+ ast_stopstream(mychannel);
+ res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
break;
- case STATS_TIME:
- wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
- tv = ast_tvnow();
- ast_localtime(&tv, &localtm, NULL);
+ case STATS_TIME:
+ case STATS_TIME_LOCAL:
+ wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
+ t = time(NULL);
+ rpt_localtime(&t, &localtm);
/* Say the phase of the day is before the time */
- if ((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
+ if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
p = "rpt/goodmorning";
- else if ((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
+ else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
p = "rpt/goodafternoon";
else
p = "rpt/goodevening";
- if (sayfile(mychannel, p) == -1) {
+ if (sayfile(mychannel,p) == -1)
+ {
imdone = 1;
break;
}
/* Say the time is ... */
- if (sayfile(mychannel, "rpt/thetimeis") == -1) {
+ if (sayfile(mychannel,"rpt/thetimeis") == -1)
+ {
imdone = 1;
break;
}
/* Say the time */
- res = ast_say_time(mychannel, tv.tv_sec, "", mychannel->language);
+ res = ast_say_time(mychannel, t, "", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
ast_stopstream(mychannel);
imdone = 1;
break;
- case STATS_VERSION:
- wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
+ case STATS_VERSION:
+ p = strstr(tdesc, "version");
+ if(!p)
+ break;
+ if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
+ break;
+ wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
/* Say "version" */
- if (sayfile(mychannel, "rpt/version") == -1) {
+ if (sayfile(mychannel,"rpt/version") == -1)
+ {
imdone = 1;
break;
}
- if (!res) /* Say "X" */
+ if(!res) /* Say "X" */
ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
if (!res)
res = ast_waitstream(mychannel, "");
ast_stopstream(mychannel);
- if (saycharstr(mychannel, ".") == -1) {
+ if (saycharstr(mychannel,".") == -1)
+ {
imdone = 1;
break;
}
- if (!res) /* Say "Y" */
+ if(!res) /* Say "Y" */
ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
- if (!res) {
+ if (!res){
res = ast_waitstream(mychannel, "");
ast_stopstream(mychannel);
- } else
+ }
+ else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
imdone = 1;
+ break;
+ case ARB_ALPHA:
+ wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
+ if(mytele->param)
+ saycharstr(mychannel, mytele->param);
+ imdone = 1;
break;
- case ARB_ALPHA:
- wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
- if (mytele->param)
- saycharstr(mychannel, mytele->param);
- imdone = 1;
- break;
- case REV_PATCH:
- wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
- if (mytele->param) {
+ case REV_PATCH:
+ wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
+ if(mytele->param) {
+
/* Parts of this section taken from app_parkandannounce */
char *tpl_working, *tpl_current;
char *tmp[100], *myparm;
- int looptemp=0, i = 0, dres = 0;
+ int looptemp=0,i=0, dres = 0;
+
- tpl_working = ast_strdupa(mytele->param);
- myparm = strsep(&tpl_working, ",");
- tpl_current = strsep(&tpl_working, ":");
+ tpl_working = ast_strdup(mytele->param);
+ myparm = strsep(&tpl_working,",");
+ tpl_current=strsep(&tpl_working, ":");
- while (tpl_current && looptemp < sizeof(tmp)) {
- tmp[looptemp] = tpl_current;
+ while(tpl_current && looptemp < sizeof(tmp)) {
+ tmp[looptemp]=tpl_current;
looptemp++;
- tpl_current = strsep(&tpl_working, ":");
+ tpl_current=strsep(&tpl_working,":");
}
- for (i = 0; i < looptemp; i++) {
- if (!strcmp(tmp[i], "PARKED")) {
+ for(i=0; i<looptemp; i++) {
+ if(!strcmp(tmp[i], "PARKED")) {
ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
- } else if (!strcmp(tmp[i], "NODE")) {
+ } else if(!strcmp(tmp[i], "NODE")) {
ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
} else {
dres = ast_streamfile(mychannel, tmp[i], mychannel->language);
- if (!dres) {
+ if(!dres) {
dres = ast_waitstream(mychannel, "");
} else {
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name);
@@ -2440,25 +5143,30 @@ static void *rpt_tele_thread(void *this)
}
}
}
+ ast_free(tpl_working);
}
- imdone = 1;
+ imdone = 1;
break;
- case TEST_TONE:
+ case TEST_TONE:
imdone = 1;
- myrpt->stopgen = 0;
- if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
+ if (myrpt->stopgen) break;
+ myrpt->stopgen = -1;
+ if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
+ {
+ myrpt->stopgen = 0;
break;
- while (mychannel->generatordata && (!myrpt->stopgen)) {
- if (ast_safe_sleep(mychannel, 1)) break;
- imdone = 1;
}
+ while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
+ if (ast_safe_sleep(mychannel,1)) break;
+ imdone = 1;
+ }
+ myrpt->stopgen = 0;
break;
- default:
- break;
+ default:
+ break;
}
-
- myrpt->stopgen = 0;
- if (!imdone) {
+ if (!imdone)
+ {
if (!res)
res = ast_waitstream(mychannel, "");
else {
@@ -2468,125 +5176,192 @@ static void *rpt_tele_thread(void *this)
}
ast_stopstream(mychannel);
rpt_mutex_lock(&myrpt->lock);
- if (mytele->mode == TAILMSG) {
- if (!res) {
+ if (mytele->mode == TAILMSG)
+ {
+ if (!res)
+ {
myrpt->tailmessagen++;
- if (myrpt->tailmessagen >= myrpt->p.tailmsg.argc)
- myrpt->tailmessagen = 0;
- } else {
+ if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
+ }
+ else
+ {
myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
}
}
remque((struct qelem *)mytele);
+ myrpt->active_telem = NULL;
rpt_mutex_unlock(&myrpt->lock);
+ ast_free(nodename);
+ if(id_malloc)
+ ast_free(ident);
ast_free(mytele);
ast_hangup(mychannel);
#ifdef APP_RPT_LOCK_DEBUG
- sleep(5);
- ast_mutex_lock(&locklock);
- t = get_lockthread(pthread_self());
- if (t)
- memset(t, 0, sizeof(struct lockthread));
- ast_mutex_unlock(&locklock);
+ {
+ struct lockthread *t;
+
+ sleep(5);
+ ast_mutex_lock(&locklock);
+ t = get_lockthread(pthread_self());
+ if (t) memset(t,0,sizeof(struct lockthread));
+ ast_mutex_unlock(&locklock);
+ }
#endif
pthread_exit(NULL);
}
-static void rpt_telemetry(struct rpt *myrpt, int mode, void *data)
+static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
{
- struct rpt_tele *tele;
- struct rpt_link *mylink = (struct rpt_link *) data;
- int res;
+struct rpt_tele *tele;
+struct rpt_link *mylink = NULL;
+int res;
+pthread_attr_t attr;
+char *v1, *v2;
- tele = ast_calloc(1, sizeof(*tele));
- if (!tele) {
+ if(debug > 6)
+ ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
+
+ switch(mode)
+ {
+ case UNKEY:
+ /* if any of the following are defined, go ahead and do it,
+ otherwise, dont bother */
+ v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
+ "unlinkedct");
+ v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
+ "remotect");
+ if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
+ telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
+ telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
+ (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
+ (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
+ break;
+ case LINKUNKEY:
+ if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
+ return;
+ break;
+ default:
+ break;
+ }
+ tele = ast_malloc(sizeof(struct rpt_tele));
+ if (!tele)
+ {
ast_log(LOG_WARNING, "Unable to allocate memory\n");
pthread_exit(NULL);
+ return;
}
+ /* zero it out */
+ memset((char *)tele,0,sizeof(struct rpt_tele));
tele->rpt = myrpt;
tele->mode = mode;
+ if (mode == PARROT) tele->parrot = (unsigned int) data;
+ else mylink = (struct rpt_link *) data;
rpt_mutex_lock(&myrpt->lock);
- if ((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED)) {
- if (mylink) {
- memcpy(&tele->mylink, mylink, sizeof(struct rpt_link));
+ if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
+ (mode == LINKUNKEY)){
+ memset(&tele->mylink,0,sizeof(struct rpt_link));
+ if (mylink){
+ memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
}
- } else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) {
- ast_copy_string(tele->param, (char *) data, sizeof(tele->param));
}
+ else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
+ strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
+ tele->param[TELEPARAMSIZE - 1] = 0;
+ }
+ if (mode == REMXXX) tele->submode = (int) data;
insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
rpt_mutex_unlock(&myrpt->lock);
- res = ast_pthread_create_detached(&tele->threadid, NULL, rpt_tele_thread, (void *) tele);
- if (res != 0) {
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
+ if(res < 0){
rpt_mutex_lock(&myrpt->lock);
remque((struct qlem *) tele); /* We don't like stuck transmitters, remove it from the queue */
rpt_mutex_unlock(&myrpt->lock);
- ast_log(LOG_WARNING, "Could not create telemetry thread: %s\n", strerror(res));
+ ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
}
return;
}
static void *rpt_call(void *this)
{
- ZT_CONFINFO ci; /* conference info */
- struct rpt *myrpt = (struct rpt *)this;
- int res;
- struct ast_frame wf;
- int stopped, congstarted, dialtimer, lastcidx, aborted;
- struct ast_channel *mychannel, *genchannel;
+ZT_CONFINFO ci; /* conference info */
+struct rpt *myrpt = (struct rpt *)this;
+int res;
+int stopped,congstarted,dialtimer,lastcidx,aborted;
+struct ast_channel *mychannel,*genchannel;
myrpt->mydtmf = 0;
/* allocate a pseudo-channel thru asterisk */
- mychannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
- if (!mychannel) {
- ast_log(LOG_ERROR, "rpt: unable to obtain pseudo channel\n");
+ mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!mychannel)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
pthread_exit(NULL);
}
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (mychannel->cdr)
+ ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
ci.chan = 0;
ci.confno = myrpt->conf; /* use the pseudo conference */
+#if 0
ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
| ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
+#endif
+ ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
/* first put the channel on the conference */
- if (ioctl(mychannel->fds[0], ZT_SETCONF, &ci) == -1) {
+ if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_hangup(mychannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
/* allocate a pseudo-channel thru asterisk */
- genchannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
- if (!genchannel) {
- ast_log(LOG_ERROR, "rpt: unable to obtain pseudo channel\n");
+ genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!genchannel)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
ast_hangup(mychannel);
pthread_exit(NULL);
}
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (genchannel->cdr)
+ ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
ci.chan = 0;
ci.confno = myrpt->conf;
ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
| ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
/* first put the channel on the conference */
- if (ioctl(genchannel->fds[0], ZT_SETCONF, &ci) == -1) {
+ if (ioctl(genchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
- if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0], myrpt->p.tonezone) == -1)) {
- ast_log(LOG_WARNING, "Unable to set tone zone %s\n", myrpt->p.tonezone);
+ if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
+ {
+ ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
- if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0], myrpt->p.tonezone) == -1)) {
- ast_log(LOG_WARNING, "Unable to set tone zone %s\n", myrpt->p.tonezone);
+ if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
+ {
+ ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
/* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */
- if ((!myrpt->patchquiet) && (tone_zone_play_tone(mychannel->fds[0], ZT_TONE_DIALTONE) < 0)) {
+ if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],ZT_TONE_DIALTONE) < 0))
+ {
ast_log(LOG_WARNING, "Cannot start dialtone\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
@@ -2597,15 +5372,19 @@ static void *rpt_call(void *this)
congstarted = 0;
dialtimer = 0;
lastcidx = 0;
+ myrpt->calldigittimer = 0;
aborted = 0;
- while ((myrpt->callmode == 1) || (myrpt->callmode == 4)) {
- if ((myrpt->patchdialtime) && (myrpt->callmode == 1) && (myrpt->cidx != lastcidx)) {
+ while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
+ {
+ if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
dialtimer = 0;
lastcidx = myrpt->cidx;
}
- if ((myrpt->patchdialtime) && (dialtimer >= myrpt->patchdialtime)) {
+ if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
+ if(debug)
+ ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
rpt_mutex_lock(&myrpt->lock);
aborted = 1;
myrpt->callmode = 0;
@@ -2613,20 +5392,36 @@ static void *rpt_call(void *this)
break;
}
- if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0)) {
+ if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
+ {
stopped = 1;
/* stop dial tone */
- tone_zone_play_tone(mychannel->fds[0], -1);
+ tone_zone_play_tone(genchannel->fds[0],-1);
+ }
+ if (myrpt->callmode == 1)
+ {
+ if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
+ {
+ myrpt->callmode = 2;
+ break;
+ }
+ /* bump timer if active */
+ if (myrpt->calldigittimer)
+ myrpt->calldigittimer += MSWAIT;
}
- if (myrpt->callmode == 4) {
- if (!congstarted) {
+ if (myrpt->callmode == 4)
+ {
+ if(!congstarted){
congstarted = 1;
/* start congestion tone */
- tone_zone_play_tone(mychannel->fds[0], ZT_TONE_CONGESTION);
+ tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
}
}
res = ast_safe_sleep(mychannel, MSWAIT);
- if (res < 0) {
+ if (res < 0)
+ {
+ if(debug)
+ ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
ast_hangup(mychannel);
ast_hangup(genchannel);
rpt_mutex_lock(&myrpt->lock);
@@ -2637,31 +5432,36 @@ static void *rpt_call(void *this)
dialtimer += MSWAIT;
}
/* stop any tone generation */
- tone_zone_play_tone(mychannel->fds[0], -1);
+ tone_zone_play_tone(genchannel->fds[0],-1);
/* end if done */
- if (!myrpt->callmode) {
+ if (!myrpt->callmode)
+ {
+ if(debug)
+ ast_log(LOG_NOTICE, "callmode==0\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
rpt_mutex_lock(&myrpt->lock);
myrpt->callmode = 0;
+ myrpt->macropatch=0;
+ channel_revert(myrpt);
rpt_mutex_unlock(&myrpt->lock);
- if ((!myrpt->patchquiet) && aborted)
+ if((!myrpt->patchquiet) && aborted)
rpt_telemetry(myrpt, TERM, NULL);
pthread_exit(NULL);
}
- if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid) {
+ if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
char *name, *loc, *instr;
instr = ast_strdup(myrpt->p.ourcallerid);
- if (instr) {
+ if(instr){
ast_callerid_parse(instr, &name, &loc);
- if (loc) {
- if (mychannel->cid.cid_num)
+ if(loc){
+ if(mychannel->cid.cid_num)
ast_free(mychannel->cid.cid_num);
mychannel->cid.cid_num = ast_strdup(loc);
}
- if (name) {
- if (mychannel->cid.cid_name)
+ if(name){
+ if(mychannel->cid.cid_name)
ast_free(mychannel->cid.cid_name);
mychannel->cid.cid_name = ast_strdup(name);
}
@@ -2669,14 +5469,15 @@ static void *rpt_call(void *this)
}
}
- ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten));
- ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context));
+ ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
+ ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
if (myrpt->p.acctcode)
- ast_string_field_set(mychannel, accountcode, myrpt->p.acctcode);
+ ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
mychannel->priority = 1;
ast_channel_undefer_dtmf(mychannel);
- if (ast_pbx_start(mychannel) < 0) {
+ if (ast_pbx_start(mychannel) < 0)
+ {
ast_log(LOG_WARNING, "Unable to start PBX!!\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
@@ -2694,40 +5495,68 @@ static void *rpt_call(void *this)
ci.confmode = (myrpt->p.duplex == 2) ? ZT_CONF_CONFANNMON :
(ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
/* first put the channel on the conference in announce mode */
- if (ioctl(myrpt->pchannel->fds[0], ZT_SETCONF, &ci) == -1) {
+ if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
- while (myrpt->callmode) {
- if ((!mychannel->pbx) && (myrpt->callmode != 4)) {
- if (myrpt->patchfarenddisconnect) { /* If patch is setup for far end disconnect */
+ /* get its channel number */
+ if (ioctl(mychannel->fds[0],ZT_CHANNO,&res) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
+ ast_hangup(mychannel);
+ myrpt->callmode = 0;
+ pthread_exit(NULL);
+ }
+ ci.chan = 0;
+ ci.confno = res;
+ ci.confmode = ZT_CONF_MONITOR;
+ /* put vox channel monitoring on the channel */
+ if (ioctl(myrpt->voxchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+ ast_hangup(mychannel);
+ myrpt->callmode = 0;
+ pthread_exit(NULL);
+ }
+ while(myrpt->callmode)
+ {
+ if ((!mychannel->pbx) && (myrpt->callmode != 4))
+ {
+ /* If patch is setup for far end disconnect */
+ if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
+ if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
+ myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
myrpt->callmode = 0;
- if (!myrpt->patchquiet) {
+ myrpt->macropatch=0;
+ if(!myrpt->patchquiet){
rpt_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt, TERM, NULL);
rpt_mutex_lock(&myrpt->lock);
}
- } else { /* Send congestion until patch is downed by command */
+ }
+ else{ /* Send congestion until patch is downed by command */
myrpt->callmode = 4;
rpt_mutex_unlock(&myrpt->lock);
/* start congestion tone */
- tone_zone_play_tone(genchannel->fds[0], ZT_TONE_CONGESTION);
+ tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
rpt_mutex_lock(&myrpt->lock);
}
}
- if (myrpt->mydtmf) {
- wf.frametype = AST_FRAME_DTMF;
+ if (myrpt->mydtmf)
+ {
+ struct ast_frame wf = {AST_FRAME_DTMF, } ;
wf.subclass = myrpt->mydtmf;
- wf.offset = 0;
- wf.mallocd = 0;
- wf.data = NULL;
- wf.datalen = 0;
- wf.samples = 0;
rpt_mutex_unlock(&myrpt->lock);
- ast_write(genchannel, &wf);
+ ast_queue_frame(mychannel,&wf);
+#ifdef NEW_ASTERISK
+ ast_senddigit(genchannel,myrpt->mydtmf,0);
+#else
+ ast_senddigit(genchannel,myrpt->mydtmf);
+#endif
rpt_mutex_lock(&myrpt->lock);
myrpt->mydtmf = 0;
}
@@ -2735,13 +5564,16 @@ static void *rpt_call(void *this)
usleep(MSWAIT * 1000);
rpt_mutex_lock(&myrpt->lock);
}
+ if(debug)
+ ast_log(LOG_NOTICE, "exit channel loop\n");
rpt_mutex_unlock(&myrpt->lock);
- tone_zone_play_tone(genchannel->fds[0], -1);
- if (mychannel->pbx)
- ast_softhangup(mychannel, AST_SOFTHANGUP_DEV);
+ tone_zone_play_tone(genchannel->fds[0],-1);
+ if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
ast_hangup(genchannel);
rpt_mutex_lock(&myrpt->lock);
myrpt->callmode = 0;
+ myrpt->macropatch=0;
+ channel_revert(myrpt);
rpt_mutex_unlock(&myrpt->lock);
/* set appropriate conference for the pseudo */
ci.chan = 0;
@@ -2749,393 +5581,566 @@ static void *rpt_call(void *this)
ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? ZT_CONF_CONFANNMON :
(ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
/* first put the channel on the conference in announce mode */
- if (ioctl(myrpt->pchannel->fds[0], ZT_SETCONF, &ci) == -1) {
+ if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
}
pthread_exit(NULL);
}
-static void send_link_dtmf(struct rpt *myrpt, char c)
+static void send_link_dtmf(struct rpt *myrpt,char c)
{
- char str[300];
- struct ast_frame wf;
- struct rpt_link *l;
+char str[300];
+struct ast_frame wf;
+struct rpt_link *l;
snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
wf.frametype = AST_FRAME_TEXT;
wf.subclass = 0;
wf.offset = 0;
- wf.mallocd = 1;
+ wf.mallocd = 0;
wf.datalen = strlen(str) + 1;
wf.samples = 0;
l = myrpt->links.next;
/* first, see if our dude is there */
- while (l != &myrpt->links) {
- if (l->name[0] == '0') {
+ while(l != &myrpt->links)
+ {
+ if (l->name[0] == '0')
+ {
l = l->next;
continue;
}
/* if we found it, write it and were done */
- if (!strcmp(l->name, myrpt->cmdnode)) {
- wf.data = ast_strdup(str);
- if (l->chan)
- ast_write(l->chan, &wf);
+ if (!strcmp(l->name,myrpt->cmdnode))
+ {
+ wf.data = str;
+ if (l->chan) ast_write(l->chan,&wf);
return;
}
l = l->next;
}
l = myrpt->links.next;
/* if not, give it to everyone */
- while (l != &myrpt->links) {
- wf.data = ast_strdup(str);
- if (l->chan)
- ast_write(l->chan, &wf);
+ while(l != &myrpt->links)
+ {
+ wf.data = str;
+ if (l->chan) ast_write(l->chan,&wf);
l = l->next;
}
return;
}
-/*
-* Internet linking function
-*/
+static void send_link_keyquery(struct rpt *myrpt)
+{
+char str[300];
+struct ast_frame wf;
+struct rpt_link *l;
-static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
+ rpt_mutex_lock(&myrpt->lock);
+ memset(myrpt->topkey,0,sizeof(myrpt->topkey));
+ myrpt->topkeystate = 1;
+ time(&myrpt->topkeytime);
+ rpt_mutex_unlock(&myrpt->lock);
+ snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
+ wf.frametype = AST_FRAME_TEXT;
+ wf.subclass = 0;
+ wf.offset = 0;
+ wf.mallocd = 0;
+ wf.datalen = strlen(str) + 1;
+ wf.samples = 0;
+ l = myrpt->links.next;
+ /* give it to everyone */
+ while(l != &myrpt->links)
+ {
+ wf.data = str;
+ if (l->chan) ast_write(l->chan,&wf);
+ l = l->next;
+ }
+ return;
+}
+
+/* send newkey request */
+
+static void send_newkey(struct ast_channel *chan)
+{
+
+ /* ast_safe_sleep(chan,10); */
+ ast_sendtext(chan,newkeystr);
+ return;
+}
+
+
+/*
+ * Connect a link
+ *
+ * Return values:
+ * -2: Attempt to connect to self
+ * -1: No such node
+ * 0: Success
+ * 1: No match yet
+ * 2: Already connected to this node
+ */
+
+static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
{
- const char *val;
- char *s, *tele;
- char deststr[300] = "", modechange = 0;
- char digitbuf[MAXNODESTR];
+ char *val, *s, *s1, *s2, *tele;
+ char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
+ char tmp[300], deststr[300] = "",modechange = 0;
+ char sx[320],*sy;
struct rpt_link *l;
int reconnects = 0;
+ int i,n;
ZT_CONFINFO ci; /* conference info */
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(s1);
- AST_APP_ARG(s2); /* XXX Never used. Scratch? XXX */
- );
-
- if (!param)
- return DC_ERROR;
- if (!myrpt->enable)
- return DC_ERROR;
+ val = node_lookup(myrpt,node);
+ if (!val){
+ if(strlen(node) >= myrpt->longestnode)
+ return -1; /* No such node */
+ return 1; /* No match yet */
+ }
- ast_copy_string(digitbuf, digits, sizeof(digitbuf));
- ast_debug(1, "@@@@ ilink param = %s, digitbuf = %s\n", S_OR(param, "(null)"), digitbuf);
+ if(!strcmp(myrpt->name,node)) /* Do not allow connections to self */
+ return -2;
+
+ if(debug > 3){
+ ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
+ ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
+ ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
+ }
- switch (myatoi(param)) {
- case 1: /* Link off */
- if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
- strcpy(digitbuf, myrpt->lastlinknode);
- val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
- if (!val) {
- if (strlen(digitbuf) >= myrpt->longestnode)
- return DC_ERROR;
+ strncpy(tmp,val,sizeof(tmp) - 1);
+ s = tmp;
+ s1 = strsep(&s,",");
+ if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
+ {
+ sy = strchr(s1,'/');
+ *sy = 0;
+ sprintf(sx,"%s:4569/%s",s1,sy + 1);
+ s1 = sx;
+ }
+ s2 = strsep(&s,",");
+ rpt_mutex_lock(&myrpt->lock);
+ l = myrpt->links.next;
+ /* try to find this one in queue */
+ while(l != &myrpt->links){
+ if (l->name[0] == '0')
+ {
+ l = l->next;
+ continue;
+ }
+ /* if found matching string */
+ if (!strcmp(l->name, node))
break;
+ l = l->next;
+ }
+ /* if found */
+ if (l != &myrpt->links){
+ /* if already in this mode, just ignore */
+ if ((l->mode) || (!l->chan)) {
+ rpt_mutex_unlock(&myrpt->lock);
+ return 2; /* Already linked */
}
- rpt_mutex_lock(&myrpt->lock);
- l = myrpt->links.next;
- /* try to find this one in queue */
- while (l != &myrpt->links) {
- if (l->name[0] == '0') {
- l = l->next;
- continue;
+ reconnects = l->reconnects;
+ rpt_mutex_unlock(&myrpt->lock);
+ if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
+ l->retries = l->max_retries + 1;
+ l->disced = 2;
+ modechange = 1;
+ } else
+ {
+ __mklinklist(myrpt,NULL,lstr);
+ rpt_mutex_unlock(&myrpt->lock);
+ n = finddelim(lstr,strs,MAXLINKLIST);
+ for(i = 0; i < n; i++)
+ {
+ if ((*strs[i] < '0') ||
+ (*strs[i] > '9')) strs[i]++;
+ if (!strcmp(strs[i],node))
+ {
+ return 2; /* Already linked */
}
- /* if found matching string */
- if (!strcmp(l->name, digitbuf))
- break;
- l = l->next;
}
- if (l != &myrpt->links) { /* if found */
- struct ast_frame wf;
- ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR);
- l->retries = MAX_RETRIES + 1;
- l->disced = 1;
- rpt_mutex_unlock(&myrpt->lock);
- wf.frametype = AST_FRAME_TEXT;
- wf.subclass = 0;
- wf.offset = 0;
- wf.mallocd = 1;
- wf.datalen = strlen(discstr) + 1;
- wf.samples = 0;
- wf.data = ast_strdup(discstr);
- if (l->chan) {
- ast_write(l->chan, &wf);
- if (ast_safe_sleep(l->chan, 250) == -1)
+ }
+ strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
+ /* establish call */
+ l = ast_malloc(sizeof(struct rpt_link));
+ if (!l)
+ {
+ ast_log(LOG_WARNING, "Unable to malloc\n");
+ return -1;
+ }
+ /* zero the silly thing */
+ memset((char *)l,0,sizeof(struct rpt_link));
+ l->mode = mode;
+ l->outbound = 1;
+ l->thisconnected = 0;
+ voxinit_link(l,1);
+ strncpy(l->name, node, MAXNODESTR - 1);
+ l->isremote = (s && ast_true(s));
+ if (modechange) l->connected = 1;
+ l->hasconnected = l->perma = perma;
+#ifdef ALLOW_LOCAL_CHANNELS
+ if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
+ strncpy(deststr, s1, sizeof(deststr));
+ else
+ snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
+#else
+ snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
+#endif
+ tele = strchr(deststr, '/');
+ if (!tele){
+ ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
+ ast_free(l);
+ return -1;
+ }
+ *tele++ = 0;
+ l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
+ if (l->chan){
+ ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
+ ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (l->chan->cdr)
+ ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+#ifndef NEW_ASTERISK
+ l->chan->whentohangup = 0;
+#endif
+ l->chan->appl = "Apprpt";
+ l->chan->data = "(Remote Rx)";
+ if (debug > 3)
+ ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
+ deststr, tele, l->chan->name);
+ if(l->chan->cid.cid_num)
+ ast_free(l->chan->cid.cid_num);
+ l->chan->cid.cid_num = ast_strdup(myrpt->name);
+ ast_call(l->chan,tele,999);
+ }
+ else {
+ if(debug > 3)
+ ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
+ deststr,tele,l->chan->name);
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+ sprintf(str,"LINKFAIL,%s",l->name);
+ donodelog(myrpt,str);
+ }
+ ast_free(l);
+ return -1;
+ }
+ /* allocate a pseudo-channel thru asterisk */
+ l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!l->pchan){
+ ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
+ ast_hangup(l->chan);
+ ast_free(l);
+ return -1;
+ }
+ ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
+ ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (l->pchan->cdr)
+ ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+ /* make a conference for the tx */
+ ci.chan = 0;
+ ci.confno = myrpt->conf;
+ ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
+ /* first put the channel on the conference in proper mode */
+ if (ioctl(l->pchan->fds[0], ZT_SETCONF, &ci) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+ ast_hangup(l->chan);
+ ast_hangup(l->pchan);
+ ast_free(l);
+ return -1;
+ }
+ rpt_mutex_lock(&myrpt->lock);
+ l->reconnects = reconnects;
+ /* insert at end of queue */
+ l->max_retries = MAX_RETRIES;
+ if (perma)
+ l->max_retries = MAX_RETRIES_PERM;
+ if (l->isremote) l->retries = l->max_retries + 1;
+ insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
+ __kickshort(myrpt);
+ rpt_mutex_unlock(&myrpt->lock);
+ if (!l->phonemode) send_newkey(l->chan);
+ return 0;
+}
+
+
+
+/*
+* Internet linking function
+*/
+
+static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
+{
+
+ char *val, *s, *s1, *s2;
+ char tmp[300];
+ char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
+ char mode,perma;
+ char sx[320],*sy;
+ struct rpt_link *l;
+ int i,r;
+
+ if(!param)
+ return DC_ERROR;
+
+
+ if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
+ return DC_ERROR;
+
+ strncpy(digitbuf,digits,MAXNODESTR - 1);
+
+ if(debug > 6)
+ printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
+
+ switch(myatoi(param)){
+ case 11: /* Perm Link off */
+ case 1: /* Link off */
+ if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
+ strcpy(digitbuf,myrpt->lastlinknode);
+ val = node_lookup(myrpt,digitbuf);
+ if (!val){
+ if(strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
- ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
+ break;
}
- rpt_telemetry(myrpt, COMPLETE, NULL);
- return DC_COMPLETE;
- }
- rpt_mutex_unlock(&myrpt->lock);
- return DC_COMPLETE;
- case 2: /* Link Monitor */
- if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
- strcpy(digitbuf, myrpt->lastlinknode);
- val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
- if (!val) {
- if (strlen(digitbuf) >= myrpt->longestnode)
- return DC_ERROR;
- break;
- }
- s = ast_strdupa(val);
- AST_STANDARD_APP_ARGS(args, s);
- rpt_mutex_lock(&myrpt->lock);
- l = myrpt->links.next;
- /* try to find this one in queue */
- while (l != &myrpt->links) {
- if (l->name[0] == '0') {
+ strncpy(tmp,val,sizeof(tmp) - 1);
+ s = tmp;
+ s1 = strsep(&s,",");
+ if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
+ {
+ sy = strchr(s1,'/');
+ *sy = 0;
+ sprintf(sx,"%s:4569/%s",s1,sy + 1);
+ s1 = sx;
+ }
+ s2 = strsep(&s,",");
+ rpt_mutex_lock(&myrpt->lock);
+ l = myrpt->links.next;
+ /* try to find this one in queue */
+ while(l != &myrpt->links){
+ if (l->name[0] == '0')
+ {
+ l = l->next;
+ continue;
+ }
+ /* if found matching string */
+ if (!strcmp(l->name, digitbuf))
+ break;
l = l->next;
- continue;
}
- /* if found matching string */
- if (!strcmp(l->name, digitbuf))
- break;
- l = l->next;
- }
- /* if found */
- if (l != &myrpt->links) {
- /* if already in this mode, just ignore */
- if ((!l->mode) || (!l->chan)) {
+ if (l != &myrpt->links){ /* if found */
+ struct ast_frame wf;
+
+ /* must use perm command on perm link */
+ if ((myatoi(param) < 10) &&
+ (l->max_retries > MAX_RETRIES))
+ {
+ rpt_mutex_unlock(&myrpt->lock);
+ return DC_COMPLETE;
+ }
+ strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
+ l->retries = l->max_retries + 1;
+ l->disced = 1;
rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, REMALREADY, NULL);
+ wf.frametype = AST_FRAME_TEXT;
+ wf.subclass = 0;
+ wf.offset = 0;
+ wf.mallocd = 0;
+ wf.datalen = strlen(discstr) + 1;
+ wf.samples = 0;
+ wf.data = discstr;
+ if (l->chan)
+ {
+ ast_write(l->chan,&wf);
+ if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
+ ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
+ }
+ rpt_telemetry(myrpt, COMPLETE, NULL);
return DC_COMPLETE;
}
- reconnects = l->reconnects;
- rpt_mutex_unlock(&myrpt->lock);
- if (l->chan)
- ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
- l->retries = MAX_RETRIES + 1;
- l->disced = 2;
- modechange = 1;
- } else
- rpt_mutex_unlock(&myrpt->lock);
- ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR);
- /* establish call in monitor mode */
- l = ast_calloc(1, sizeof(*l));
- if (!l) {
- ast_log(LOG_WARNING, "Unable to malloc\n");
- return DC_ERROR;
- }
- snprintf(deststr, sizeof(deststr), "IAX2/%s", args.s1);
- tele = strchr(deststr, '/');
- if (!tele) {
- ast_log(LOG_ERROR, "link2:Dial number (%s) must be in format tech/number\n", deststr);
- return DC_ERROR;
- }
- *tele++ = 0;
- l->isremote = (s && ast_true(s));
- ast_copy_string(l->name, digitbuf, MAXNODESTR);
- l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele, NULL);
- if (modechange)
- l->connected = 1;
- if (l->chan) {
- ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
- ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
- ast_channel_setwhentohangup_tv(l->chan, cancel_atimeout);
- l->chan->appl = "Apprpt";
- l->chan->data = "(Remote Rx)";
- ast_verb(3, "rpt (remote) initiating call to %s/%s on %s\n",
- deststr, tele, l->chan->name);
- if (l->chan->cid.cid_num)
- ast_free(l->chan->cid.cid_num);
- l->chan->cid.cid_num = ast_strdup(myrpt->name);
- ast_call(l->chan, tele, 0);
- } else {
- rpt_telemetry(myrpt, CONNFAIL, l);
- ast_free(l);
- ast_verb(3, "Unable to place call to %s/%s on %s\n",
- deststr, tele, l->chan->name);
- return DC_ERROR;
- }
- /* allocate a pseudo-channel thru asterisk */
- l->pchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
- if (!l->pchan) {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
- ast_hangup(l->chan);
- ast_free(l);
- return DC_ERROR;
- }
- ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
- ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
- /* make a conference for the pseudo-one */
- ci.chan = 0;
- ci.confno = myrpt->conf;
- ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
- /* first put the channel on the conference in proper mode */
- if (ioctl(l->pchan->fds[0], ZT_SETCONF, &ci) == -1) {
- ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
- ast_hangup(l->chan);
- ast_hangup(l->pchan);
- ast_free(l);
- return DC_ERROR;
- }
- rpt_mutex_lock(&myrpt->lock);
- l->reconnects = reconnects;
- /* insert at end of queue */
- insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, COMPLETE, NULL);
- return DC_COMPLETE;
- case 3: /* Link transceive */
- if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
- strcpy(digitbuf, myrpt->lastlinknode);
- val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
- if (!val) {
- if (strlen(digitbuf) >= myrpt->longestnode)
- return DC_ERROR;
- break;
- }
- s = ast_strdupa(val);
- AST_STANDARD_APP_ARGS(args, s);
- rpt_mutex_lock(&myrpt->lock);
- l = myrpt->links.next;
- /* try to find this one in queue */
- while (l != &myrpt->links) {
- if (l->name[0] == '0') {
- l = l->next;
- continue;
+ rpt_mutex_unlock(&myrpt->lock);
+ return DC_COMPLETE;
+ case 2: /* Link Monitor */
+ case 3: /* Link transceive */
+ case 12: /* Link Monitor permanent */
+ case 13: /* Link transceive permanent */
+ if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
+ strcpy(digitbuf,myrpt->lastlinknode);
+ /* Attempt connection */
+ perma = (atoi(param) > 10) ? 1 : 0;
+ mode = (atoi(param) & 1) ? 1 : 0;
+ r = connect_link(myrpt, digitbuf, mode, perma);
+ switch(r){
+ case -2: /* Attempt to connect to self */
+ return DC_COMPLETE; /* Silent error */
+
+ case 0:
+ rpt_telemetry(myrpt, COMPLETE, NULL);
+ return DC_COMPLETE;
+
+ case 1:
+ break;
+
+ case 2:
+ rpt_telemetry(myrpt, REMALREADY, NULL);
+ return DC_COMPLETE;
+
+ default:
+ rpt_telemetry(myrpt, CONNFAIL, NULL);
+ return DC_COMPLETE;
}
- /* if found matching string */
- if (!strcmp(l->name, digitbuf))
- break;
- l = l->next;
- }
- /* if found */
- if (l != &myrpt->links) {
- /* if already in this mode, just ignore */
- if ((l->mode) || (!l->chan)) {
- rpt_mutex_unlock(&myrpt->lock);
+ break;
+
+ case 4: /* Enter Command Mode */
+
+ /* if doesnt allow link cmd, or no links active, return */
+ if (((command_source != SOURCE_RPT) &&
+ (command_source != SOURCE_PHONE) &&
+ (command_source != SOURCE_ALT) &&
+ (command_source != SOURCE_DPHONE)) ||
+ (myrpt->links.next == &myrpt->links))
+ return DC_COMPLETE;
+
+ /* if already in cmd mode, or selected self, fughetabahtit */
+ if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
+
rpt_telemetry(myrpt, REMALREADY, NULL);
return DC_COMPLETE;
}
- reconnects = l->reconnects;
- rpt_mutex_unlock(&myrpt->lock);
- if (l->chan)
- ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
- l->retries = MAX_RETRIES + 1;
- l->disced = 2;
- modechange = 1;
- } else
+ if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
+ strcpy(digitbuf,myrpt->lastlinknode);
+ /* node must at least exist in list */
+ val = node_lookup(myrpt,digitbuf);
+ if (!val){
+ if(strlen(digitbuf) >= myrpt->longestnode)
+ return DC_ERROR;
+ break;
+
+ }
+ rpt_mutex_lock(&myrpt->lock);
+ strcpy(myrpt->lastlinknode,digitbuf);
+ strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
rpt_mutex_unlock(&myrpt->lock);
- ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR);
- /* establish call in tranceive mode */
- l = ast_calloc(1, sizeof(*l));
- if (!l) {
- ast_log(LOG_WARNING, "Unable to malloc\n");
- return DC_ERROR;
- }
- l->mode = 1;
- l->outbound = 1;
- ast_copy_string(l->name, digitbuf, MAXNODESTR);
- l->isremote = (s && ast_true(s));
- if (modechange)
- l->connected = 1;
- snprintf(deststr, sizeof(deststr), "IAX2/%s", args.s1);
- tele = strchr(deststr, '/');
- if (!tele) {
- ast_log(LOG_ERROR, "link3:Dial number (%s) must be in format tech/number\n", deststr);
- ast_free(l);
- return DC_ERROR;
- }
- *tele++ = 0;
- l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele, NULL);
- if (l->chan) {
- ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
- ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
- ast_channel_setwhentohangup_tv(l->chan, cancel_atimeout);
- l->chan->appl = "Apprpt";
- l->chan->data = "(Remote Rx)";
- ast_verb(3, "rpt (remote) initiating call to %s/%s on %s\n",
- deststr, tele, l->chan->name);
- if (l->chan->cid.cid_num)
- ast_free(l->chan->cid.cid_num);
- l->chan->cid.cid_num = ast_strdup(myrpt->name);
- ast_call(l->chan, tele, 999);
- } else {
- rpt_telemetry(myrpt, CONNFAIL, l);
- ast_free(l);
- ast_verb(3, "Unable to place call to %s/%s on %s\n",
- deststr, tele, l->chan->name);
- return DC_ERROR;
- }
- /* allocate a pseudo-channel thru asterisk */
- l->pchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
- if (!l->pchan) {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
- ast_hangup(l->chan);
- ast_free(l);
- return DC_ERROR;
- }
- ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
- ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
- /* make a conference for the tx */
- ci.chan = 0;
- ci.confno = myrpt->conf;
- ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
- /* first put the channel on the conference in proper mode */
- if (ioctl(l->pchan->fds[0], ZT_SETCONF, &ci) == -1) {
- ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
- ast_hangup(l->chan);
- ast_hangup(l->pchan);
- ast_free(l);
- return DC_ERROR;
- }
- rpt_mutex_lock(&myrpt->lock);
- l->reconnects = reconnects;
- /* insert at end of queue */
- insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, COMPLETE, NULL);
- return DC_COMPLETE;
- case 4: /* Enter Command Mode */
- /* if doesnt allow link cmd, or no links active, return */
- if (((command_source != SOURCE_RPT) &&
- (command_source != SOURCE_PHONE) &&
- (command_source != SOURCE_DPHONE)) ||
- (myrpt->links.next == &myrpt->links))
+ rpt_telemetry(myrpt, REMGO, NULL);
return DC_COMPLETE;
- /* if already in cmd mode, or selected self, fughetabahtit */
- if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))) {
- rpt_telemetry(myrpt, REMALREADY, NULL);
+
+ case 5: /* Status */
+ rpt_telemetry(myrpt, STATUS, NULL);
return DC_COMPLETE;
- }
- if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
- strcpy(digitbuf, myrpt->lastlinknode);
- /* node must at least exist in list */
- val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
- if (!val) {
- if (strlen(digitbuf) >= myrpt->longestnode)
- return DC_ERROR;
+
+ case 15: /* Full Status */
+ rpt_telemetry(myrpt, FULLSTATUS, NULL);
+ return DC_COMPLETE;
+
+
+ case 6: /* All Links Off, including permalinks */
+ rpt_mutex_lock(&myrpt->lock);
+ myrpt->savednodes[0] = 0;
+ l = myrpt->links.next;
+ /* loop through all links */
+ while(l != &myrpt->links){
+ struct ast_frame wf;
+ if (l->name[0] == '0') /* Skip any IAXRPT monitoring */
+ {
+ l = l->next;
+ continue;
+ }
+ /* Make a string of disconnected nodes for possible restoration */
+ sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
+ if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
+ if(myrpt->savednodes[0])
+ strcat(myrpt->savednodes, ",");
+ strcat(myrpt->savednodes, tmp);
+ }
+ l->retries = l->max_retries + 1;
+ l->disced = 2; /* Silently disconnect */
+ rpt_mutex_unlock(&myrpt->lock);
+ /* ast_log(LOG_NOTICE,"dumping link %s\n",l->name); */
+
+ wf.frametype = AST_FRAME_TEXT;
+ wf.subclass = 0;
+ wf.offset = 0;
+ wf.mallocd = 0;
+ wf.datalen = strlen(discstr) + 1;
+ wf.samples = 0;
+ wf.data = discstr;
+ if (l->chan)
+ {
+ ast_write(l->chan,&wf);
+ ast_safe_sleep(l->chan,250); /* It's dead already, why check the return value? */
+ ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
+ }
+ rpt_mutex_lock(&myrpt->lock);
+ l = l->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ if(debug > 3)
+ ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
+ rpt_telemetry(myrpt, COMPLETE, NULL);
+ return DC_COMPLETE;
+
+ case 7: /* Identify last node which keyed us up */
+ rpt_telemetry(myrpt, LASTNODEKEY, NULL);
break;
- }
- rpt_mutex_lock(&myrpt->lock);
- strcpy(myrpt->lastlinknode, digitbuf);
- ast_copy_string(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode));
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, REMGO, NULL);
- return DC_COMPLETE;
- case 5: /* Status */
- rpt_telemetry(myrpt, STATUS, NULL);
- return DC_COMPLETE;
- case 6: /* All Links Off */
- l = myrpt->links.next;
- while (l != &myrpt->links) { /* This code is broke and needs to be changed to work with the reconnect kludge */
- if (l->chan)
- ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); /* Hang 'em up */
- l = l->next;
- }
- rpt_telemetry(myrpt, COMPLETE, NULL);
- break;
- case 7: /* Identify last node which keyed us up */
- rpt_telemetry(myrpt, LASTNODEKEY, NULL);
- break;
- default:
- return DC_ERROR;
- }
+
+#ifdef _MDC_DECODE_H_
+ case 8:
+ myrpt->lastunit = 0xd00d;
+ mdc1200_notify(myrpt,NULL,myrpt->lastunit);
+ mdc1200_send(myrpt,myrpt->lastunit);
+ break;
+#endif
+
+ case 16: /* Restore links disconnected with "disconnect all links" command */
+ strcpy(tmp, myrpt->savednodes); /* Make a copy */
+ finddelim(tmp, strs, MAXLINKLIST); /* convert into substrings */
+ for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
+ s1 = strs[i];
+ mode = (s1[0] == 'X') ? 1 : 0;
+ perma = (s1[1] == 'P') ? 1 : 0;
+ connect_link(myrpt, s1 + 2, mode, perma); /* Try to reconnect */
+ }
+ rpt_telemetry(myrpt, COMPLETE, NULL);
+ break;
+
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ if (((myrpt->p.propagate_dtmf) &&
+ (command_source == SOURCE_LNK)) ||
+ ((myrpt->p.propagate_phonedtmf) &&
+ ((command_source == SOURCE_PHONE) ||
+ (command_source == SOURCE_ALT) ||
+ (command_source == SOURCE_DPHONE))))
+ do_dtmf_local(myrpt,
+ remdtmfstr[myatoi(param) - 200]);
+ default:
+ return DC_ERROR;
+
+ }
+
return DC_INDETERMINATE;
-}
+}
/*
* Autopatch up
@@ -3143,11 +6148,11 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
{
- int i, index;
+ pthread_attr_t attr;
+ int i, index, paramlength;
+ char *lparam;
char *value = NULL;
- AST_DECLARE_APP_ARGS(params,
- AST_APP_ARG(list)[20];
- );
+ char *paramlist[20];
static char *keywords[] = {
"context",
@@ -3158,47 +6163,59 @@ static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf,
NULL
};
- if (!myrpt->enable)
+ if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
return DC_ERROR;
+
+ if(debug)
+ printf("@@@@ Autopatch up\n");
- ast_debug(1, "@@@@ Autopatch up\n");
-
- if (!myrpt->callmode) {
+ if(!myrpt->callmode){
/* Set defaults */
myrpt->patchnoct = 0;
myrpt->patchdialtime = 0;
myrpt->patchfarenddisconnect = 0;
myrpt->patchquiet = 0;
- ast_copy_string(myrpt->patchcontext, myrpt->p.ourcontext, sizeof(myrpt->patchcontext));
+ strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
- if (param) {
+ if(param){
/* Process parameter list */
- char *tmp = ast_strdupa(param);
- AST_STANDARD_APP_ARGS(params, tmp);
- for (i = 0; i < params.argc; i++) {
- index = matchkeyword(params.list[i], &value, keywords);
- if (value)
+ lparam = ast_strdup(param);
+ if(!lparam){
+ ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
+ return DC_ERROR;
+ }
+ paramlength = finddelim(lparam, paramlist, 20);
+ for(i = 0; i < paramlength; i++){
+ index = matchkeyword(paramlist[i], &value, keywords);
+ if(value)
value = skipchars(value, "= ");
- switch (index) {
- case 1: /* context */
- ast_copy_string(myrpt->patchcontext, value, sizeof(myrpt->patchcontext)) ;
- break;
- case 2: /* dialtime */
- myrpt->patchdialtime = atoi(value);
- break;
- case 3: /* farenddisconnect */
- myrpt->patchfarenddisconnect = atoi(value);
- break;
- case 4: /* noct */
- myrpt->patchnoct = atoi(value);
- break;
- case 5: /* quiet */
- myrpt->patchquiet = atoi(value);
- break;
- default:
- break;
+ switch(index){
+
+ case 1: /* context */
+ strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
+ break;
+
+ case 2: /* dialtime */
+ myrpt->patchdialtime = atoi(value);
+ break;
+
+ case 3: /* farenddisconnect */
+ myrpt->patchfarenddisconnect = atoi(value);
+ break;
+
+ case 4: /* noct */
+ myrpt->patchnoct = atoi(value);
+ break;
+
+ case 5: /* quiet */
+ myrpt->patchquiet = atoi(value);
+ break;
+
+ default:
+ break;
}
}
+ ast_free(lparam);
}
}
@@ -3206,10 +6223,10 @@ static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf,
/* if on call, force * into current audio stream */
- if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) {
- myrpt->mydtmf = myrpt->p.funcchar;
+ if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
+ myrpt->mydtmf = myrpt->p.endchar;
}
- if (myrpt->callmode) {
+ if (myrpt->callmode){
rpt_mutex_unlock(&myrpt->lock);
return DC_COMPLETE;
}
@@ -3217,7 +6234,9 @@ static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf,
myrpt->cidx = 0;
myrpt->exten[myrpt->cidx] = 0;
rpt_mutex_unlock(&myrpt->lock);
- ast_pthread_create_detached(&myrpt->rpt_call_thread, NULL, rpt_call, (void *) myrpt);
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
return DC_COMPLETE;
}
@@ -3227,19 +6246,23 @@ static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf,
static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
{
- if (!myrpt->enable)
+ if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
return DC_ERROR;
- ast_debug(1, "@@@@ Autopatch down\n");
+ if(debug)
+ printf("@@@@ Autopatch down\n");
rpt_mutex_lock(&myrpt->lock);
- if (!myrpt->callmode) {
+ myrpt->macropatch=0;
+
+ if (!myrpt->callmode){
rpt_mutex_unlock(&myrpt->lock);
return DC_COMPLETE;
}
myrpt->callmode = 0;
+ channel_revert(myrpt);
rpt_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt, TERM, NULL);
return DC_COMPLETE;
@@ -3255,121 +6278,94 @@ static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int c
if (!param)
return DC_ERROR;
- if (!myrpt->enable)
+ if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
return DC_ERROR;
- ast_debug(1, "@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
+ if(debug)
+ printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
- switch (myatoi(param)) {
- case 1: /* System ID */
- rpt_telemetry(myrpt, ID1, NULL);
- return DC_COMPLETE;
- case 2: /* System Time */
- rpt_telemetry(myrpt, STATS_TIME, NULL);
- return DC_COMPLETE;
- case 3: /* app_rpt.c version */
- rpt_telemetry(myrpt, STATS_VERSION, NULL);
- default:
- return DC_ERROR;
+ switch(myatoi(param)){
+ case 1: /* System ID */
+ rpt_telemetry(myrpt, ID1, NULL);
+ return DC_COMPLETE;
+ case 2: /* System Time */
+ rpt_telemetry(myrpt, STATS_TIME, NULL);
+ return DC_COMPLETE;
+ case 3: /* app_rpt.c version */
+ rpt_telemetry(myrpt, STATS_VERSION, NULL);
+ return DC_COMPLETE;
+ case 11: /* System ID (local only)*/
+ rpt_telemetry(myrpt, ID , NULL);
+ return DC_COMPLETE;
+ case 12: /* System Time (local only)*/
+ rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
+ return DC_COMPLETE;
+ default:
+ return DC_ERROR;
}
-
- /* Never reached */
return DC_INDETERMINATE;
}
-
/*
* Macro-oni (without Salami)
*/
-
static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
{
-
- const char *val;
- int i;
- struct ast_channel *mychannel;
-
- if ((!myrpt->remote) && (!myrpt->enable))
+char *val;
+int i;
+ if (myrpt->remote)
return DC_ERROR;
- ast_debug(1, "@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
+ if(debug)
+ printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
- mychannel = myrpt->remchannel;
-
- if (ast_strlen_zero(digitbuf)) /* needs 1 digit */
+ if(strlen(digitbuf) < 1) /* needs 1 digit */
return DC_INDETERMINATE;
- for (i = 0; i < digitbuf[i]; i++) {
- if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
+ for(i = 0 ; i < digitbuf[i] ; i++) {
+ if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
return DC_ERROR;
}
- if (*digitbuf == '0')
- val = myrpt->p.startupmacro;
- else
- val = ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
+ if (*digitbuf == '0') val = myrpt->p.startupmacro;
+ else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
/* param was 1 for local buf */
- if (!val) {
+ if (!val){
+ if (strlen(digitbuf) < myrpt->macro_longest)
+ return DC_INDETERMINATE;
rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
return DC_COMPLETE;
}
rpt_mutex_lock(&myrpt->lock);
- if ((sizeof(myrpt->macrobuf) - strlen(myrpt->macrobuf)) < strlen(val)) {
+ if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
+ {
rpt_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt, MACRO_BUSY, NULL);
return DC_ERROR;
}
myrpt->macrotimer = MACROTIME;
- strncat(myrpt->macrobuf, val, sizeof(myrpt->macrobuf) - strlen(myrpt->macrobuf) - 1);
+ strncat(myrpt->macrobuf,val,MAXMACRO - 1);
rpt_mutex_unlock(&myrpt->lock);
return DC_COMPLETE;
}
/*
-* Gosub
+* Playback a recording
*/
-static int function_gosub(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
+static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
{
- const char *val;
- int i;
- struct ast_channel *mychannel;
-
- if ((!myrpt->remote) && (!myrpt->enable))
+ if (myrpt->remote)
return DC_ERROR;
- if (debug)
- ast_log(LOG_DEBUG, "@@@@ gosub param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
+ if(debug)
+ printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
- mychannel = myrpt->remchannel;
-
- if (ast_strlen_zero(digitbuf)) /* needs 1 digit */
- return DC_INDETERMINATE;
-
- for (i = 0; i < digitbuf[i]; i++) {
- if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
- return DC_ERROR;
- }
-
- if (*digitbuf == '0')
- val = myrpt->p.startupgosub;
- else
- val = ast_variable_retrieve(myrpt->cfg, myrpt->p.gosub, digitbuf);
- /* param was 1 for local buf */
- if (!val) {
- rpt_telemetry(myrpt, GOSUB_NOTFOUND, NULL);
- return DC_COMPLETE;
- }
- rpt_mutex_lock(&myrpt->lock);
- if ((sizeof(myrpt->gosubbuf) - strlen(myrpt->gosubbuf)) < strlen(val)) {
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, GOSUB_BUSY, NULL);
+ if (ast_fileexists(param,NULL,myrpt->rxchannel->language) <= 0)
return DC_ERROR;
- }
- myrpt->gosubtimer = GOSUBTIME;
- strncat(myrpt->gosubbuf, val, sizeof(myrpt->gosubbuf) - strlen(myrpt->gosubbuf) - 1);
- rpt_mutex_unlock(&myrpt->lock);
- return DC_COMPLETE;
+
+ rpt_telemetry(myrpt,PLAYBACK,param);
+ return DC_COMPLETE;
}
/*
@@ -3378,163 +6374,510 @@ static int function_gosub(struct rpt *myrpt, char *param, char *digitbuf, int co
static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
{
- if (!param)
+ char string[16];
+
+ int i, r;
+
+ if(!param)
return DC_ERROR;
- switch(myatoi(param)) {
- case 1: /* System reset */
- ast_cli_command(STDERR_FILENO, "restart now"); /* A little less drastic than what was previously here. */
- return DC_COMPLETE;
- case 2:
- myrpt->enable = 1;
- rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
- return DC_COMPLETE;
- case 3:
- myrpt->enable = 0;
- return DC_COMPLETE;
- case 4: /* test tone on */
- rpt_telemetry(myrpt, TEST_TONE, NULL);
- return DC_COMPLETE;
- case 5: /* Disgorge variables to log for debug purposes */
- myrpt->disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
- return DC_COMPLETE;
- case 6: /* Simulate COR being activated (phone only) */
- if (command_source != SOURCE_PHONE)
- return DC_INDETERMINATE;
- return DC_DOKEY;
+ switch(myatoi(param)){
+ case 1: /* System reset */
+ system("killall -9 asterisk");
+ return DC_COMPLETE;
+
+ case 2:
+ myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
+ return DC_COMPLETE;
+
+ case 3:
+ myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
+ return DC_COMPLETE;
+
+ case 4: /* test tone on */
+ if (myrpt->stopgen < 0)
+ {
+ myrpt->stopgen = 1;
+ }
+ else
+ {
+ myrpt->stopgen = 0;
+ rpt_telemetry(myrpt, TEST_TONE, NULL);
+ }
+ return DC_COMPLETE;
+
+ case 5: /* Disgorge variables to log for debug purposes */
+ myrpt->disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
+ return DC_COMPLETE;
+
+ case 6: /* Simulate COR being activated (phone only) */
+ if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
+ return DC_DOKEY;
+
+
+ case 7: /* Time out timer enable */
+ myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
+ return DC_COMPLETE;
+
+ case 8: /* Time out timer disable */
+ myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
+ return DC_COMPLETE;
+
+ case 9: /* Autopatch enable */
+ myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
+ return DC_COMPLETE;
+
+ case 10: /* Autopatch disable */
+ myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
+ return DC_COMPLETE;
+
+ case 11: /* Link Enable */
+ myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
+ return DC_COMPLETE;
+
+ case 12: /* Link Disable */
+ myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
+ return DC_COMPLETE;
+
+ case 13: /* Query System State */
+ string[0] = string[1] = 'S';
+ string[2] = myrpt->p.sysstate_cur + '0';
+ string[3] = '\0';
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
+ return DC_COMPLETE;
+
+ case 14: /* Change System State */
+ if(strlen(digitbuf) == 0)
+ break;
+ if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
+ return DC_ERROR;
+ myrpt->p.sysstate_cur = digitbuf[0] - '0';
+ string[0] = string[1] = 'S';
+ string[2] = myrpt->p.sysstate_cur + '0';
+ string[3] = '\0';
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
+ return DC_COMPLETE;
+
+ case 15: /* Scheduler Enable */
+ myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
+ return DC_COMPLETE;
+
+ case 16: /* Scheduler Disable */
+ myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
+ return DC_COMPLETE;
+
+ case 17: /* User functions Enable */
+ myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
+ return DC_COMPLETE;
+
+ case 18: /* User Functions Disable */
+ myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
+ return DC_COMPLETE;
+
+ case 19: /* Alternate Tail Enable */
+ myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
+ return DC_COMPLETE;
+
+ case 20: /* Alternate Tail Disable */
+ myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
+ rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
+ return DC_COMPLETE;
+
+ case 21: /* Parrot Mode Disable */
+ birdbath(myrpt);
+ if (myrpt->p.parrotmode < 2)
+ {
+ myrpt->p.parrotmode = 0;
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ return DC_COMPLETE;
+ }
+ break;
+
+ case 22: /* Parrot Mode Enable */
+ birdbath(myrpt);
+ if (myrpt->p.parrotmode < 2)
+ {
+ myrpt->p.parrotmode = 1;
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ return DC_COMPLETE;
+ }
+ break;
+ case 23: /* flush parrot in progress */
+ birdbath(myrpt);
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ return DC_COMPLETE;
+ case 24: /* flush all telemetry */
+ flush_telem(myrpt);
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ return DC_COMPLETE;
+ case 25: /* request keying info (brief) */
+ send_link_keyquery(myrpt);
+ myrpt->topkeylong = 0;
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ return DC_COMPLETE;
+ case 26: /* request keying info (full) */
+ send_link_keyquery(myrpt);
+ myrpt->topkeylong = 1;
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ return DC_COMPLETE;
+
+ case 30: /* recall memory location on programmable radio */
+
+ if(strlen(digitbuf) < 2) /* needs 2 digits */
+ break;
+
+ for(i = 0 ; i < 2 ; i++){
+ if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
+ return DC_ERROR;
+ }
+
+ r = retreive_memory(myrpt, digitbuf);
+ if (r < 0){
+ rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
+ return DC_COMPLETE;
+ }
+ if (r > 0){
+ return DC_ERROR;
+ }
+ if (setrem(myrpt) == -1) return DC_ERROR;
+ return DC_COMPLETE;
+
+ case 31:
+ /* set channel. note that it's going to change channel
+ then confirm on the new channel! */
+ if(strlen(digitbuf) < 2) /* needs 2 digits */
+ break;
+
+ for(i = 0 ; i < 2 ; i++){
+ if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
+ return DC_ERROR;
+ }
+ channel_steer(myrpt,digitbuf);
+ return DC_COMPLETE;
+
+ case 32: /* Touch Tone Pad Test */
+ i = strlen(digitbuf);
+ if(!i){
+ if(debug > 3)
+ ast_log(LOG_NOTICE,"Padtest entered");
+ myrpt->inpadtest = 1;
+ }
+ else{
+ if(debug > 3)
+ ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
+ if(digitbuf[i-1] != myrpt->p.endchar)
+ break;
+ rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
+ myrpt->inpadtest = 0;
+ if(debug > 3)
+ ast_log(LOG_NOTICE,"Padtest exited");
+ return DC_COMPLETE;
+ }
}
return DC_INDETERMINATE;
}
-
/*
* Collect digits one by one until something matches
*/
-
-static int collect_function_digits(struct rpt *myrpt, char *digits, int command_source, struct rpt_link *mylink)
+static int collect_function_digits(struct rpt *myrpt, char *digits,
+ int command_source, struct rpt_link *mylink)
{
- int i;
- char *stringp, *functiondigits;
+ int i,rv;
+ char *stringp,*action,*param,*functiondigits;
char function_table_name[30] = "";
+ char workstring[200];
+
struct ast_variable *vp;
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(action);
- AST_APP_ARG(param);
- );
- ast_debug(1, "@@@@ Digits collected: %s, source: %d\n", digits, command_source);
+ if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
+
+ //if(debug)
+ // printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
if (command_source == SOURCE_DPHONE) {
- if (!myrpt->p.dphone_functions)
- return DC_INDETERMINATE;
- ast_copy_string(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name));
- } else if (command_source == SOURCE_PHONE) {
- if (!myrpt->p.phone_functions)
- return DC_INDETERMINATE;
- ast_copy_string(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name));
- } else if (command_source == SOURCE_LNK)
- ast_copy_string(function_table_name, myrpt->p.link_functions, sizeof(function_table_name));
+ if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
+ strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
+ }
+ else if (command_source == SOURCE_ALT) {
+ if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
+ strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
+ }
+ else if (command_source == SOURCE_PHONE) {
+ if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
+ strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
+ }
+ else if (command_source == SOURCE_LNK)
+ strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
else
- ast_copy_string(function_table_name, myrpt->p.functions, sizeof(function_table_name));
-
- for (vp = ast_variable_browse(myrpt->cfg, function_table_name); vp; vp = vp->next) {
- if (!strncasecmp(vp->name, digits, strlen(vp->name)))
+ strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
+ /* find context for function table in rpt.conf file */
+ vp = ast_variable_browse(myrpt->cfg, function_table_name);
+ while(vp) {
+ if(!strncasecmp(vp->name, digits, strlen(vp->name)))
break;
+ vp = vp->next;
}
- if (!vp) {
+ /* if function context not found */
+ if(!vp) {
int n;
n = myrpt->longestfunc;
- if (command_source == SOURCE_LNK)
- n = myrpt->link_longestfunc;
- else if (command_source == SOURCE_PHONE)
- n = myrpt->phone_longestfunc;
- else if (command_source == SOURCE_DPHONE)
- n = myrpt->dphone_longestfunc;
-
- if (strlen(digits) >= n)
+ if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
+ else
+ if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
+ else
+ if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
+ else
+ if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
+
+ if(strlen(digits) >= n)
return DC_ERROR;
else
return DC_INDETERMINATE;
- }
-
+ }
/* Found a match, retrieve value part and parse */
- stringp = ast_strdupa(vp->value);
- AST_STANDARD_APP_ARGS(args, stringp);
-
- ast_debug(1, "@@@@ action: %s, param = %s\n", args.action, S_OR(args.param, "(null)"));
+ strncpy(workstring, vp->value, sizeof(workstring) - 1 );
+ stringp = workstring;
+ action = strsep(&stringp, ",");
+ param = stringp;
+ if(debug)
+ printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
/* Look up the action */
- for (i = 0; i < (sizeof(function_table) / sizeof(struct function_table_tag)); i++) {
- if (!strncasecmp(args.action, function_table[i].action, strlen(args.action)))
+ for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
+ if(!strncasecmp(action, function_table[i].action, strlen(action)))
break;
}
- ast_debug(1, "@@@@ table index i = %d\n", i);
- if (i == (sizeof(function_table) / sizeof(struct function_table_tag))) {
+ if(debug)
+ printf("@@@@ table index i = %d\n",i);
+ if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
/* Error, action not in table */
return DC_ERROR;
}
- if (function_table[i].function == NULL) {
+ if(function_table[i].function == NULL){
/* Error, function undefined */
- ast_debug(1, "@@@@ NULL for action: %s\n", args.action);
+ if(debug)
+ printf("@@@@ NULL for action: %s\n",action);
return DC_ERROR;
}
functiondigits = digits + strlen(vp->name);
- return (*function_table[i].function)(myrpt, args.param, functiondigits, command_source, mylink);
+ rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
+ if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
+ return(rv);
}
-static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink, char *str)
+static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
+ char *str)
{
- char cmd[300] = "", dest[300], src[300], c;
- int seq, res;
- struct rpt_link *l;
- struct ast_frame wf;
+char tmp[512],tmp1[512],cmd[300] = "",dest[300],src[300],c;
+int i,seq, res, ts;
+struct rpt_link *l;
+struct ast_frame wf;
wf.frametype = AST_FRAME_TEXT;
wf.subclass = 0;
wf.offset = 0;
- wf.mallocd = 1;
+ wf.mallocd = 0;
wf.datalen = strlen(str) + 1;
wf.samples = 0;
- if (!strcmp(str, discstr)) {
- mylink->disced = 1;
- mylink->retries = MAX_RETRIES + 1;
- ast_softhangup(mylink->chan, AST_SOFTHANGUP_DEV);
+ /* put string in our buffer */
+ strncpy(tmp,str,sizeof(tmp) - 1);
+
+ if (!strcmp(tmp,discstr))
+ {
+ mylink->disced = 1;
+ mylink->retries = mylink->max_retries + 1;
+ ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
+ return;
+ }
+ if (!strcmp(tmp,newkeystr))
+ {
+ mylink->newkey = 1;
+ return;
+ }
+ if (tmp[0] == 'L')
+ {
+ rpt_mutex_lock(&myrpt->lock);
+ strcpy(mylink->linklist,tmp + 2);
+ time(&mylink->linklistreceived);
+ rpt_mutex_unlock(&myrpt->lock);
+ if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s recieved node list %s from node %s\n",
+ myrpt->name,tmp,mylink->name);
return;
}
- if (sscanf(str, "%s %s %s %d %c", cmd, dest, src, &seq, &c) != 5) {
- ast_log(LOG_WARNING, "Unable to parse link string %s\n", str);
+ if (tmp[0] == 'K')
+ {
+ if (sscanf(tmp,"%s %s %s %d %d",cmd,dest,src,&seq,&ts) != 5)
+ {
+ ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
+ return;
+ }
+ if (dest[0] == '0')
+ {
+ strcpy(dest,myrpt->name);
+ }
+ /* if not for me, redistribute to all links */
+ if (strcmp(dest,myrpt->name))
+ {
+ l = myrpt->links.next;
+ /* see if this is one in list */
+ while(l != &myrpt->links)
+ {
+ if (l->name[0] == '0')
+ {
+ l = l->next;
+ continue;
+ }
+ /* dont send back from where it came */
+ if ((l == mylink) || (!strcmp(l->name,mylink->name)))
+ {
+ l = l->next;
+ continue;
+ }
+ /* if it is, send it and we're done */
+ if (!strcmp(l->name,dest))
+ {
+ /* send, but not to src */
+ if (strcmp(l->name,src)) {
+ wf.data = str;
+ if (l->chan) ast_write(l->chan,&wf);
+ }
+ return;
+ }
+ l = l->next;
+ }
+ }
+ /* if not for me, or is broadcast, redistribute to all links */
+ if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
+ {
+ l = myrpt->links.next;
+ /* otherwise, send it to all of em */
+ while(l != &myrpt->links)
+ {
+ if (l->name[0] == '0')
+ {
+ l = l->next;
+ continue;
+ }
+ /* dont send back from where it came */
+ if ((l == mylink) || (!strcmp(l->name,mylink->name)))
+ {
+ l = l->next;
+ continue;
+ }
+ /* send, but not to src */
+ if (strcmp(l->name,src)) {
+ wf.data = str;
+ if (l->chan) ast_write(l->chan,&wf);
+ }
+ l = l->next;
+ }
+ }
+ /* if not for me, end here */
+ if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
+ if (cmd[1] == '?')
+ {
+ time_t now;
+ int n = 0;
+
+ time(&now);
+ if (myrpt->lastkeyedtime)
+ {
+ n = (int)(now - myrpt->lastkeyedtime);
+ }
+ sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
+ wf.data = tmp1;
+ wf.datalen = strlen(tmp1) + 1;
+ if (mylink->chan) ast_write(mylink->chan,&wf);
+ return;
+ }
+ if (myrpt->topkeystate != 1) return;
+ rpt_mutex_lock(&myrpt->lock);
+ for(i = 0; i < TOPKEYN; i++)
+ {
+ if (!strcmp(myrpt->topkey[i].node,src)) break;
+ }
+ if (i >= TOPKEYN)
+ {
+ for(i = 0; i < TOPKEYN; i++)
+ {
+ if (!myrpt->topkey[i].node[0]) break;
+ }
+ }
+ if (i < TOPKEYN)
+ {
+ strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
+ myrpt->topkey[i].timesince = ts;
+ myrpt->topkey[i].keyed = seq;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
return;
}
- if (strcmp(cmd, "D")) {
- ast_log(LOG_WARNING, "Unable to parse link string %s\n", str);
- return;
+ if (tmp[0] == 'I')
+ {
+ if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
+ {
+ ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
+ return;
+ }
+ mdc1200_notify(myrpt,src,seq);
+ strcpy(dest,"*");
}
-
- if (dest[0] == '0') {
- strcpy(dest, myrpt->name);
+ else
+ {
+ if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
+ {
+ ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
+ return;
+ }
+ if (strcmp(cmd,"D"))
+ {
+ ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
+ return;
+ }
}
+ if (dest[0] == '0')
+ {
+ strcpy(dest,myrpt->name);
+ }
/* if not for me, redistribute to all links */
- if (strcmp(dest, myrpt->name)) {
+ if (strcmp(dest,myrpt->name))
+ {
l = myrpt->links.next;
/* see if this is one in list */
- while (l != &myrpt->links) {
- if (l->name[0] == '0') {
+ while(l != &myrpt->links)
+ {
+ if (l->name[0] == '0')
+ {
l = l->next;
continue;
}
/* dont send back from where it came */
- if ((l == mylink) || (!strcmp(l->name, mylink->name))) {
+ if ((l == mylink) || (!strcmp(l->name,mylink->name)))
+ {
l = l->next;
continue;
}
/* if it is, send it and we're done */
- if (!strcmp(l->name, dest)) {
+ if (!strcmp(l->name,dest))
+ {
/* send, but not to src */
- if (strcmp(l->name, src)) {
- wf.data = ast_strdup(str);
- if (l->chan)
- ast_write(l->chan, &wf);
+ if (strcmp(l->name,src)) {
+ wf.data = str;
+ if (l->chan) ast_write(l->chan,&wf);
}
return;
}
@@ -3542,89 +6885,130 @@ static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink, char *s
}
l = myrpt->links.next;
/* otherwise, send it to all of em */
- while (l != &myrpt->links) {
- if (l->name[0] == '0') {
+ while(l != &myrpt->links)
+ {
+ if (l->name[0] == '0')
+ {
l = l->next;
continue;
}
/* dont send back from where it came */
- if ((l == mylink) || (!strcmp(l->name, mylink->name))) {
+ if ((l == mylink) || (!strcmp(l->name,mylink->name)))
+ {
l = l->next;
continue;
}
/* send, but not to src */
- if (strcmp(l->name, src)) {
- wf.data = ast_strdup(str);
- if (l->chan)
- ast_write(l->chan, &wf);
+ if (strcmp(l->name,src)) {
+ wf.data = str;
+ if (l->chan) ast_write(l->chan,&wf);
}
l = l->next;
}
return;
}
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ sprintf(str,"DTMF,%s,%c",mylink->name,c);
+ donodelog(myrpt,str);
+ }
+ c = func_xlat(myrpt,c,&myrpt->p.outxlat);
+ if (!c) return;
rpt_mutex_lock(&myrpt->lock);
- if (c == myrpt->p.endchar)
- myrpt->stopgen = 1;
- if (myrpt->callmode == 1) {
+ if (c == myrpt->p.endchar) myrpt->stopgen = 1;
+ if (myrpt->callmode == 1)
+ {
myrpt->exten[myrpt->cidx++] = c;
myrpt->exten[myrpt->cidx] = 0;
/* if this exists */
- if (ast_exists_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
- myrpt->callmode = 2;
- if (!myrpt->patchquiet) {
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, PROC, NULL);
- rpt_mutex_lock(&myrpt->lock);
+ if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
+ {
+ /* if this really it, end now */
+ if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
+ myrpt->exten,1,NULL))
+ {
+ myrpt->callmode = 2;
+ if(!myrpt->patchquiet)
+ {
+ rpt_mutex_unlock(&myrpt->lock);
+ rpt_telemetry(myrpt,PROC,NULL);
+ rpt_mutex_lock(&myrpt->lock);
+ }
+ }
+ else /* othewise, reset timer */
+ {
+ myrpt->calldigittimer = 1;
}
}
/* if can continue, do so */
- if (!ast_canmatch_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
+ if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
+ {
/* call has failed, inform user */
myrpt->callmode = 4;
}
}
- if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) {
- myrpt->mydtmf = c;
- }
- if (c == myrpt->p.funcchar) {
+ if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
+ {
myrpt->rem_dtmfidx = 0;
myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
time(&myrpt->rem_dtmf_time);
rpt_mutex_unlock(&myrpt->lock);
return;
- } else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0)) {
+ }
+ else if (myrpt->rem_dtmfidx < 0)
+ {
+ if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
+ {
+ myrpt->mydtmf = c;
+ }
+ if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
+ if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
+ rpt_mutex_unlock(&myrpt->lock);
+ return;
+ }
+ else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
+ {
time(&myrpt->rem_dtmf_time);
- if (myrpt->rem_dtmfidx < MAXDTMF) {
+ if (myrpt->rem_dtmfidx < MAXDTMF)
+ {
myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
rpt_mutex_unlock(&myrpt->lock);
- ast_copy_string(cmd, myrpt->rem_dtmfbuf, sizeof(cmd));
+ strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
rpt_mutex_lock(&myrpt->lock);
- switch (res) {
- case DC_INDETERMINATE:
- break;
- case DC_REQ_FLUSH:
- myrpt->rem_dtmfidx = 0;
- myrpt->rem_dtmfbuf[0] = 0;
- break;
- case DC_COMPLETE:
- myrpt->totalexecdcommands++;
- myrpt->dailyexecdcommands++;
- ast_copy_string(myrpt->lastdtmfcommand, cmd, MAXDTMF);
- myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
- myrpt->rem_dtmfbuf[0] = 0;
- myrpt->rem_dtmfidx = -1;
- myrpt->rem_dtmf_time = 0;
- break;
- case DC_ERROR:
- default:
- myrpt->rem_dtmfbuf[0] = 0;
- myrpt->rem_dtmfidx = -1;
- myrpt->rem_dtmf_time = 0;
- break;
+ switch(res){
+
+ case DC_INDETERMINATE:
+ break;
+
+ case DC_REQ_FLUSH:
+ myrpt->rem_dtmfidx = 0;
+ myrpt->rem_dtmfbuf[0] = 0;
+ break;
+
+
+ case DC_COMPLETE:
+ case DC_COMPLETEQUIET:
+ myrpt->totalexecdcommands++;
+ myrpt->dailyexecdcommands++;
+ strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
+ myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
+ myrpt->rem_dtmfbuf[0] = 0;
+ myrpt->rem_dtmfidx = -1;
+ myrpt->rem_dtmf_time = 0;
+ break;
+
+ case DC_ERROR:
+ default:
+ myrpt->rem_dtmfbuf[0] = 0;
+ myrpt->rem_dtmfidx = -1;
+ myrpt->rem_dtmf_time = 0;
+ break;
}
}
@@ -3633,109 +7017,173 @@ static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink, char *s
return;
}
-static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink, char c)
+static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
+ char c)
{
- char cmd[300];
- int res;
+char cmd[300];
+int res;
+
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
+ donodelog(myrpt,str);
+ }
rpt_mutex_lock(&myrpt->lock);
- if (c == myrpt->p.endchar) {
- if (mylink->lastrx) {
- mylink->lastrx = 0;
+
+ if (mylink->phonemode == 3) /*If in simplex dumb phone mode */
+ {
+ if(c == myrpt->p.endchar) /* If end char */
+ {
+ mylink->lastrealrx = 0; /* Keying state = off */
rpt_mutex_unlock(&myrpt->lock);
return;
}
- myrpt->stopgen = 1;
- if (myrpt->cmdnode[0]) {
- myrpt->cmdnode[0] = 0;
- myrpt->dtmfidx = -1;
- myrpt->dtmfbuf[0] = 0;
+
+ if(c == myrpt->p.funcchar) /* If lead-in char */
+ {
+ mylink->lastrealrx = !mylink->lastrealrx; /* Toggle keying state */
rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, COMPLETE, NULL);
return;
}
}
- if (myrpt->cmdnode[0]) {
+ else
+ {
+ if (c == myrpt->p.endchar)
+ {
+ if (mylink->lastrx)
+ {
+ mylink->lastrealrx = 0;
+ rpt_mutex_unlock(&myrpt->lock);
+ return;
+ }
+ myrpt->stopgen = 1;
+ if (myrpt->cmdnode[0])
+ {
+ myrpt->cmdnode[0] = 0;
+ myrpt->dtmfidx = -1;
+ myrpt->dtmfbuf[0] = 0;
+ rpt_mutex_unlock(&myrpt->lock);
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ return;
+ }
+ }
+ }
+ if (myrpt->cmdnode[0])
+ {
rpt_mutex_unlock(&myrpt->lock);
- send_link_dtmf(myrpt, c);
+ send_link_dtmf(myrpt,c);
return;
}
- if (myrpt->callmode == 1) {
+ if (myrpt->callmode == 1)
+ {
myrpt->exten[myrpt->cidx++] = c;
myrpt->exten[myrpt->cidx] = 0;
/* if this exists */
- if (ast_exists_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
- myrpt->callmode = 2;
- if (!myrpt->patchquiet) {
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, PROC, NULL);
- rpt_mutex_lock(&myrpt->lock);
+ if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
+ {
+ /* if this really it, end now */
+ if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
+ myrpt->exten,1,NULL))
+ {
+ myrpt->callmode = 2;
+ if(!myrpt->patchquiet)
+ {
+ rpt_mutex_unlock(&myrpt->lock);
+ rpt_telemetry(myrpt,PROC,NULL);
+ rpt_mutex_lock(&myrpt->lock);
+ }
+ }
+ else /* othewise, reset timer */
+ {
+ myrpt->calldigittimer = 1;
}
}
/* if can continue, do so */
- if (!ast_canmatch_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
+ if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
+ {
/* call has failed, inform user */
myrpt->callmode = 4;
}
}
- if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) {
+ if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
+ {
myrpt->mydtmf = c;
}
- if (c == myrpt->p.funcchar) {
+ if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
+ {
myrpt->rem_dtmfidx = 0;
myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
time(&myrpt->rem_dtmf_time);
rpt_mutex_unlock(&myrpt->lock);
return;
- } else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0)) {
+ }
+ else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
+ {
time(&myrpt->rem_dtmf_time);
- if (myrpt->rem_dtmfidx < MAXDTMF) {
+ if (myrpt->rem_dtmfidx < MAXDTMF)
+ {
myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
rpt_mutex_unlock(&myrpt->lock);
- ast_copy_string(cmd, myrpt->rem_dtmfbuf, sizeof(cmd));
- switch(mylink->phonemode) {
- case 1:
+ strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
+ switch(mylink->phonemode)
+ {
+ case 1:
res = collect_function_digits(myrpt, cmd,
SOURCE_PHONE, mylink);
break;
- case 2:
+ case 2:
res = collect_function_digits(myrpt, cmd,
- SOURCE_DPHONE, mylink);
+ SOURCE_DPHONE,mylink);
break;
- default:
+ case 4:
+ res = collect_function_digits(myrpt, cmd,
+ SOURCE_ALT,mylink);
+ break;
+ default:
res = collect_function_digits(myrpt, cmd,
SOURCE_LNK, mylink);
break;
}
rpt_mutex_lock(&myrpt->lock);
+
+ switch(res){
- switch(res) {
- case DC_INDETERMINATE:
- break;
- case DC_DOKEY:
- mylink->lastrx = 1;
- break;
- case DC_REQ_FLUSH:
- myrpt->rem_dtmfidx = 0;
- myrpt->rem_dtmfbuf[0] = 0;
- break;
- case DC_COMPLETE:
- myrpt->totalexecdcommands++;
- myrpt->dailyexecdcommands++;
- ast_copy_string(myrpt->lastdtmfcommand, cmd, MAXDTMF);
- myrpt->rem_dtmfbuf[0] = 0;
- myrpt->rem_dtmfidx = -1;
- myrpt->rem_dtmf_time = 0;
- break;
- case DC_ERROR:
- default:
- myrpt->rem_dtmfbuf[0] = 0;
- myrpt->rem_dtmfidx = -1;
- myrpt->rem_dtmf_time = 0;
- break;
+ case DC_INDETERMINATE:
+ break;
+
+ case DC_DOKEY:
+ mylink->lastrealrx = 1;
+ break;
+
+ case DC_REQ_FLUSH:
+ myrpt->rem_dtmfidx = 0;
+ myrpt->rem_dtmfbuf[0] = 0;
+ break;
+
+
+ case DC_COMPLETE:
+ case DC_COMPLETEQUIET:
+ myrpt->totalexecdcommands++;
+ myrpt->dailyexecdcommands++;
+ strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
+ myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
+ myrpt->rem_dtmfbuf[0] = 0;
+ myrpt->rem_dtmfidx = -1;
+ myrpt->rem_dtmf_time = 0;
+ break;
+
+ case DC_ERROR:
+ default:
+ myrpt->rem_dtmfbuf[0] = 0;
+ myrpt->rem_dtmfidx = -1;
+ myrpt->rem_dtmf_time = 0;
+ break;
}
}
@@ -3777,33 +7225,34 @@ static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink, c
static int rbi_mhztoband(char *str)
{
- int i;
+int i;
i = atoi(str) / 10; /* get the 10's of mhz */
- switch (i) {
- case 2:
+ switch(i)
+ {
+ case 2:
return 10;
- case 5:
+ case 5:
return 11;
- case 14:
+ case 14:
return 2;
- case 22:
+ case 22:
return 3;
- case 44:
+ case 44:
return 4;
- case 124:
+ case 124:
return 0;
- case 125:
+ case 125:
return 1;
- case 126:
+ case 126:
return 8;
- case 127:
+ case 127:
return 5;
- case 128:
+ case 128:
return 6;
- case 129:
+ case 129:
return 7;
- default:
+ default:
break;
}
return -1;
@@ -3812,90 +7261,90 @@ static int rbi_mhztoband(char *str)
/* take a PL frequency and turn it into a code */
static int rbi_pltocode(char *str)
{
- int i;
- char *s;
+int i;
+char *s;
- s = strchr(str, '.');
+ s = strchr(str,'.');
i = 0;
- if (s)
- i = atoi(s + 1);
+ if (s) i = atoi(s + 1);
i += atoi(str) * 10;
- switch(i) {
- case 670:
+ switch(i)
+ {
+ case 670:
return 0;
- case 719:
+ case 719:
return 1;
- case 744:
+ case 744:
return 2;
- case 770:
+ case 770:
return 3;
- case 797:
+ case 797:
return 4;
- case 825:
+ case 825:
return 5;
- case 854:
+ case 854:
return 6;
- case 885:
+ case 885:
return 7;
- case 915:
+ case 915:
return 8;
- case 948:
+ case 948:
return 9;
- case 974:
+ case 974:
return 10;
- case 1000:
+ case 1000:
return 11;
- case 1035:
+ case 1035:
return 12;
- case 1072:
+ case 1072:
return 13;
- case 1109:
+ case 1109:
return 14;
- case 1148:
+ case 1148:
return 15;
- case 1188:
+ case 1188:
return 16;
- case 1230:
+ case 1230:
return 17;
- case 1273:
+ case 1273:
return 18;
- case 1318:
+ case 1318:
return 19;
- case 1365:
+ case 1365:
return 20;
- case 1413:
+ case 1413:
return 21;
- case 1462:
+ case 1462:
return 22;
- case 1514:
+ case 1514:
return 23;
- case 1567:
+ case 1567:
return 24;
- case 1622:
+ case 1622:
return 25;
- case 1679:
+ case 1679:
return 26;
- case 1738:
+ case 1738:
return 27;
- case 1799:
+ case 1799:
return 28;
- case 1862:
+ case 1862:
return 29;
- case 1928:
+ case 1928:
return 30;
- case 2035:
+ case 2035:
return 31;
- case 2107:
+ case 2107:
return 32;
- case 2181:
+ case 2181:
return 33;
- case 2257:
+ case 2257:
return 34;
- case 2336:
+ case 2336:
return 35;
- case 2418:
+ case 2418:
return 36;
- case 2503:
+ case 2503:
return 37;
}
return -1;
@@ -3905,166 +7354,769 @@ static int rbi_pltocode(char *str)
* Shift out a formatted serial bit stream
*/
-static void rbi_out_parallel(struct rpt *myrpt, unsigned char *data)
-{
- int i, j;
- unsigned char od, d;
-
- for (i = 0; i < 5; i++) {
- od = *data++;
- for (j = 0; j < 8; j++) {
- d = od & 1;
- outb(d, myrpt->p.iobase);
- usleep(15);
- od >>= 1;
- outb(d | 2, myrpt->p.iobase);
- usleep(30);
- outb(d, myrpt->p.iobase);
- usleep(10);
- }
- }
+static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
+ {
+#ifdef __i386__
+ int i,j;
+ unsigned char od,d;
+ static volatile long long delayvar;
+
+ for(i = 0 ; i < 5 ; i++){
+ od = *data++;
+ for(j = 0 ; j < 8 ; j++){
+ d = od & 1;
+ outb(d,myrpt->p.iobase);
+ /* >= 15 us */
+ for(delayvar = 1; delayvar < 15000; delayvar++);
+ od >>= 1;
+ outb(d | 2,myrpt->p.iobase);
+ /* >= 30 us */
+ for(delayvar = 1; delayvar < 30000; delayvar++);
+ outb(d,myrpt->p.iobase);
+ /* >= 10 us */
+ for(delayvar = 1; delayvar < 10000; delayvar++);
+ }
+ }
/* >= 50 us */
- usleep(50);
-}
+ for(delayvar = 1; delayvar < 50000; delayvar++);
+#endif
+ }
-static void rbi_out(struct rpt *myrpt, unsigned char *data)
+static void rbi_out(struct rpt *myrpt,unsigned char *data)
{
- struct zt_radio_param r = { 0, };
+struct zt_radio_param r;
+ memset(&r,0,sizeof(struct zt_radio_param));
r.radpar = ZT_RADPAR_REMMODE;
r.data = ZT_RADPAR_REM_RBI1;
/* if setparam ioctl fails, its probably not a pciradio card */
- if (ioctl(myrpt->rxchannel->fds[0], ZT_RADIO_SETPARAM, &r) == -1) {
- rbi_out_parallel(myrpt, data);
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
+ {
+ rbi_out_parallel(myrpt,data);
return;
}
r.radpar = ZT_RADPAR_REMCOMMAND;
- memcpy(&r.data, data, 5);
- if (ioctl(myrpt->rxchannel->fds[0], ZT_RADIO_SETPARAM, &r) == -1) {
- ast_log(LOG_WARNING, "Cannot send RBI command for channel %s\n", myrpt->rxchannel->name);
+ memcpy(&r.data,data,5);
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
+ {
+ ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->zaprxchannel->name);
return;
}
}
-static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes, char *rxbuf, int rxmaxbytes, int asciiflag)
+static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
+ unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
{
- int i;
+ int i,j,index,oldmode,olddata;
struct zt_radio_param prm;
+ char c;
- char *buf = alloca(30 + txbytes * 3);
- int len;
- ast_copy_string(buf, "String output was: ", 30 + txbytes * 3);
- len = strlen(buf);
- for (i = 0; i < txbytes; i++)
- len += snprintf(buf + len, 30 + txbytes * 3 - len, "%02X ", (unsigned char) txbuf[i]);
- strcat(buf + len, "\n");
- ast_debug(1, "%s", buf);
-
- prm.radpar = ZT_RADPAR_REMMODE;
- if (asciiflag)
- prm.data = ZT_RADPAR_REM_SERIAL_ASCII;
- else
- prm.data = ZT_RADPAR_REM_SERIAL;
- if (ioctl(myrpt->rxchannel->fds[0], ZT_RADIO_SETPARAM, &prm) == -1)
- return -1;
- prm.radpar = ZT_RADPAR_REMCOMMAND;
- prm.data = rxmaxbytes;
- memcpy(prm.buf, txbuf, txbytes);
- prm.index = txbytes;
- if (ioctl(myrpt->rxchannel->fds[0], ZT_RADIO_SETPARAM, &prm) == -1)
- return -1;
- if (rxbuf) {
- *rxbuf = 0;
- memcpy(rxbuf, prm.buf, prm.index);
+ if(debug) {
+ ast_log(LOG_NOTICE, "ioport=%s iofd=0x%x\n",myrpt->p.ioport,myrpt->iofd);
+ printf("String output was:\n");
+ for(i = 0; i < txbytes; i++)
+ printf("%02X ", (unsigned char ) txbuf[i]);
+ printf("\n");
+ }
+
+ if (myrpt->iofd >= 0) /* if to do out a serial port */
+ {
+ if (write(myrpt->iofd,txbuf,txbytes) != txbytes)
+ {
+ return -1;
+ }
+ if ((!rxmaxbytes) || (rxbuf == NULL))
+ {
+ return(0);
+ }
+ memset(rxbuf,0,rxmaxbytes);
+ for(i = 0; i < rxmaxbytes; i++)
+ {
+ j = read(myrpt->iofd,&c,1);
+ if (j < 1)
+ {
+ return(i);
+ }
+ rxbuf[i] = c;
+ if (asciiflag & 1)
+ {
+ rxbuf[i + 1] = 0;
+ if (c == '\r') break;
+ }
+ }
+ if(debug) {
+ printf("String returned was:\n");
+ for(j = 0; j < i; j++)
+ printf("%02X ", (unsigned char ) rxbuf[j]);
+ printf("\n");
+ }
+ return(i);
+ }
+
+ /* if not a zap channel, cant use pciradio stuff */
+ if (myrpt->rxchannel != myrpt->zaprxchannel) return -1;
+
+ prm.radpar = ZT_RADPAR_UIOMODE;
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_GETPARAM,&prm) == -1) return -1;
+ oldmode = prm.data;
+ prm.radpar = ZT_RADPAR_UIODATA;
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_GETPARAM,&prm) == -1) return -1;
+ olddata = prm.data;
+ prm.radpar = ZT_RADPAR_REMMODE;
+ if (asciiflag & 1) prm.data = ZT_RADPAR_REM_SERIAL_ASCII;
+ else prm.data = ZT_RADPAR_REM_SERIAL;
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
+ if (asciiflag & 2)
+ {
+ i = ZT_ONHOOK;
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_HOOK,&i) == -1) return -1;
+ usleep(100000);
+ }
+ prm.radpar = ZT_RADPAR_REMCOMMAND;
+ prm.data = rxmaxbytes;
+ memcpy(prm.buf,txbuf,txbytes);
+ prm.index = txbytes;
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
+ if (rxbuf)
+ {
+ *rxbuf = 0;
+ memcpy(rxbuf,prm.buf,prm.index);
+ }
+ index = prm.index;
+ prm.radpar = ZT_RADPAR_REMMODE;
+ prm.data = ZT_RADPAR_REM_NONE;
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
+ if (asciiflag & 2)
+ {
+ i = ZT_OFFHOOK;
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_HOOK,&i) == -1) return -1;
+ }
+ prm.radpar = ZT_RADPAR_UIOMODE;
+ prm.data = oldmode;
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
+ prm.radpar = ZT_RADPAR_UIODATA;
+ prm.data = olddata;
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
+ return(index);
+}
+
+static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
+{
+unsigned char rxbuf[100];
+int i,rv ;
+
+ rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
+ if (rv == -1) return(-1);
+ if (rv != (cmdlen + 6)) return(1);
+ for(i = 0; i < 6; i++)
+ if (rxbuf[i] != cmd[i]) return(1);
+ if (rxbuf[cmdlen] != 0xfe) return(1);
+ if (rxbuf[cmdlen + 1] != 0xfe) return(1);
+ if (rxbuf[cmdlen + 4] != 0xfb) return(1);
+ if (rxbuf[cmdlen + 5] != 0xfd) return(1);
+ return(0);
+}
+
+static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
+{
+int i;
+
+ast_log(LOG_NOTICE,"Sent to kenwood: %s\n",txstr);
+ if (debug) printf("Send to kenwood: %s\n",txstr);
+ i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
+ (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
+ if (i < 0) return -1;
+ if ((i > 0) && (rxstr[i - 1] == '\r'))
+ rxstr[i-- - 1] = 0;
+ if (debug) printf("Got from kenwood: %s\n",rxstr);
+ast_log(LOG_NOTICE,"Got from kenwood: %s\n",rxstr);
+ return(i);
+}
+
+/* take a PL frequency and turn it into a code */
+static int kenwood_pltocode(char *str)
+{
+int i;
+char *s;
+
+ s = strchr(str,'.');
+ i = 0;
+ if (s) i = atoi(s + 1);
+ i += atoi(str) * 10;
+ switch(i)
+ {
+ case 670:
+ return 1;
+ case 719:
+ return 3;
+ case 744:
+ return 4;
+ case 770:
+ return 5;
+ case 797:
+ return 6;
+ case 825:
+ return 7;
+ case 854:
+ return 8;
+ case 885:
+ return 9;
+ case 915:
+ return 10;
+ case 948:
+ return 11;
+ case 974:
+ return 12;
+ case 1000:
+ return 13;
+ case 1035:
+ return 14;
+ case 1072:
+ return 15;
+ case 1109:
+ return 16;
+ case 1148:
+ return 17;
+ case 1188:
+ return 18;
+ case 1230:
+ return 19;
+ case 1273:
+ return 20;
+ case 1318:
+ return 21;
+ case 1365:
+ return 22;
+ case 1413:
+ return 23;
+ case 1462:
+ return 24;
+ case 1514:
+ return 25;
+ case 1567:
+ return 26;
+ case 1622:
+ return 27;
+ case 1679:
+ return 28;
+ case 1738:
+ return 29;
+ case 1799:
+ return 30;
+ case 1862:
+ return 31;
+ case 1928:
+ return 32;
+ case 2035:
+ return 33;
+ case 2107:
+ return 34;
+ case 2181:
+ return 35;
+ case 2257:
+ return 36;
+ case 2336:
+ return 37;
+ case 2418:
+ return 38;
+ case 2503:
+ return 39;
+ }
+ return -1;
+}
+
+static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
+ char *cmpstr)
+{
+int i,j;
+
+ for(i = 0;i < KENWOOD_RETRIES;i++)
+ {
+ j = sendkenwood(myrpt,txstr,rxstr);
+ if (j < 0) return(j);
+ if (j == 0) continue;
+ if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
+ }
+ return(-1);
+}
+
+static int setkenwood(struct rpt *myrpt)
+{
+char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
+char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
+int myrxpl;
+
+int offsets[] = {0,2,1};
+int powers[] = {2,1,0};
+
+ if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
+ split_freq(mhz, decimals, myrpt->freq);
+ if (atoi(mhz) > 400)
+ {
+ band = '6';
+ band1 = '1';
+ band2 = '5';
+ strcpy(offset,"005000000");
}
- return(prm.index);
+ else
+ {
+ band = '2';
+ band1 = '0';
+ band2 = '2';
+ strcpy(offset,"000600000");
+ }
+ strcpy(freq,"000000");
+ strncpy(freq,decimals,strlen(decimals));
+ myrxpl = myrpt->rxplon;
+ if (IS_XPMR(myrpt)) myrxpl = 0;
+ sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
+ band,atoi(mhz),freq,offsets[(int)myrpt->offset],
+ (myrpt->txplon != 0),myrxpl,
+ kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
+ offset);
+ if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
+ sprintf(txstr,"RBN %c\r",band2);
+ if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
+ sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
+ if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
+ return 0;
+}
+
+static int set_tm271(struct rpt *myrpt)
+{
+char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
+char mhz[MAXREMSTR],decimals[MAXREMSTR];
+
+int offsets[] = {0,2,1};
+int powers[] = {2,1,0};
+
+ split_freq(mhz, decimals, myrpt->freq);
+ strcpy(freq,"000000");
+ strncpy(freq,decimals,strlen(decimals));
+
+ sprintf(txstr,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
+ atoi(mhz),freq,offsets[(int)myrpt->offset],
+ (myrpt->txplon != 0),kenwood_pltocode(myrpt->txpl),
+ kenwood_pltocode(myrpt->rxpl));
+
+ if (sendrxkenwood(myrpt,txstr,rxstr,"VF") < 0) return -1;
+ if (sendrxkenwood(myrpt,"VM 0\r",rxstr,"VM") < 0) return -1;
+ sprintf(txstr,"PC %d\r",powers[(int)myrpt->powerlevel]);
+ if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
+ return 0;
}
static int setrbi(struct rpt *myrpt)
{
- char tmp[MAXREMSTR] = "", *s;
- unsigned char rbicmd[5];
- int band, txoffset = 0, txpower = 0, txpl;
+char tmp[MAXREMSTR] = "",*s;
+unsigned char rbicmd[5];
+int band,txoffset = 0,txpower = 0,rxpl;
/* must be a remote system */
- if (!myrpt->remote)
- return(0);
+ if (!myrpt->remoterig) return(0);
+ if (!myrpt->remoterig[0]) return(0);
/* must have rbi hardware */
- if (strncmp(myrpt->remote, remote_rig_rbi, 3))
- return(0);
- ast_copy_string(tmp, myrpt->freq, sizeof(tmp));
- s = strchr(tmp, '.');
+ if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
+ if (setrbi_check(myrpt) == -1) return(-1);
+ strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
+ s = strchr(tmp,'.');
/* if no decimal, is invalid */
- if (s == NULL) {
- ast_debug(1, "@@@@ Frequency needs a decimal\n");
+ if (s == NULL){
+ if(debug)
+ printf("@@@@ Frequency needs a decimal\n");
return -1;
}
*s++ = 0;
- if (strlen(tmp) < 2) {
- ast_debug(1, "@@@@ Bad MHz digits: %s\n", tmp);
+ if (strlen(tmp) < 2){
+ if(debug)
+ printf("@@@@ Bad MHz digits: %s\n", tmp);
return -1;
}
- if (strlen(s) < 3) {
- ast_debug(1, "@@@@ Bad KHz digits: %s\n", s);
+ if (strlen(s) < 3){
+ if(debug)
+ printf("@@@@ Bad KHz digits: %s\n", s);
return -1;
}
- if ((s[2] != '0') && (s[2] != '5')) {
- ast_debug(1, "@@@@ KHz must end in 0 or 5: %c\n", s[2]);
+ if ((s[2] != '0') && (s[2] != '5')){
+ if(debug)
+ printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
return -1;
}
band = rbi_mhztoband(tmp);
- if (band == -1) {
- ast_debug(1, "@@@@ Bad Band: %s\n", tmp);
+ if (band == -1){
+ if(debug)
+ printf("@@@@ Bad Band: %s\n", tmp);
return -1;
}
- txpl = rbi_pltocode(myrpt->txpl);
+ rxpl = rbi_pltocode(myrpt->rxpl);
- if (txpl == -1) {
- ast_debug(1, "@@@@ Bad TX PL: %s\n", myrpt->txpl);
+ if (rxpl == -1){
+ if(debug)
+ printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
return -1;
}
- switch (myrpt->offset) {
- case REM_MINUS:
+ switch(myrpt->offset)
+ {
+ case REM_MINUS:
txoffset = 0;
break;
- case REM_PLUS:
+ case REM_PLUS:
txoffset = 0x10;
break;
- case REM_SIMPLEX:
+ case REM_SIMPLEX:
txoffset = 0x20;
break;
}
- switch(myrpt->powerlevel) {
- case REM_LOWPWR:
+ switch(myrpt->powerlevel)
+ {
+ case REM_LOWPWR:
txpower = 0;
break;
- case REM_MEDPWR:
+ case REM_MEDPWR:
txpower = 0x20;
break;
- case REM_HIPWR:
+ case REM_HIPWR:
txpower = 0x10;
break;
}
rbicmd[0] = 0;
rbicmd[1] = band | txpower | 0xc0;
rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
- if (s[2] == '5')
- rbicmd[2] |= 0x40;
+ if (s[2] == '5') rbicmd[2] |= 0x40;
rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
- rbicmd[4] = txpl;
- if (myrpt->txplon)
- rbicmd[4] |= 0x40;
- if (myrpt->rxplon)
- rbicmd[4] |= 0x80;
- rbi_out(myrpt, rbicmd);
+ rbicmd[4] = rxpl;
+ if (myrpt->txplon) rbicmd[4] |= 0x40;
+ if (myrpt->rxplon) rbicmd[4] |= 0x80;
+ rbi_out(myrpt,rbicmd);
+ return 0;
+}
+
+static int setrtx(struct rpt *myrpt)
+{
+char tmp[MAXREMSTR] = "",*s,rigstr[200],pwr,res = 0;
+int band,txoffset = 0,txpower = 0,rxpl,txpl;
+float ofac;
+double txfreq;
+
+ /* must be a remote system */
+ if (!myrpt->remoterig) return(0);
+ if (!myrpt->remoterig[0]) return(0);
+ /* must have rtx hardware */
+ if (!ISRIG_RTX(myrpt->remoterig)) return(0);
+ /* must be a usbradio interface type */
+ if (!IS_XPMR(myrpt)) return(0);
+ strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
+ s = strchr(tmp,'.');
+ /* if no decimal, is invalid */
+
+ if(debug)printf("setrtx() %s %s\n",myrpt->name,myrpt->remoterig);
+
+ if (s == NULL){
+ if(debug)
+ printf("@@@@ Frequency needs a decimal\n");
+ return -1;
+ }
+ *s++ = 0;
+ if (strlen(tmp) < 2){
+ if(debug)
+ printf("@@@@ Bad MHz digits: %s\n", tmp);
+ return -1;
+ }
+
+ if (strlen(s) < 3){
+ if(debug)
+ printf("@@@@ Bad KHz digits: %s\n", s);
+ return -1;
+ }
+
+ if ((s[2] != '0') && (s[2] != '5')){
+ if(debug)
+ printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
+ return -1;
+ }
+
+ band = rbi_mhztoband(tmp);
+ if (band == -1){
+ if(debug)
+ printf("@@@@ Bad Band: %s\n", tmp);
+ return -1;
+ }
+
+ rxpl = rbi_pltocode(myrpt->rxpl);
+
+ if (rxpl == -1){
+ if(debug)
+ printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
+ return -1;
+ }
+
+ txpl = rbi_pltocode(myrpt->txpl);
+
+ if (txpl == -1){
+ if(debug)
+ printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
+ return -1;
+ }
+
+ switch(myrpt->offset)
+ {
+ case REM_MINUS:
+ txoffset = 0;
+ break;
+ case REM_PLUS:
+ txoffset = 0x10;
+ break;
+ case REM_SIMPLEX:
+ txoffset = 0x20;
+ break;
+ }
+ switch(myrpt->powerlevel)
+ {
+ case REM_LOWPWR:
+ txpower = 0;
+ break;
+ case REM_MEDPWR:
+ txpower = 0x20;
+ break;
+ case REM_HIPWR:
+ txpower = 0x10;
+ break;
+ }
+
+ res = setrtx_check(myrpt);
+ if (res < 0) return res;
+ ofac = 0.0;
+ if (myrpt->offset == REM_MINUS) ofac = -1.0;
+ if (myrpt->offset == REM_PLUS) ofac = 1.0;
+
+ if (!strcmp(myrpt->remoterig,remote_rig_rtx450))
+ txfreq = atof(myrpt->freq) + (ofac * 5.0);
+ else
+ txfreq = atof(myrpt->freq) + (ofac * 0.6);
+
+ pwr = 'L';
+ if (myrpt->powerlevel == REM_HIPWR) pwr = 'H';
+ if (!res)
+ {
+ sprintf(rigstr,"SETFREQ %s %f %s %s %c",myrpt->freq,txfreq,
+ (myrpt->rxplon) ? myrpt->rxpl : "0.0",
+ (myrpt->txplon) ? myrpt->txpl : "0.0",pwr);
+ send_usb_txt(myrpt,rigstr);
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ res = 0;
+ }
+ return 0;
+}
+#if 0
+/*
+ sets current signaling code for xpmr routines
+ under development for new radios.
+*/
+static int setxpmr(struct rpt *myrpt)
+{
+ char rigstr[200];
+ int rxpl,txpl;
+
+ /* must be a remote system */
+ if (!myrpt->remoterig) return(0);
+ if (!myrpt->remoterig[0]) return(0);
+ /* must not have rtx hardware */
+ if (ISRIG_RTX(myrpt->remoterig)) return(0);
+ /* must be a usbradio interface type */
+ if (!IS_XPMR(myrpt)) return(0);
+
+ if(debug)printf("setxpmr() %s %s\n",myrpt->name,myrpt->remoterig );
+
+ rxpl = rbi_pltocode(myrpt->rxpl);
+
+ if (rxpl == -1){
+ if(debug)
+ printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
+ return -1;
+ }
+
+ txpl = rbi_pltocode(myrpt->txpl);
+ if (txpl == -1){
+ if(debug)
+ printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
+ return -1;
+ }
+ sprintf(rigstr,"SETFREQ 0.0 0.0 %s %s L",
+ (myrpt->rxplon) ? myrpt->rxpl : "0.0",
+ (myrpt->txplon) ? myrpt->txpl : "0.0");
+ send_usb_txt(myrpt,rigstr);
+ return 0;
+}
+#endif
+
+static int setrbi_check(struct rpt *myrpt)
+{
+char tmp[MAXREMSTR] = "",*s;
+int band,txpl;
+
+ /* must be a remote system */
+ if (!myrpt->remote) return(0);
+ /* must have rbi hardware */
+ if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
+ strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
+ s = strchr(tmp,'.');
+ /* if no decimal, is invalid */
+
+ if (s == NULL){
+ if(debug)
+ printf("@@@@ Frequency needs a decimal\n");
+ return -1;
+ }
+
+ *s++ = 0;
+ if (strlen(tmp) < 2){
+ if(debug)
+ printf("@@@@ Bad MHz digits: %s\n", tmp);
+ return -1;
+ }
+
+ if (strlen(s) < 3){
+ if(debug)
+ printf("@@@@ Bad KHz digits: %s\n", s);
+ return -1;
+ }
+
+ if ((s[2] != '0') && (s[2] != '5')){
+ if(debug)
+ printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
+ return -1;
+ }
+
+ band = rbi_mhztoband(tmp);
+ if (band == -1){
+ if(debug)
+ printf("@@@@ Bad Band: %s\n", tmp);
+ return -1;
+ }
+
+ txpl = rbi_pltocode(myrpt->txpl);
+
+ if (txpl == -1){
+ if(debug)
+ printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
+ return -1;
+ }
+ return 0;
+}
+
+static int setrtx_check(struct rpt *myrpt)
+{
+char tmp[MAXREMSTR] = "",*s;
+int band,txpl,rxpl;
+
+ /* must be a remote system */
+ if (!myrpt->remote) return(0);
+ /* must have rbi hardware */
+ if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
+ strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
+ s = strchr(tmp,'.');
+ /* if no decimal, is invalid */
+
+ if (s == NULL){
+ if(debug)
+ printf("@@@@ Frequency needs a decimal\n");
+ return -1;
+ }
+
+ *s++ = 0;
+ if (strlen(tmp) < 2){
+ if(debug)
+ printf("@@@@ Bad MHz digits: %s\n", tmp);
+ return -1;
+ }
+
+ if (strlen(s) < 3){
+ if(debug)
+ printf("@@@@ Bad KHz digits: %s\n", s);
+ return -1;
+ }
+
+ if ((s[2] != '0') && (s[2] != '5')){
+ if(debug)
+ printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
+ return -1;
+ }
+
+ band = rbi_mhztoband(tmp);
+ if (band == -1){
+ if(debug)
+ printf("@@@@ Bad Band: %s\n", tmp);
+ return -1;
+ }
+
+ txpl = rbi_pltocode(myrpt->txpl);
+
+ if (txpl == -1){
+ if(debug)
+ printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
+ return -1;
+ }
+
+ rxpl = rbi_pltocode(myrpt->rxpl);
+
+ if (rxpl == -1){
+ if(debug)
+ printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
+ return -1;
+ }
+ return 0;
+}
+
+static int check_freq_kenwood(int m, int d, int *defmode)
+{
+ int dflmd = REM_MODE_FM;
+
+ if (m == 144){ /* 2 meters */
+ if(d < 10100)
+ return -1;
+ }
+ else if((m >= 145) && (m < 148)){
+ ;
+ }
+ else if((m >= 430) && (m < 450)){ /* 70 centimeters */
+ ;
+ }
+ else
+ return -1;
+
+ if(defmode)
+ *defmode = dflmd;
+
+
+ return 0;
+}
+
+
+static int check_freq_tm271(int m, int d, int *defmode)
+{
+ int dflmd = REM_MODE_FM;
+
+ if (m == 144){ /* 2 meters */
+ if(d < 10100)
+ return -1;
+ }
+ else if((m >= 145) && (m < 148)){
+ ;
+ }
+ return -1;
+
+ if(defmode)
+ *defmode = dflmd;
+
+
return 0;
}
@@ -4076,55 +8128,138 @@ static int check_freq_rbi(int m, int d, int *defmode)
{
int dflmd = REM_MODE_FM;
- if (m == 50) { /* 6 meters */
- if (d < 10100)
+ if(m == 50){ /* 6 meters */
+ if(d < 10100)
return -1;
- } else if ((m >= 51) && ( m < 54)) {
- /* nada */
- } else if (m == 144) { /* 2 meters */
- if (d < 10100)
+ }
+ else if((m >= 51) && ( m < 54)){
+ ;
+ }
+ else if(m == 144){ /* 2 meters */
+ if(d < 10100)
return -1;
- } else if ((m >= 145) && (m < 148)) {
- /* nada */
- } else if ((m >= 222) && (m < 225)) { /* 1.25 meters */
- /* nada */
- } else if ((m >= 430) && (m < 450)) { /* 70 centimeters */
- /* nada */
- } else if ((m >= 1240) && (m < 1300)) { /* 23 centimeters */
- /* nada */
- } else
+ }
+ else if((m >= 145) && (m < 148)){
+ ;
+ }
+ else if((m >= 222) && (m < 225)){ /* 1.25 meters */
+ ;
+ }
+ else if((m >= 430) && (m < 450)){ /* 70 centimeters */
+ ;
+ }
+ else if((m >= 1240) && (m < 1300)){ /* 23 centimeters */
+ ;
+ }
+ else
return -1;
- if (defmode)
+ if(defmode)
*defmode = dflmd;
+
return 0;
}
-static int split_decimal(char *input, int *ints, int *decs, int places)
+/* Check for valid rtx frequency */
+/* Hard coded limits now, configurable later, maybe? */
+
+static int check_freq_rtx(int m, int d, int *defmode, struct rpt *myrpt)
{
- double input2 = 0.0;
- long long modifier = (long long)pow(10.0, (double)places);
- if (sscanf(input, "%lf", &input2) == 1) {
- long long input3 = input2 * modifier;
- *ints = input3 / modifier;
- *decs = input3 % modifier;
+ int dflmd = REM_MODE_FM;
+
+ if (!strcmp(myrpt->remoterig,remote_rig_rtx150))
+ {
+
+ if(m == 144){ /* 2 meters */
+ if(d < 10100)
+ return -1;
+ }
+ else if((m >= 145) && (m < 148)){
+ ;
+ }
+ else
+ return -1;
+ }
+ else
+ {
+ if((m >= 430) && (m < 450)){ /* 70 centimeters */
+ ;
+ }
+ else
+ return -1;
+ }
+ if(defmode)
+ *defmode = dflmd;
+
+
+ return 0;
+}
+
+/*
+ * Convert decimals of frequency to int
+ */
+
+static int decimals2int(char *fraction)
+{
+ int i;
+ char len = strlen(fraction);
+ int multiplier = 100000;
+ int res = 0;
+
+ if(!len)
return 0;
- } else
- return -1;
+ for( i = 0 ; i < len ; i++, multiplier /= 10)
+ res += (fraction[i] - '0') * multiplier;
+ return res;
}
+
/*
* Split frequency into mhz and decimals
*/
-#define split_freq(mhz, decimal, freq) split_decimal(freq, mhz, decimal, 5)
+static int split_freq(char *mhz, char *decimals, char *freq)
+{
+ char freq_copy[MAXREMSTR];
+ char *decp;
+
+ decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
+ if(decp){
+ *decp++ = 0;
+ strncpy(mhz, freq_copy, MAXREMSTR);
+ strcpy(decimals, "00000");
+ strncpy(decimals, decp, strlen(decp));
+ decimals[5] = 0;
+ return 0;
+ }
+ else
+ return -1;
+}
+
/*
* Split ctcss frequency into hertz and decimal
*/
-#define split_ctcss_freq(hertz, decimal, freq) split_decimal(freq, hertz, decimal, 1)
+static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
+{
+ char freq_copy[MAXREMSTR];
+ char *decp;
+
+ decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
+ if(decp){
+ *decp++ = 0;
+ strncpy(hertz, freq_copy, MAXREMSTR);
+ strncpy(decimal, decp, strlen(decp));
+ decimal[strlen(decp)] = '\0';
+ return 0;
+ }
+ else
+ return -1;
+}
+
+
/*
* FT-897 I/O handlers
@@ -4133,77 +8268,87 @@ static int split_decimal(char *input, int *ints, int *decs, int places)
/* Check to see that the frequency is valid */
/* Hard coded limits now, configurable later, maybe? */
+
static int check_freq_ft897(int m, int d, int *defmode)
{
int dflmd = REM_MODE_FM;
- if (m == 1) { /* 160 meters */
+ if(m == 1){ /* 160 meters */
dflmd = REM_MODE_LSB;
- if (d < 80001)
+ if(d < 80000)
return -1;
- } else if (m == 3) { /* 80 meters */
+ }
+ else if(m == 3){ /* 80 meters */
dflmd = REM_MODE_LSB;
- if (d < 75001)
+ if(d < 50000)
return -1;
- } else if (m == 7) { /* 40 meters */
+ }
+ else if(m == 7){ /* 40 meters */
dflmd = REM_MODE_LSB;
- if ((d < 15001) || (d > 29999))
+ if(d > 30000)
return -1;
- } else if (m == 14) { /* 20 meters */
+ }
+ else if(m == 14){ /* 20 meters */
dflmd = REM_MODE_USB;
- if ((d < 15001) || (d > 34999))
+ if(d > 35000)
return -1;
- } else if (m == 18) { /* 17 meters */
+ }
+ else if(m == 18){ /* 17 meters */
dflmd = REM_MODE_USB;
- if ((d < 11001) || (d > 16797))
+ if((d < 6800) || (d > 16800))
return -1;
- } else if (m == 21) { /* 15 meters */
+ }
+ else if(m == 21){ /* 15 meters */
dflmd = REM_MODE_USB;
- if ((d < 20001) || (d > 44999))
+ if((d < 20000) || (d > 45000))
return -1;
- } else if (m == 24) { /* 12 meters */
+ }
+ else if(m == 24){ /* 12 meters */
dflmd = REM_MODE_USB;
- if ((d < 93001) || (d > 98999))
+ if((d < 89000) || (d > 99000))
return -1;
- } else if (m == 28) { /* 10 meters */
+ }
+ else if(m == 28){ /* 10 meters */
dflmd = REM_MODE_USB;
- if (d < 30001)
- return -1;
- } else if (m == 29) {
- if (d >= 51000)
+ }
+ else if(m == 29){
+ if(d >= 51000)
dflmd = REM_MODE_FM;
else
dflmd = REM_MODE_USB;
- if (d > 69999)
- return -1;
- } else if (m == 50) { /* 6 meters */
- if (d < 10100)
+ if(d > 70000)
return -1;
- if (d >= 30000)
+ }
+ else if(m == 50){ /* 6 meters */
+ if(d >= 30000)
dflmd = REM_MODE_FM;
else
dflmd = REM_MODE_USB;
- } else if ((m >= 51) && ( m < 54)) {
+
+ }
+ else if((m >= 51) && ( m < 54)){
dflmd = REM_MODE_FM;
- } else if (m == 144) { /* 2 meters */
- if (d < 10100)
- return -1;
- if (d >= 30000)
+ }
+ else if(m == 144){ /* 2 meters */
+ if(d >= 30000)
dflmd = REM_MODE_FM;
else
dflmd = REM_MODE_USB;
- } else if ((m >= 145) && (m < 148)) {
+ }
+ else if((m >= 145) && (m < 148)){
dflmd = REM_MODE_FM;
- } else if ((m >= 430) && (m < 450)) { /* 70 centimeters */
- if (m < 438)
+ }
+ else if((m >= 430) && (m < 450)){ /* 70 centimeters */
+ if(m < 438)
dflmd = REM_MODE_USB;
else
dflmd = REM_MODE_FM;
;
- } else
+ }
+ else
return -1;
- if (defmode)
+ if(defmode)
*defmode = dflmd;
return 0;
@@ -4216,52 +8361,69 @@ static int check_freq_ft897(int m, int d, int *defmode)
static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
{
unsigned char cmdstr[5];
- int fd, m, d;
+ int fd,m,d;
+ char mhz[MAXREMSTR];
+ char decimals[MAXREMSTR];
fd = 0;
- ast_debug(1, "New frequency: %s\n", newfreq);
+ if(debug)
+ printf("New frequency: %s\n",newfreq);
- if (split_freq(&m, &d, newfreq))
+ if(split_freq(mhz, decimals, newfreq))
return -1;
+ m = atoi(mhz);
+ d = atoi(decimals);
+
/* The FT-897 likes packed BCD frequencies */
- cmdstr[0] = ((m / 100) << 4) + ((m % 100) / 10); /* 100MHz 10Mhz */
- cmdstr[1] = ((m % 10) << 4) + (d / 10000); /* 1MHz 100KHz */
- cmdstr[2] = (((d % 10000) / 1000) << 4) + ((d % 1000) / 100); /* 10KHz 1KHz */
- cmdstr[3] = (((d % 100) / 10) << 4) + (d % 10); /* 100Hz 10Hz */
- cmdstr[4] = 0x01; /* command */
+ cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10); /* 100MHz 10Mhz */
+ cmdstr[1] = ((m % 10) << 4) + (d / 10000); /* 1MHz 100KHz */
+ cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100); /* 10KHz 1KHz */
+ cmdstr[3] = (((d % 100)/10) << 4) + (d % 10); /* 100Hz 10Hz */
+ cmdstr[4] = 0x01; /* command */
return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
+
}
/* ft-897 simple commands */
static int simple_command_ft897(struct rpt *myrpt, char command)
{
- unsigned char cmdstr[5] = { 0, 0, 0, 0, command };
+ unsigned char cmdstr[5];
+
+ memset(cmdstr, 0, 5);
+
+ cmdstr[4] = command;
return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
+
}
/* ft-897 offset */
static int set_offset_ft897(struct rpt *myrpt, char offset)
{
- unsigned char cmdstr[5] = "";
+ unsigned char cmdstr[5];
+
+ memset(cmdstr, 0, 5);
- switch (offset) {
- case REM_SIMPLEX:
- cmdstr[0] = 0x89;
- break;
- case REM_MINUS:
- cmdstr[0] = 0x09;
- break;
- case REM_PLUS:
- cmdstr[0] = 0x49;
- break;
- default:
- return -1;
+ switch(offset){
+ case REM_SIMPLEX:
+ cmdstr[0] = 0x89;
+ break;
+
+ case REM_MINUS:
+ cmdstr[0] = 0x09;
+ break;
+
+ case REM_PLUS:
+ cmdstr[0] = 0x49;
+ break;
+
+ default:
+ return -1;
}
cmdstr[4] = 0x09;
@@ -4273,24 +8435,31 @@ static int set_offset_ft897(struct rpt *myrpt, char offset)
static int set_mode_ft897(struct rpt *myrpt, char newmode)
{
- unsigned char cmdstr[5] = { 0, 0, 0, 0, 0x07 };
+ unsigned char cmdstr[5];
+
+ memset(cmdstr, 0, 5);
+
+ switch(newmode){
+ case REM_MODE_FM:
+ cmdstr[0] = 0x08;
+ break;
- switch (newmode) {
- case REM_MODE_FM:
- cmdstr[0] = 0x08;
- break;
- case REM_MODE_USB:
- cmdstr[0] = 0x01;
- break;
- case REM_MODE_LSB:
- cmdstr[0] = 0x00;
- break;
- case REM_MODE_AM:
- cmdstr[0] = 0x04;
- break;
- default:
- return -1;
+ case REM_MODE_USB:
+ cmdstr[0] = 0x01;
+ break;
+
+ case REM_MODE_LSB:
+ cmdstr[0] = 0x00;
+ break;
+
+ case REM_MODE_AM:
+ cmdstr[0] = 0x04;
+ break;
+
+ default:
+ return -1;
}
+ cmdstr[4] = 0x07;
return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
}
@@ -4299,9 +8468,11 @@ static int set_mode_ft897(struct rpt *myrpt, char newmode)
static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
{
- unsigned char cmdstr[5] = { 0, 0, 0, 0, 0x0A };
-
- if (rxplon && txplon)
+ unsigned char cmdstr[5];
+
+ memset(cmdstr, 0, 5);
+
+ if(rxplon && txplon)
cmdstr[0] = 0x2A; /* Encode and Decode */
else if (!rxplon && txplon)
cmdstr[0] = 0x4A; /* Encode only */
@@ -4310,6 +8481,8 @@ static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
else
cmdstr[0] = 0x8A; /* OFF */
+ cmdstr[4] = 0x0A;
+
return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
}
@@ -4318,22 +8491,33 @@ static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
{
- unsigned char cmdstr[5] = { 0, 0, 0, 0, 0x0B };
- int hertz, decimal;
+ unsigned char cmdstr[5];
+ char hertz[MAXREMSTR],decimal[MAXREMSTR];
+ int h,d;
- if (split_ctcss_freq(&hertz, &decimal, txtone))
+ memset(cmdstr, 0, 5);
+
+ if(split_ctcss_freq(hertz, decimal, txtone))
return -1;
- cmdstr[0] = ((hertz / 100) << 4) + (hertz % 100) / 10;
- cmdstr[1] = ((hertz % 10) << 4) + (decimal % 10);
+ h = atoi(hertz);
+ d = atoi(decimal);
+
+ cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
+ cmdstr[1] = ((h % 10) << 4) + (d % 10);
- if (rxtone) {
- if (split_ctcss_freq(&hertz, &decimal, rxtone))
+ if(rxtone){
+
+ if(split_ctcss_freq(hertz, decimal, rxtone))
return -1;
- cmdstr[2] = ((hertz / 100) << 4) + (hertz % 100)/ 10;
- cmdstr[3] = ((hertz % 10) << 4) + (decimal % 10);
+ h = atoi(hertz);
+ d = atoi(decimal);
+
+ cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
+ cmdstr[3] = ((h % 10) << 4) + (d % 10);
}
+ cmdstr[4] = 0x0B;
return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
}
@@ -4344,44 +8528,53 @@ static int set_ft897(struct rpt *myrpt)
{
int res;
- ast_debug(1, "@@@@ lock on\n");
+ if(debug)
+ printf("@@@@ lock on\n");
- res = simple_command_ft897(myrpt, 0x00); /* LOCK on */
+ res = simple_command_ft897(myrpt, 0x00); /* LOCK on */
- ast_debug(1, "@@@@ ptt off\n");
+ if(debug)
+ printf("@@@@ ptt off\n");
- if (!res)
+ if(!res)
res = simple_command_ft897(myrpt, 0x88); /* PTT off */
- ast_debug(1, "Modulation mode\n");
+ if(debug)
+ printf("Modulation mode\n");
- if (!res)
+ if(!res)
res = set_mode_ft897(myrpt, myrpt->remmode); /* Modulation mode */
- ast_debug(1, "Split off\n");
+ if(debug)
+ printf("Split off\n");
- if (!res)
+ if(!res)
simple_command_ft897(myrpt, 0x82); /* Split off */
- ast_debug(1, "Frequency\n");
+ if(debug)
+ printf("Frequency\n");
- if (!res)
+ if(!res)
res = set_freq_ft897(myrpt, myrpt->freq); /* Frequency */
- if ((myrpt->remmode == REM_MODE_FM)) {
- ast_debug(1, "Offset\n");
- if (!res)
+ if((myrpt->remmode == REM_MODE_FM)){
+ if(debug)
+ printf("Offset\n");
+ if(!res)
res = set_offset_ft897(myrpt, myrpt->offset); /* Offset if FM */
- if ((!res)&&(myrpt->rxplon || myrpt->txplon)) {
- ast_debug(1, "CTCSS tone freqs.\n");
+ if((!res)&&(myrpt->rxplon || myrpt->txplon)){
+ if(debug)
+ printf("CTCSS tone freqs.\n");
res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl); /* CTCSS freqs if CTCSS is enabled */
}
- if (!res) {
- ast_debug(1, "CTCSS mode\n");
+ if(!res){
+ if(debug)
+ printf("CTCSS mode\n");
res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */
}
}
- if ((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)) {
- ast_debug(1, "Clarifier off\n");
+ if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
+ if(debug)
+ printf("Clarifier off\n");
simple_command_ft897(myrpt, 0x85); /* Clarifier off if LSB or USB */
}
return res;
@@ -4401,29 +8594,38 @@ static int closerem_ft897(struct rpt *myrpt)
static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
{
- int m, d;
+ int m,d;
+ char mhz[MAXREMSTR], decimals[MAXREMSTR];
- ast_debug(1, "Before bump: %s\n", myrpt->freq);
+ if(debug)
+ printf("Before bump: %s\n", myrpt->freq);
- if (split_freq(&m, &d, myrpt->freq))
+ if(split_freq(mhz, decimals, myrpt->freq))
return -1;
+ m = atoi(mhz);
+ d = atoi(decimals);
+
d += (interval / 10); /* 10Hz resolution */
- if (d < 0) {
+ if(d < 0){
m--;
d += 100000;
- } else if (d >= 100000) {
+ }
+ else if(d >= 100000){
m++;
d -= 100000;
}
- if (check_freq_ft897(m, d, NULL)) {
- ast_debug(1, "Bump freq invalid\n");
+ if(check_freq_ft897(m, d, NULL)){
+ if(debug)
+ printf("Bump freq invalid\n");
return -1;
}
snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
- ast_debug(1, "After bump: %s\n", myrpt->freq);
+
+ if(debug)
+ printf("After bump: %s\n", myrpt->freq);
return set_freq_ft897(myrpt, myrpt->freq);
}
@@ -4431,893 +8633,1543 @@ static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
/*
-* Dispatch to correct I/O handler
+* IC-706 I/O handlers
*/
-static int setrem(struct rpt *myrpt)
+/* Check to see that the frequency is valid */
+/* returns 0 if frequency is valid */
+
+static int check_freq_ic706(int m, int d, int *defmode, char mars)
{
- return 0; /* XXX BROKEN!! */
- if (!strcmp(myrpt->remote, remote_rig_ft897))
- return set_ft897(myrpt);
- else if (!strcmp(myrpt->remote, remote_rig_rbi))
- return setrbi(myrpt);
- else
- return -1;
+ int dflmd = REM_MODE_FM;
+ int rv=0;
+
+ if(debug > 6)
+ ast_log(LOG_NOTICE,"(%i,%i,%i,%i)\n",m,d,*defmode,mars);
+
+ /* first test for standard amateur radio bands */
+
+ if(m == 1){ /* 160 meters */
+ dflmd = REM_MODE_LSB;
+ if(d < 80000)rv=-1;
+ }
+ else if(m == 3){ /* 80 meters */
+ dflmd = REM_MODE_LSB;
+ if(d < 50000)rv=-1;
+ }
+ else if(m == 7){ /* 40 meters */
+ dflmd = REM_MODE_LSB;
+ if(d > 30000)rv=-1;
+ }
+ else if(m == 14){ /* 20 meters */
+ dflmd = REM_MODE_USB;
+ if(d > 35000)rv=-1;
+ }
+ else if(m == 18){ /* 17 meters */
+ dflmd = REM_MODE_USB;
+ if((d < 6800) || (d > 16800))rv=-1;
+ }
+ else if(m == 21){ /* 15 meters */
+ dflmd = REM_MODE_USB;
+ if((d < 20000) || (d > 45000))rv=-1;
+ }
+ else if(m == 24){ /* 12 meters */
+ dflmd = REM_MODE_USB;
+ if((d < 89000) || (d > 99000))rv=-1;
+ }
+ else if(m == 28){ /* 10 meters */
+ dflmd = REM_MODE_USB;
+ }
+ else if(m == 29){
+ if(d >= 51000)
+ dflmd = REM_MODE_FM;
+ else
+ dflmd = REM_MODE_USB;
+ if(d > 70000)rv=-1;
+ }
+ else if(m == 50){ /* 6 meters */
+ if(d >= 30000)
+ dflmd = REM_MODE_FM;
+ else
+ dflmd = REM_MODE_USB;
+ }
+ else if((m >= 51) && ( m < 54)){
+ dflmd = REM_MODE_FM;
+ }
+ else if(m == 144){ /* 2 meters */
+ if(d >= 30000)
+ dflmd = REM_MODE_FM;
+ else
+ dflmd = REM_MODE_USB;
+ }
+ else if((m >= 145) && (m < 148)){
+ dflmd = REM_MODE_FM;
+ }
+ else if((m >= 430) && (m < 450)){ /* 70 centimeters */
+ if(m < 438)
+ dflmd = REM_MODE_USB;
+ else
+ dflmd = REM_MODE_FM;
+ }
+
+ /* check expanded coverage */
+ if(mars && rv<0){
+ if((m >= 450) && (m < 470)){ /* LMR */
+ dflmd = REM_MODE_FM;
+ rv=0;
+ }
+ else if((m >= 148) && (m < 174)){ /* LMR */
+ dflmd = REM_MODE_FM;
+ rv=0;
+ }
+ else if((m >= 138) && (m < 144)){ /* VHF-AM AIRCRAFT */
+ dflmd = REM_MODE_AM;
+ rv=0;
+ }
+ else if((m >= 108) && (m < 138)){ /* VHF-AM AIRCRAFT */
+ dflmd = REM_MODE_AM;
+ rv=0;
+ }
+ else if( (m==0 && d>=55000) || (m==1 && d<=75000) ){ /* AM BCB*/
+ dflmd = REM_MODE_AM;
+ rv=0;
+ }
+ else if( (m == 1 && d>75000) || (m>1 && m<30) ){ /* HF SWL*/
+ dflmd = REM_MODE_AM;
+ rv=0;
+ }
+ }
+
+ if(defmode)
+ *defmode = dflmd;
+
+ if(debug > 1)
+ ast_log(LOG_NOTICE,"(%i,%i,%i,%i) returning %i\n",m,d,*defmode,mars,rv);
+
+ return rv;
}
-static int closerem(struct rpt *myrpt)
+/* take a PL frequency and turn it into a code */
+static int ic706_pltocode(char *str)
{
- return 0; /* XXX BROKEN!! */
- if (!strcmp(myrpt->remote, remote_rig_ft897))
- return closerem_ft897(myrpt);
- else
- return 0;
+ int i;
+ char *s;
+ int rv=-1;
+
+ s = strchr(str,'.');
+ i = 0;
+ if (s) i = atoi(s + 1);
+ i += atoi(str) * 10;
+ switch(i)
+ {
+ case 670:
+ rv=0;
+ case 693:
+ rv=1;
+ case 719:
+ rv=2;
+ case 744:
+ rv=3;
+ case 770:
+ rv=4;
+ case 797:
+ rv=5;
+ case 825:
+ rv=6;
+ case 854:
+ rv=7;
+ case 885:
+ rv=8;
+ case 915:
+ rv=9;
+ case 948:
+ rv=10;
+ case 974:
+ rv=11;
+ case 1000:
+ rv=12;
+ case 1035:
+ rv=13;
+ case 1072:
+ rv=14;
+ case 1109:
+ rv=15;
+ case 1148:
+ rv=16;
+ case 1188:
+ rv=17;
+ case 1230:
+ rv=18;
+ case 1273:
+ rv=19;
+ case 1318:
+ rv=20;
+ case 1365:
+ rv=21;
+ case 1413:
+ rv=22;
+ case 1462:
+ rv=23;
+ case 1514:
+ rv=24;
+ case 1567:
+ rv=25;
+ case 1598:
+ rv=26;
+ case 1622:
+ rv=27;
+ case 1655:
+ rv=28;
+ case 1679:
+ rv=29;
+ case 1713:
+ rv=30;
+ case 1738:
+ rv=31;
+ case 1773:
+ rv=32;
+ case 1799:
+ rv=33;
+ case 1835:
+ rv=34;
+ case 1862:
+ rv=35;
+ case 1899:
+ rv=36;
+ case 1928:
+ rv=37;
+ case 1966:
+ rv=38;
+ case 1995:
+ rv=39;
+ case 2035:
+ rv=40;
+ case 2065:
+ rv=41;
+ case 2107:
+ rv=42;
+ case 2181:
+ rv=43;
+ case 2257:
+ rv=44;
+ case 2291:
+ rv=45;
+ case 2336:
+ rv=46;
+ case 2418:
+ rv=47;
+ case 2503:
+ rv=48;
+ case 2541:
+ rv=49;
+ }
+ if(debug > 1)
+ ast_log(LOG_NOTICE,"%i rv=%i\n",i, rv);
+
+ return rv;
}
-/*
-* Dispatch to correct frequency checker
-*/
+/* ic-706 simple commands */
-static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
+static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
{
- if (!strcmp(myrpt->remote, remote_rig_ft897))
- return check_freq_ft897(m, d, defmode);
- else if (!strcmp(myrpt->remote, remote_rig_rbi))
- return check_freq_rbi(m, d, defmode);
- else
- return -1;
+ unsigned char cmdstr[10];
+
+ cmdstr[0] = cmdstr[1] = 0xfe;
+ cmdstr[2] = myrpt->p.civaddr;
+ cmdstr[3] = 0xe0;
+ cmdstr[4] = command;
+ cmdstr[5] = subcommand;
+ cmdstr[6] = 0xfd;
+
+ return(civ_cmd(myrpt,cmdstr,7));
}
/*
-* Return 1 if rig is multimode capable
+* Set a new frequency for the ic706
*/
-static int multimode_capable(struct rpt *myrpt)
+static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
{
- if (!strcmp(myrpt->remote, remote_rig_ft897))
- return 1;
- return 0;
-}
+ unsigned char cmdstr[20];
+ char mhz[MAXREMSTR], decimals[MAXREMSTR];
+ int fd,m,d;
-/*
-* Dispatch to correct frequency bumping function
-*/
+ fd = 0;
+ if(debug)
+ ast_log(LOG_NOTICE,"newfreq:%s\n",newfreq);
-static int multimode_bump_freq(struct rpt *myrpt, int interval)
-{
- if (!strcmp(myrpt->remote, remote_rig_ft897))
- return multimode_bump_freq_ft897(myrpt, interval);
- else
- return -1;
-}
+ if(split_freq(mhz, decimals, newfreq))
+ return -1;
+ m = atoi(mhz);
+ d = atoi(decimals);
-/*
-* Queue announcment that scan has been stopped
-*/
+ /* The ic-706 likes packed BCD frequencies */
-static void stop_scan(struct rpt *myrpt, int flag)
-{
- myrpt->hfscanmode = 0;
- myrpt->hfscanstatus = ((flag) ? -2 : -1);
+ cmdstr[0] = cmdstr[1] = 0xfe;
+ cmdstr[2] = myrpt->p.civaddr;
+ cmdstr[3] = 0xe0;
+ cmdstr[4] = 5;
+ cmdstr[5] = ((d % 10) << 4);
+ cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
+ cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
+ cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
+ cmdstr[9] = (m / 100);
+ cmdstr[10] = 0xfd;
+
+ return(civ_cmd(myrpt,cmdstr,11));
}
-/*
-* This is called periodically when in scan mode
-*/
+/* ic-706 offset */
-static int service_scan(struct rpt *myrpt)
+static int set_offset_ic706(struct rpt *myrpt, char offset)
{
- int res, interval, mhz, decimals;
- char k10=0, k100=0;
+ unsigned char c;
- switch (myrpt->hfscanmode) {
+ if(debug > 6)
+ ast_log(LOG_NOTICE,"offset=%i\n",offset);
- case HF_SCAN_DOWN_SLOW:
- interval = -10; /* 100Hz /sec */
- break;
+ switch(offset){
+ case REM_SIMPLEX:
+ c = 0x10;
+ break;
- case HF_SCAN_DOWN_QUICK:
- interval = -50; /* 500Hz /sec */
- break;
+ case REM_MINUS:
+ c = 0x11;
+ break;
+
+ case REM_PLUS:
+ c = 0x12;
+ break;
- case HF_SCAN_DOWN_FAST:
- interval = -200; /* 2KHz /sec */
- break;
+ default:
+ return -1;
+ }
- case HF_SCAN_UP_SLOW:
- interval = 10; /* 100Hz /sec */
- break;
+ return simple_command_ic706(myrpt,0x0f,c);
- case HF_SCAN_UP_QUICK:
- interval = 50; /* 500 Hz/sec */
- break;
+}
- case HF_SCAN_UP_FAST:
- interval = 200; /* 2KHz /sec */
- break;
+/* ic-706 mode */
- default:
- myrpt->hfscanmode = 0; /* Huh? */
- return -1;
- }
+static int set_mode_ic706(struct rpt *myrpt, char newmode)
+{
+ unsigned char c;
+
+ if(debug > 6)
+ ast_log(LOG_NOTICE,"newmode=%i\n",newmode);
- res = split_freq(&mhz, &decimals, myrpt->freq);
-
- if (!res) {
- k100 = decimals / 10000;
- k10 = (decimals / 1000) % 10;
- res = multimode_bump_freq(myrpt, interval);
- }
+ switch(newmode){
+ case REM_MODE_FM:
+ c = 5;
+ break;
- if (!res)
- res = split_freq(&mhz, &decimals, myrpt->freq);
+ case REM_MODE_USB:
+ c = 1;
+ break;
- if (res) {
- stop_scan(myrpt, 1);
- return -1;
- }
+ case REM_MODE_LSB:
+ c = 0;
+ break;
- /* Announce 10KHz boundaries */
- if (k10 != (decimals / 1000) % 10) {
- int myhund = (interval < 0) ? k100 : decimals / 10000;
- int myten = (interval < 0) ? k10 : (decimals / 1000) % 10;
- myrpt->hfscanstatus = (myten == 0) ? (myhund) * 100 : (myten) * 10;
+ case REM_MODE_AM:
+ c = 2;
+ break;
+
+ default:
+ return -1;
}
- return res;
-
+ return simple_command_ic706(myrpt,6,c);
}
+/* Set tone encode and decode modes */
-static int rmt_telem_start(struct rpt *myrpt, struct ast_channel *chan, int delay)
+static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
{
- myrpt->remotetx = 0;
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
- if (!myrpt->remoterx)
- ast_indicate(chan, AST_CONTROL_RADIO_KEY);
- if (ast_safe_sleep(chan, delay) == -1)
- return -1;
- return 0;
+ unsigned char cmdstr[10];
+ int rv;
+
+ if(debug > 6)
+ ast_log(LOG_NOTICE,"txplon=%i rxplon=%i \n",txplon,rxplon);
+
+ cmdstr[0] = cmdstr[1] = 0xfe;
+ cmdstr[2] = myrpt->p.civaddr;
+ cmdstr[3] = 0xe0;
+ cmdstr[4] = 0x16;
+ cmdstr[5] = 0x42;
+ cmdstr[6] = (txplon != 0);
+ cmdstr[7] = 0xfd;
+
+ rv = civ_cmd(myrpt,cmdstr,8);
+ if (rv) return(-1);
+
+ cmdstr[0] = cmdstr[1] = 0xfe;
+ cmdstr[2] = myrpt->p.civaddr;
+ cmdstr[3] = 0xe0;
+ cmdstr[4] = 0x16;
+ cmdstr[5] = 0x43;
+ cmdstr[6] = (rxplon != 0);
+ cmdstr[7] = 0xfd;
+
+ return(civ_cmd(myrpt,cmdstr,8));
}
+#if 0
+/* Set transmit and receive ctcss tone frequencies */
-static int rmt_telem_finish(struct rpt *myrpt, struct ast_channel *chan)
+static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
{
- struct zt_params par;
+ unsigned char cmdstr[10];
+ char hertz[MAXREMSTR],decimal[MAXREMSTR];
+ int h,d,rv;
- if (ioctl(myrpt->txchannel->fds[0], ZT_GET_PARAMS, &par) == -1) {
- return -1;
+ memset(cmdstr, 0, 5);
- }
- if (!par.rxisoffhook) {
- ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_UNKEY);
- myrpt->remoterx = 0;
- } else {
- myrpt->remoterx = 1;
- }
- return 0;
-}
+ if(debug > 6)
+ ast_log(LOG_NOTICE,"txtone=%s rxtone=%s \n",txtone,rxtone);
+
+ if(split_ctcss_freq(hertz, decimal, txtone))
+ return -1;
+
+ h = atoi(hertz);
+ d = atoi(decimal);
+
+ cmdstr[0] = cmdstr[1] = 0xfe;
+ cmdstr[2] = myrpt->p.civaddr;
+ cmdstr[3] = 0xe0;
+ cmdstr[4] = 0x1b;
+ cmdstr[5] = 0;
+ cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
+ cmdstr[7] = ((h % 10) << 4) + (d % 10);
+ cmdstr[8] = 0xfd;
+
+ rv = civ_cmd(myrpt,cmdstr,9);
+ if (rv) return(-1);
+
+ if (!rxtone) return(0);
+ if(split_ctcss_freq(hertz, decimal, rxtone))
+ return -1;
+
+ h = atoi(hertz);
+ d = atoi(decimal);
+
+ cmdstr[0] = cmdstr[1] = 0xfe;
+ cmdstr[2] = myrpt->p.civaddr;
+ cmdstr[3] = 0xe0;
+ cmdstr[4] = 0x1b;
+ cmdstr[5] = 1;
+ cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
+ cmdstr[7] = ((h % 10) << 4) + (d % 10);
+ cmdstr[8] = 0xfd;
+ return(civ_cmd(myrpt,cmdstr,9));
+}
+#endif
-static int rmt_sayfile(struct rpt *myrpt, struct ast_channel *chan, int delay, char *filename)
+static int vfo_ic706(struct rpt *myrpt)
{
- int res;
+ unsigned char cmdstr[10];
+
+ cmdstr[0] = cmdstr[1] = 0xfe;
+ cmdstr[2] = myrpt->p.civaddr;
+ cmdstr[3] = 0xe0;
+ cmdstr[4] = 7;
+ cmdstr[5] = 0xfd;
- res = rmt_telem_start(myrpt, chan, delay);
+ return(civ_cmd(myrpt,cmdstr,6));
+}
- if (!res)
- res = sayfile(chan, filename);
+static int mem2vfo_ic706(struct rpt *myrpt)
+{
+ unsigned char cmdstr[10];
- if (!res)
- res = rmt_telem_finish(myrpt, chan);
- return res;
+ cmdstr[0] = cmdstr[1] = 0xfe;
+ cmdstr[2] = myrpt->p.civaddr;
+ cmdstr[3] = 0xe0;
+ cmdstr[4] = 0x0a;
+ cmdstr[5] = 0xfd;
+
+ return(civ_cmd(myrpt,cmdstr,6));
}
-static int rmt_saycharstr(struct rpt *myrpt, struct ast_channel *chan, int delay, char *charstr)
+static int select_mem_ic706(struct rpt *myrpt, int slot)
{
- int res;
+ unsigned char cmdstr[10];
+
+ cmdstr[0] = cmdstr[1] = 0xfe;
+ cmdstr[2] = myrpt->p.civaddr;
+ cmdstr[3] = 0xe0;
+ cmdstr[4] = 8;
+ cmdstr[5] = 0;
+ cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
+ cmdstr[7] = 0xfd;
+
+ return(civ_cmd(myrpt,cmdstr,8));
+}
- res = rmt_telem_start(myrpt, chan, delay);
+static int set_ic706(struct rpt *myrpt)
+{
+ int res = 0,i;
+
+ if(debug)ast_log(LOG_NOTICE, "Set to VFO A iobase=%i\n",myrpt->p.iobase);
if (!res)
- res = saycharstr(chan, charstr);
-
+ res = simple_command_ic706(myrpt,7,0);
+
+ if((myrpt->remmode == REM_MODE_FM))
+ {
+ i = ic706_pltocode(myrpt->rxpl);
+ if (i == -1) return -1;
+ if(debug)
+ printf("Select memory number\n");
+ if (!res)
+ res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
+ if(debug)
+ printf("Transfer memory to VFO\n");
+ if (!res)
+ res = mem2vfo_ic706(myrpt);
+ }
+
+ if(debug)
+ printf("Set to VFO\n");
+
+ if (!res)
+ res = vfo_ic706(myrpt);
+
+ if(debug)
+ printf("Modulation mode\n");
+
if (!res)
- res = rmt_telem_finish(myrpt, chan);
+ res = set_mode_ic706(myrpt, myrpt->remmode); /* Modulation mode */
+
+ if(debug)
+ printf("Split off\n");
+
+ if(!res)
+ simple_command_ic706(myrpt, 0x82,0); /* Split off */
+
+ if(debug)
+ printf("Frequency\n");
+
+ if(!res)
+ res = set_freq_ic706(myrpt, myrpt->freq); /* Frequency */
+ if((myrpt->remmode == REM_MODE_FM)){
+ if(debug)
+ printf("Offset\n");
+ if(!res)
+ res = set_offset_ic706(myrpt, myrpt->offset); /* Offset if FM */
+ if(!res){
+ if(debug)
+ printf("CTCSS mode\n");
+ res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */
+ }
+ }
return res;
}
/*
-* Remote base function
+* Bump frequency up or down by a small amount
+* Return 0 if the new frequnecy is valid, or -1 if invalid
+* Interval is in Hz, resolution is 10Hz
*/
-static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
+static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
{
- char *s, *modestr;
- const char *val;
- int i, j, ht, k, l, ls2, res, offset, offsave, modesave, defmode = 0;
- char multimode = 0;
- char oc;
- char tmp[20], freq[20] = "", savestr[20] = "";
- int mhz = 0, decimals = 0;
- struct ast_channel *mychannel;
- AST_DECLARE_APP_ARGS(args1,
- AST_APP_ARG(freq);
- AST_APP_ARG(xpl);
- AST_APP_ARG(mode);
- );
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(s1);
- AST_APP_ARG(s2);
- );
-
- if ((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
- return DC_ERROR;
-
- multimode = multimode_capable(myrpt);
- mychannel = myrpt->remchannel;
+ int m,d;
+ char mhz[MAXREMSTR], decimals[MAXREMSTR];
+ unsigned char cmdstr[20];
- switch (myatoi(param)) {
- case 1: /* retrieve memory */
- if (strlen(digitbuf) < 2) /* needs 2 digits */
- break;
-
- for (i = 0 ; i < 2 ; i++) {
- if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
- return DC_ERROR;
- }
+ if(debug)
+ printf("Before bump: %s\n", myrpt->freq);
- val = ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, digitbuf);
- if (!val) {
- if (ast_safe_sleep(mychannel, 1000) == -1)
- return DC_ERROR;
- sayfile(mychannel, "rpt/memory_notfound");
- return DC_COMPLETE;
- }
- s = ast_strdupa(val);
- AST_STANDARD_APP_ARGS(args1, s);
- if (args1.argc < 3)
- return DC_ERROR;
- ast_copy_string(myrpt->freq, args1.freq, sizeof(myrpt->freq));
- ast_copy_string(myrpt->rxpl, args1.xpl, sizeof(myrpt->rxpl));
- ast_copy_string(myrpt->txpl, args1.xpl, sizeof(myrpt->rxpl));
- myrpt->remmode = REM_MODE_FM;
- myrpt->offset = REM_SIMPLEX;
- myrpt->powerlevel = REM_MEDPWR;
- myrpt->txplon = myrpt->rxplon = 0;
- modestr = args1.mode;
- while (*modestr) {
- switch (*modestr++) {
- case 'A':
- case 'a':
- strcpy(myrpt->rxpl, "100.0");
- strcpy(myrpt->txpl, "100.0");
- myrpt->remmode = REM_MODE_AM;
- break;
+ if(split_freq(mhz, decimals, myrpt->freq))
+ return -1;
+
+ m = atoi(mhz);
+ d = atoi(decimals);
- case 'B':
- case 'b':
- strcpy(myrpt->rxpl, "100.0");
- strcpy(myrpt->txpl, "100.0");
- myrpt->remmode = REM_MODE_LSB;
- break;
+ d += (interval / 10); /* 10Hz resolution */
+ if(d < 0){
+ m--;
+ d += 100000;
+ }
+ else if(d >= 100000){
+ m++;
+ d -= 100000;
+ }
- case 'F':
- myrpt->remmode = REM_MODE_FM;
- break;
+ if(check_freq_ic706(m, d, NULL,myrpt->p.remote_mars)){
+ if(debug)
+ printf("Bump freq invalid\n");
+ return -1;
+ }
- case 'L':
- case 'l':
- myrpt->powerlevel = REM_LOWPWR;
- break;
- case 'H':
- case 'h':
- myrpt->powerlevel = REM_HIPWR;
- break;
+ snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
- case 'M':
- case 'm':
- myrpt->powerlevel = REM_MEDPWR;
- break;
+ if(debug)
+ printf("After bump: %s\n", myrpt->freq);
- case '-':
- myrpt->offset = REM_MINUS;
- break;
+ /* The ic-706 likes packed BCD frequencies */
- case '+':
- myrpt->offset = REM_PLUS;
- break;
+ cmdstr[0] = cmdstr[1] = 0xfe;
+ cmdstr[2] = myrpt->p.civaddr;
+ cmdstr[3] = 0xe0;
+ cmdstr[4] = 0;
+ cmdstr[5] = ((d % 10) << 4);
+ cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
+ cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
+ cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
+ cmdstr[9] = (m / 100);
+ cmdstr[10] = 0xfd;
- case 'S':
- case 's':
- myrpt->offset = REM_SIMPLEX;
- break;
+ return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
+}
- case 'T':
- case 't':
- myrpt->txplon = 1;
- break;
- case 'R':
- case 'r':
- myrpt->rxplon = 1;
- break;
- case 'U':
- case 'u':
- strcpy(myrpt->rxpl, "100.0");
- strcpy(myrpt->txpl, "100.0");
- myrpt->remmode = REM_MODE_USB;
- break;
- }
+/*
+* Dispatch to correct I/O handler
+*/
+static int setrem(struct rpt *myrpt)
+{
+char str[300];
+char *offsets[] = {"SIMPLEX","MINUS","PLUS"};
+char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
+char *modes[] = {"FM","USB","LSB","AM"};
+int res = -1;
+
+#if 0
+printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt->freq,
+ modes[(int)myrpt->remmode],
+ myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
+ powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
+ myrpt->rxplon);
+#endif
+ if (myrpt->p.archivedir)
+ {
+ sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
+ modes[(int)myrpt->remmode],
+ myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
+ powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
+ myrpt->rxplon);
+ donodelog(myrpt,str);
+ }
+ if(!strcmp(myrpt->remoterig, remote_rig_ft897))
+ {
+ rpt_telemetry(myrpt,SETREMOTE,NULL);
+ res = 0;
+ }
+ if(!strcmp(myrpt->remoterig, remote_rig_ic706))
+ {
+ rpt_telemetry(myrpt,SETREMOTE,NULL);
+ res = 0;
+ }
+ if(!strcmp(myrpt->remoterig, remote_rig_tm271))
+ {
+ rpt_telemetry(myrpt,SETREMOTE,NULL);
+ res = 0;
+ }
+ else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
+ {
+ res = setrbi_check(myrpt);
+ if (!res)
+ {
+ rpt_telemetry(myrpt,SETREMOTE,NULL);
+ res = 0;
}
+ }
+ else if(ISRIG_RTX(myrpt->remoterig))
+ {
+ setrtx(myrpt);
+ res = 0;
+ }
+ else if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) {
+ rpt_telemetry(myrpt,SETREMOTE,NULL);
+ res = 0;
+ }
+ else
+ res = 0;
- if (setrem(myrpt) == -1)
- return DC_ERROR;
+ if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
- return DC_COMPLETE;
+ return res;
+}
- case 2: /* set freq and offset */
- for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for M+*K+*O or M+*H+* depending on mode */
- if (digitbuf[i] == '*') {
- j++;
- continue;
- }
- if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
- goto invalid_freq;
- else {
- if (j == 0)
- l++; /* # of digits before first * */
- if (j == 1)
- k++; /* # of digits after first * */
- }
- }
+static int closerem(struct rpt *myrpt)
+{
+ if(!strcmp(myrpt->remoterig, remote_rig_ft897))
+ return closerem_ft897(myrpt);
+ else
+ return 0;
+}
- i = strlen(digitbuf) - 1;
- if (multimode) {
- if ((j > 2) || (l > 3) || (k > 6))
- goto invalid_freq; /* &^@#! */
- } else {
- if ((j > 2) || (l > 4) || (k > 3))
- goto invalid_freq; /* &^@#! */
- }
+/*
+* Dispatch to correct RX frequency checker
+*/
- /* Wait for M+*K+* */
+static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
+{
+ if(!strcmp(myrpt->remoterig, remote_rig_ft897))
+ return check_freq_ft897(m, d, defmode);
+ else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
+ return check_freq_ic706(m, d, defmode,myrpt->p.remote_mars);
+ else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
+ return check_freq_rbi(m, d, defmode);
+ else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
+ return check_freq_kenwood(m, d, defmode);
+ else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
+ return check_freq_tm271(m, d, defmode);
+ else if(ISRIG_RTX(myrpt->remoterig))
+ return check_freq_rtx(m, d, defmode, myrpt);
+ else
+ return -1;
+}
- if (j < 2)
- break; /* Not yet */
+/*
+ * Check TX frequency before transmitting
+ rv=1 if tx frequency in ok.
+*/
- /* We have a frequency */
+static char check_tx_freq(struct rpt *myrpt)
+{
+ int i,rv=0;
+ int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
+ char radio_mhz_char[MAXREMSTR];
+ char radio_decimals_char[MAXREMSTR];
+ char limit_mhz_char[MAXREMSTR];
+ char limit_decimals_char[MAXREMSTR];
+ char limits[256];
+ char *limit_ranges[40];
+ struct ast_variable *limitlist;
+
+ if(debug > 3){
+ ast_log(LOG_NOTICE, "myrpt->freq = %s\n", myrpt->freq);
+ }
- s = ast_strdupa(digitbuf);
- AST_NONSTANDARD_APP_ARGS(args, s, '*');
- ls2 = strlen(args.s2);
+ /* Must have user logged in and tx_limits defined */
- switch (ls2) { /* Allow partial entry of khz and hz digits for laziness support */
- case 1:
- ht = 0;
- k = 100 * atoi(args.s2);
- break;
- case 2:
- ht = 0;
- k = 10 * atoi(args.s2);
- break;
- case 3:
- if (!multimode) {
- if ((args.s2[2] != '0') && (args.s2[2] != '5'))
- goto invalid_freq;
- }
- ht = 0;
- k = atoi(args.s2);
- break;
- case 4:
- k = atoi(args.s2) / 10;
- ht = 10 * (atoi(args.s2 + (ls2 - 1)));
- break;
- case 5:
- k = atoi(args.s2) / 100;
- ht = (atoi(args.s2 + (ls2 - 2)));
- break;
- default:
- goto invalid_freq;
+ if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
+ if(debug > 3){
+ ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in. rv=1\n");
}
+ rv=1;
+ return 1; /* Assume it's ok otherwise */
+ }
- /* Check frequency for validity and establish a default mode */
-
- snprintf(freq, sizeof(freq), "%s.%03d%02d", args.s1, k, ht);
- ast_debug(1, "New frequency: %s\n", freq);
-
- split_freq(&mhz, &decimals, freq);
-
- if (check_freq(myrpt, mhz, decimals, &defmode)) /* Check to see if frequency entered is legit */
- goto invalid_freq;
-
- if ((defmode == REM_MODE_FM) && (digitbuf[i] == '*')) /* If FM, user must enter and additional offset digit */
- break; /* Not yet */
+ /* Retrieve the band table for the loginlevel */
+ limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
- offset = REM_SIMPLEX; /* Assume simplex */
+ if(!limitlist){
+ ast_log(LOG_WARNING, "No entries in %s band table stanza. rv=0\n", myrpt->p.txlimitsstanzaname);
+ rv=0;
+ return 0;
+ }
- if (defmode == REM_MODE_FM) {
- oc = *s; /* Pick off offset */
- if (oc) {
- switch (oc) {
- case '1':
- offset = REM_MINUS;
- break;
- case '2':
- offset = REM_SIMPLEX;
- break;
- case '3':
- offset = REM_PLUS;
- break;
- default:
- goto invalid_freq;
- }
- }
- }
- offsave = myrpt->offset;
- modesave = myrpt->remmode;
- ast_copy_string(savestr, myrpt->freq, sizeof(savestr));
- ast_copy_string(myrpt->freq, freq, sizeof(myrpt->freq));
- myrpt->offset = offset;
- myrpt->remmode = defmode;
+ split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
+ radio_mhz = atoi(radio_mhz_char);
+ radio_decimals = decimals2int(radio_decimals_char);
- if (setrem(myrpt) == -1) {
- myrpt->offset = offsave;
- myrpt->remmode = modesave;
- ast_copy_string(myrpt->freq, savestr, sizeof(myrpt->freq));
- goto invalid_freq;
- }
+ if(debug > 3){
+ ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
+ }
- return DC_COMPLETE;
+ /* Find our entry */
-invalid_freq:
- rmt_sayfile(myrpt, mychannel, 1000, "rpt/invalid-freq");
+ for(;limitlist; limitlist=limitlist->next){
+ if(!strcmp(limitlist->name, myrpt->loginlevel))
+ break;
+ }
- return DC_ERROR;
-
- case 3: /* set rx PL tone */
+ if(!limitlist){
+ ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
+ rv=0;
+ return 0;
+ }
+
+ if(debug > 3){
+ ast_log(LOG_NOTICE, "Auth: %s = %s\n", limitlist->name, limitlist->value);
+ }
+
+ /* Parse the limits */
+
+ strncpy(limits, limitlist->value, 256);
+ limits[255] = 0;
+ finddelim(limits, limit_ranges, 40);
+ for(i = 0; i < 40 && limit_ranges[i] ; i++){
+ char range[40];
+ char *r,*s;
+ strncpy(range, limit_ranges[i], 40);
+ range[39] = 0;
+ if(debug > 3)
+ ast_log(LOG_NOTICE, "Check %s within %s\n", myrpt->freq, range);
+
+ r = strchr(range, '-');
+ if(!r){
+ ast_log(LOG_WARNING, "Malformed range in %s tx band table entry. rv=0\n", limitlist->name);
+ rv=0;
+ break;
+ }
+ *r++ = 0;
+ s = eatwhite(range);
+ r = eatwhite(r);
+ split_freq(limit_mhz_char, limit_decimals_char, s);
+ llimit_mhz = atoi(limit_mhz_char);
+ llimit_decimals = decimals2int(limit_decimals_char);
+ split_freq(limit_mhz_char, limit_decimals_char, r);
+ ulimit_mhz = atoi(limit_mhz_char);
+ ulimit_decimals = decimals2int(limit_decimals_char);
- for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for N+*N */
- if (digitbuf[i] == '*') {
- j++;
- continue;
+ if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
+ if(radio_mhz == llimit_mhz){ /* CASE 1: TX freq is in llimit mhz portion of band */
+ if(radio_decimals >= llimit_decimals){ /* Cannot be below llimit decimals */
+ if(llimit_mhz == ulimit_mhz){ /* If bandwidth < 1Mhz, check ulimit decimals */
+ if(radio_decimals <= ulimit_decimals){
+ rv=1;
+ break;
+ }
+ else{
+ if(debug > 3)
+ ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
+ rv=0;
+ break;
+ }
+ }
+ else{
+ rv=1;
+ break;
+ }
+ }
+ else{ /* Is below llimit decimals */
+ if(debug > 3)
+ ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
+ rv=0;
+ break;
+ }
}
- if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
- return DC_ERROR;
- else {
- if (j)
- l++;
- else
- k++;
- }
- }
- if ((j > 1) || (k > 3) || (l > 1))
- return DC_ERROR; /* &$@^! */
- i = strlen(digitbuf) - 1;
- if ((j != 1) || (k < 2)|| (l != 1))
- break; /* Not yet */
- ast_debug(1, "PL digits entered %s\n", digitbuf);
-
- ast_copy_string(tmp, digitbuf, sizeof(tmp));
- /* see if we have at least 1 */
- s = strchr(tmp, '*');
- if (s)
- *s = '.';
- ast_copy_string(savestr, myrpt->rxpl, sizeof(savestr));
- ast_copy_string(myrpt->rxpl, tmp, sizeof(myrpt->rxpl));
-
- if (setrem(myrpt) == -1) {
- ast_copy_string(myrpt->rxpl, savestr, sizeof(myrpt->rxpl));
- return DC_ERROR;
- }
-
- return DC_COMPLETE;
- case 4: /* set tx PL tone */
- for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for N+*N */
- if (digitbuf[i] == '*') {
- j++;
- continue;
+ else if(radio_mhz == ulimit_mhz){ /* CASE 2: TX freq not in llimit mhz portion of band */
+ if(radio_decimals <= ulimit_decimals){
+ if(debug > 3)
+ ast_log(LOG_NOTICE, "radio_decimals <= ulimit_decimals\n");
+ rv=1;
+ break;
+ }
+ else{ /* Is above ulimit decimals */
+ if(debug > 3)
+ ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
+ rv=0;
+ break;
+ }
}
- if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
- return DC_ERROR;
- else {
- if (j)
- l++;
- else
- k++;
- }
- }
- if ((j > 1) || (k > 3) || (l > 1))
- return DC_ERROR; /* &$@^! */
- i = strlen(digitbuf) - 1;
- if ((j != 1) || (k < 2)|| (l != 1))
- break; /* Not yet */
- ast_debug(1, "PL digits entered %s\n", digitbuf);
-
- ast_copy_string(tmp, digitbuf, sizeof(tmp));
- /* see if we have at least 1 */
- s = strchr(tmp, '*');
- if (s)
- *s = '.';
- ast_copy_string(savestr, myrpt->txpl, sizeof(savestr));
- ast_copy_string(myrpt->txpl, tmp, sizeof(myrpt->txpl));
-
- if (setrem(myrpt) == -1) {
- ast_copy_string(myrpt->txpl, savestr, sizeof(myrpt->txpl));
- return DC_ERROR;
+ else /* CASE 3: TX freq within a multi-Mhz band and ok */
+ if(debug > 3)
+ ast_log(LOG_NOTICE, "Valid TX freq within a multi-Mhz band and ok.\n");
+ rv=1;
+ break;
}
+ }
+ if(debug > 3)
+ ast_log(LOG_NOTICE, "rv=%i\n",rv);
- return DC_COMPLETE;
+ return rv;
+}
- case 6: /* MODE (FM,USB,LSB,AM) */
- if (strlen(digitbuf) < 1)
- break;
- if (!multimode)
- return DC_ERROR; /* Multimode radios only */
+/*
+* Dispatch to correct frequency bumping function
+*/
- switch (*digitbuf) {
- case '1':
- split_freq(&mhz, &decimals, myrpt->freq);
- if (mhz < 29) /* No FM allowed below 29MHz! */
- return DC_ERROR;
- myrpt->remmode = REM_MODE_FM;
- res = rmt_saycharstr(myrpt, mychannel, 1000, "FM");
- break;
+static int multimode_bump_freq(struct rpt *myrpt, int interval)
+{
+ if(!strcmp(myrpt->remoterig, remote_rig_ft897))
+ return multimode_bump_freq_ft897(myrpt, interval);
+ else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
+ return multimode_bump_freq_ic706(myrpt, interval);
+ else
+ return -1;
+}
- case '2':
- myrpt->remmode = REM_MODE_USB;
- res = rmt_saycharstr(myrpt, mychannel, 1000, "USB");
- break;
- case '3':
- myrpt->remmode = REM_MODE_LSB;
- res = rmt_saycharstr(myrpt, mychannel, 1000, "LSB");
- break;
+/*
+* Queue announcment that scan has been stopped
+*/
- case '4':
- myrpt->remmode = REM_MODE_AM;
- res = rmt_saycharstr(myrpt, mychannel, 1000, "AM");
- break;
+static void stop_scan(struct rpt *myrpt)
+{
+ myrpt->hfscanstop = 1;
+ rpt_telemetry(myrpt,SCAN,0);
+}
- default:
- return DC_ERROR;
- }
- if (res)
- return DC_ERROR;
+/*
+* This is called periodically when in scan mode
+*/
- if (setrem(myrpt))
- return DC_ERROR;
- return DC_COMPLETE;
- case 100: /* other stuff */
- case 101:
- case 102:
- case 103:
- case 104:
- case 105:
- case 106:
- res = rmt_telem_start(myrpt, mychannel, 1000);
- switch (myatoi(param)) { /* Quick commands requiring a setrem call */
- case 100: /* RX PL Off */
- myrpt->rxplon = 0;
- if (!res)
- res = sayfile(mychannel, "rpt/rxpl");
- if (!res)
- sayfile(mychannel, "rpt/off");
- break;
+static int service_scan(struct rpt *myrpt)
+{
+ int res, interval;
+ char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
- case 101: /* RX PL On */
- myrpt->rxplon = 1;
- if (!res)
- res = sayfile(mychannel, "rpt/rxpl");
- if (!res)
- sayfile(mychannel, "rpt/on");
+ switch(myrpt->hfscanmode){
+
+ case HF_SCAN_DOWN_SLOW:
+ interval = -10; /* 100Hz /sec */
break;
- case 102: /* TX PL Off */
- myrpt->txplon = 0;
- if (!res)
- res = sayfile(mychannel, "rpt/txpl");
- if (!res)
- sayfile(mychannel, "rpt/off");
+ case HF_SCAN_DOWN_QUICK:
+ interval = -50; /* 500Hz /sec */
break;
- case 103: /* TX PL On */
- myrpt->txplon = 1;
- if (!res)
- res = sayfile(mychannel, "rpt/txpl");
- if (!res)
- sayfile(mychannel, "rpt/on");
+ case HF_SCAN_DOWN_FAST:
+ interval = -200; /* 2KHz /sec */
break;
- case 104: /* Low Power */
- myrpt->powerlevel = REM_LOWPWR;
- if (!res)
- res = sayfile(mychannel, "rpt/lopwr");
+ case HF_SCAN_UP_SLOW:
+ interval = 10; /* 100Hz /sec */
break;
- case 105: /* Medium Power */
- myrpt->powerlevel = REM_MEDPWR;
- if (!res)
- res = sayfile(mychannel, "rpt/medpwr");
+ case HF_SCAN_UP_QUICK:
+ interval = 50; /* 500 Hz/sec */
break;
- case 106: /* Hi Power */
- myrpt->powerlevel = REM_HIPWR;
- if (!res)
- res = sayfile(mychannel, "rpt/hipwr");
+ case HF_SCAN_UP_FAST:
+ interval = 200; /* 2KHz /sec */
break;
default:
- if (!res)
- rmt_telem_finish(myrpt, mychannel);
- return DC_ERROR;
- }
- if (!res)
- res = rmt_telem_finish(myrpt, mychannel);
- if (res)
- return DC_ERROR;
+ myrpt->hfscanmode = 0; /* Huh? */
+ return -1;
+ }
- if (setrem(myrpt) == -1)
- return DC_ERROR;
- return DC_COMPLETE;
+ res = split_freq(mhz, decimals, myrpt->freq);
+
+ if(!res){
+ k100 =decimals[0];
+ k10 = decimals[1];
+ res = multimode_bump_freq(myrpt, interval);
+ }
- case 107: /* Bump down 20Hz */
- multimode_bump_freq(myrpt, -20);
- return DC_COMPLETE;
+ if(!res)
+ res = split_freq(mhz, decimals, myrpt->freq);
- case 108: /* Bump down 100Hz */
- multimode_bump_freq(myrpt, -100);
- return DC_COMPLETE;
- case 109: /* Bump down 500Hz */
- multimode_bump_freq(myrpt, -500);
- return DC_COMPLETE;
+ if(res){
+ myrpt->hfscanmode = 0;
+ myrpt->hfscanstatus = -2;
+ return -1;
+ }
- case 110: /* Bump up 20Hz */
- multimode_bump_freq(myrpt, 20);
- return DC_COMPLETE;
-
- case 111: /* Bump up 100Hz */
- multimode_bump_freq(myrpt, 100);
- return DC_COMPLETE;
+ /* Announce 10KHz boundaries */
+ if(k10 != decimals[1]){
+ int myhund = (interval < 0) ? k100 : decimals[0];
+ int myten = (interval < 0) ? k10 : decimals[1];
+ myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
+ } else myrpt->hfscanstatus = 0;
+ return res;
- case 112: /* Bump up 500Hz */
- multimode_bump_freq(myrpt, 500);
- return DC_COMPLETE;
+}
+/*
+ retrieve memory setting and set radio
+*/
+static int get_mem_set(struct rpt *myrpt, char *digitbuf)
+{
+ int res=0;
+ if(debug)ast_log(LOG_NOTICE," digitbuf=%s\n", digitbuf);
+ res = retreive_memory(myrpt, digitbuf);
+ if(!res)res=setrem(myrpt);
+ if(debug)ast_log(LOG_NOTICE," freq=%s res=%i\n", myrpt->freq, res);
+ return res;
+}
+/*
+ steer the radio selected channel to either one programmed into the radio
+ or if the radio is VFO agile, to an rpt.conf memory location.
+*/
+static int channel_steer(struct rpt *myrpt, char *data)
+{
+ int res=0;
- case 113:
- case 114:
- case 115:
- case 116:
- case 117:
- case 118:
- myrpt->remotetx = 0;
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
- if (!myrpt->remoterx)
- ast_indicate(mychannel, AST_CONTROL_RADIO_KEY);
- if (ast_safe_sleep(mychannel, 1000) == -1)
- return DC_ERROR;
+ if(debug)ast_log(LOG_NOTICE,"remoterig=%s, data=%s\n",myrpt->remoterig,data);
+ if (!myrpt->remoterig) return(0);
+ if(data<=0)
+ {
+ res=-1;
+ }
+ else
+ {
+ myrpt->nowchan=strtod(data,NULL);
+ if(!strcmp(myrpt->remoterig, remote_rig_ppp16))
+ {
+ char string[16];
+ sprintf(string,"SETCHAN %d ",myrpt->nowchan);
+ send_usb_txt(myrpt,string);
+ }
+ else
+ {
+ if(get_mem_set(myrpt, data))res=-1;
+ }
+ }
+ if(debug)ast_log(LOG_NOTICE,"nowchan=%i res=%i\n",myrpt->nowchan, res);
+ return res;
+}
+/*
+*/
+static int channel_revert(struct rpt *myrpt)
+{
+ int res=0;
+ if(debug)ast_log(LOG_NOTICE,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt->remoterig,myrpt->nowchan,myrpt->waschan);
+ if (!myrpt->remoterig) return(0);
+ if(myrpt->nowchan!=myrpt->waschan)
+ {
+ char data[8];
+ if(debug)ast_log(LOG_NOTICE,"reverting.\n");
+ sprintf(data,"%02d",myrpt->waschan);
+ myrpt->nowchan=myrpt->waschan;
+ channel_steer(myrpt,data);
+ res=1;
+ }
+ return(res);
+}
+/*
+* Remote base function
+*/
- switch (myatoi(param)) {
- case 113: /* Scan down slow */
- res = sayfile(mychannel, "rpt/down");
- if (!res)
- res = sayfile(mychannel, "rpt/slow");
- if (!res) {
- myrpt->scantimer = REM_SCANTIME;
- myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
- }
- break;
+static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
+{
+ char *s,*s1,*s2;
+ int i,j,p,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode;
+ char multimode = 0;
+ char oc,*cp,*cp1,*cp2;
+ char tmp[20], freq[20] = "", savestr[20] = "";
+ char mhz[MAXREMSTR], decimals[MAXREMSTR];
- case 114: /* Scan down quick */
- res = sayfile(mychannel, "rpt/down");
- if (!res)
- res = sayfile(mychannel, "rpt/quick");
- if (!res) {
- myrpt->scantimer = REM_SCANTIME;
- myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
- }
- break;
+ if(debug > 6) {
+ ast_log(LOG_NOTICE,"%s param=%s digitbuf=%s source=%i\n",myrpt->name,param,digitbuf,command_source);
+ }
- case 115: /* Scan down fast */
- res = sayfile(mychannel, "rpt/down");
- if (!res)
- res = sayfile(mychannel, "rpt/fast");
- if (!res) {
- myrpt->scantimer = REM_SCANTIME;
- myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
- }
- break;
+ if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
+ return DC_ERROR;
+
+ p = myatoi(param);
- case 116: /* Scan up slow */
- res = sayfile(mychannel, "rpt/up");
- if (!res)
- res = sayfile(mychannel, "rpt/slow");
- if (!res) {
- myrpt->scantimer = REM_SCANTIME;
- myrpt->hfscanmode = HF_SCAN_UP_SLOW;
- }
- break;
+ if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
+ (!myrpt->loginlevel[0])) return DC_ERROR;
+ multimode = multimode_capable(myrpt);
- case 117: /* Scan up quick */
- res = sayfile(mychannel, "rpt/up");
- if (!res)
- res = sayfile(mychannel, "rpt/quick");
- if (!res) {
- myrpt->scantimer = REM_SCANTIME;
- myrpt->hfscanmode = HF_SCAN_UP_QUICK;
+ switch(p){
+
+ case 1: /* retrieve memory */
+ if(strlen(digitbuf) < 2) /* needs 2 digits */
+ break;
+
+ for(i = 0 ; i < 2 ; i++){
+ if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
+ return DC_ERROR;
+ }
+ r=get_mem_set(myrpt, digitbuf);
+ if (r < 0){
+ rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
+ return DC_COMPLETE;
+ }
+ else if (r > 0){
+ return DC_ERROR;
+ }
+ return DC_COMPLETE;
+
+ case 2: /* set freq and offset */
+
+
+ for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for M+*K+*O or M+*H+* depending on mode */
+ if(digitbuf[i] == '*'){
+ j++;
+ continue;
+ }
+ if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
+ goto invalid_freq;
+ else{
+ if(j == 0)
+ l++; /* # of digits before first * */
+ if(j == 1)
+ k++; /* # of digits after first * */
+ }
+ }
+
+ i = strlen(digitbuf) - 1;
+ if(multimode){
+ if((j > 2) || (l > 3) || (k > 6))
+ goto invalid_freq; /* &^@#! */
+ }
+ else{
+ if((j > 2) || (l > 4) || (k > 3))
+ goto invalid_freq; /* &^@#! */
}
- break;
- case 118: /* Scan up fast */
- res = sayfile(mychannel, "rpt/up");
- if (!res)
- res = sayfile(mychannel, "rpt/fast");
- if (!res) {
- myrpt->scantimer = REM_SCANTIME;
- myrpt->hfscanmode = HF_SCAN_UP_FAST;
+ /* Wait for M+*K+* */
+
+ if(j < 2)
+ break; /* Not yet */
+
+ /* We have a frequency */
+
+ strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
+
+ s = tmp;
+ s1 = strsep(&s, "*"); /* Pick off MHz */
+ s2 = strsep(&s,"*"); /* Pick off KHz and Hz */
+ ls2 = strlen(s2);
+
+ switch(ls2){ /* Allow partial entry of khz and hz digits for laziness support */
+ case 1:
+ ht = 0;
+ k = 100 * atoi(s2);
+ break;
+
+ case 2:
+ ht = 0;
+ k = 10 * atoi(s2);
+ break;
+
+ case 3:
+ if(!multimode){
+ if((s2[2] != '0')&&(s2[2] != '5'))
+ goto invalid_freq;
+ }
+ ht = 0;
+ k = atoi(s2);
+ break;
+ case 4:
+ k = atoi(s2)/10;
+ ht = 10 * (atoi(s2+(ls2-1)));
+ break;
+
+ case 5:
+ k = atoi(s2)/100;
+ ht = (atoi(s2+(ls2-2)));
+ break;
+
+ default:
+ goto invalid_freq;
}
- break;
- }
- rmt_telem_finish(myrpt, mychannel);
- return DC_COMPLETE;
+ /* Check frequency for validity and establish a default mode */
+
+ snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
- case 119: /* Tune Request */
- myrpt->tunerequest = 1;
- return DC_COMPLETE;
+ if(debug)
+ ast_log(LOG_NOTICE, "New frequency: %s\n", freq);
+
+ split_freq(mhz, decimals, freq);
+ m = atoi(mhz);
+ d = atoi(decimals);
- case 5: /* Long Status */
- case 140: /* Short Status */
- res = rmt_telem_start(myrpt, mychannel, 1000);
+ if(check_freq(myrpt, m, d, &defmode)) /* Check to see if frequency entered is legit */
+ goto invalid_freq;
- res = sayfile(mychannel, "rpt/node");
- if (!res)
- res = saycharstr(mychannel, myrpt->name);
- if (!res)
- res = sayfile(mychannel, "rpt/frequency");
- if (!res)
- res = split_freq(&mhz, &decimals, myrpt->freq);
- if (!res) {
- if (mhz < 100)
- res = saynum(mychannel, mhz);
- else
- res = saydigits(mychannel, mhz);
- }
- if (!res)
- res = sayfile(mychannel, "letters/dot");
- if (!res)
- res = saydigits(mychannel, decimals);
- if (res) {
- rmt_telem_finish(myrpt, mychannel);
- return DC_ERROR;
- }
- if (myrpt->remmode == REM_MODE_FM) { /* Mode FM? */
- switch (myrpt->offset) {
- case REM_MINUS:
- res = sayfile(mychannel, "rpt/minus");
- break;
+ if((defmode == REM_MODE_FM) && (digitbuf[i] == '*')) /* If FM, user must enter and additional offset digit */
+ break; /* Not yet */
- case REM_SIMPLEX:
- res = sayfile(mychannel, "rpt/simplex");
- break;
- case REM_PLUS:
- res = sayfile(mychannel, "rpt/plus");
- break;
+ offset = REM_SIMPLEX; /* Assume simplex */
- default:
- return DC_ERROR;
+ if(defmode == REM_MODE_FM){
+ oc = *s; /* Pick off offset */
+
+ if (oc){
+ switch(oc){
+ case '1':
+ offset = REM_MINUS;
+ break;
+
+ case '2':
+ offset = REM_SIMPLEX;
+ break;
+
+ case '3':
+ offset = REM_PLUS;
+ break;
+
+ default:
+ goto invalid_freq;
+ }
+ }
+ }
+ offsave = myrpt->offset;
+ modesave = myrpt->remmode;
+ strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
+ strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
+ myrpt->offset = offset;
+ myrpt->remmode = defmode;
+
+ if (setrem(myrpt) == -1){
+ myrpt->offset = offsave;
+ myrpt->remmode = modesave;
+ strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
+ goto invalid_freq;
+ }
+
+ return DC_COMPLETE;
+invalid_freq:
+ rpt_telemetry(myrpt,INVFREQ,NULL);
+ return DC_ERROR;
+
+ case 3: /* set rx PL tone */
+ for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N */
+ if(digitbuf[i] == '*'){
+ j++;
+ continue;
+ }
+ if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
+ return DC_ERROR;
+ else{
+ if(j)
+ l++;
+ else
+ k++;
+ }
}
- } else { /* Must be USB, LSB, or AM */
- switch (myrpt->remmode) {
- case REM_MODE_USB:
- res = saycharstr(mychannel, "USB");
- break;
- case REM_MODE_LSB:
- res = saycharstr(mychannel, "LSB");
- break;
- case REM_MODE_AM:
- res = saycharstr(mychannel, "AM");
- break;
- default:
+ if((j > 1) || (k > 3) || (l > 1))
+ return DC_ERROR; /* &$@^! */
+ i = strlen(digitbuf) - 1;
+ if((j != 1) || (k < 2)|| (l != 1))
+ break; /* Not yet */
+ if(debug)
+ printf("PL digits entered %s\n", digitbuf);
+
+ strncpy(tmp, digitbuf, sizeof(tmp) - 1);
+ /* see if we have at least 1 */
+ s = strchr(tmp,'*');
+ if(s)
+ *s = '.';
+ strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
+ strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
+ if(!strcmp(myrpt->remoterig, remote_rig_rbi))
+ {
+ strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
+ }
+ if (setrem(myrpt) == -1){
+ strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
return DC_ERROR;
}
- }
+ return DC_COMPLETE;
+
+ case 4: /* set tx PL tone */
+ /* cant set tx tone on RBI (rx tone does both) */
+ if(!strcmp(myrpt->remoterig, remote_rig_rbi))
+ return DC_ERROR;
+ /* eventually for the ic706 instead of just throwing the exception
+ we can check if we are in encode only mode and allow the tx
+ ctcss code to be changed. but at least the warning message is
+ issued for now.
+ */
+ if(!strcmp(myrpt->remoterig, remote_rig_ic706))
+ {
+ if(debug)
+ ast_log(LOG_WARNING,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
+ return DC_ERROR;
+ }
+ for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N */
+ if(digitbuf[i] == '*'){
+ j++;
+ continue;
+ }
+ if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
+ return DC_ERROR;
+ else{
+ if(j)
+ l++;
+ else
+ k++;
+ }
+ }
+ if((j > 1) || (k > 3) || (l > 1))
+ return DC_ERROR; /* &$@^! */
+ i = strlen(digitbuf) - 1;
+ if((j != 1) || (k < 2)|| (l != 1))
+ break; /* Not yet */
+ if(debug)
+ printf("PL digits entered %s\n", digitbuf);
+
+ strncpy(tmp, digitbuf, sizeof(tmp) - 1);
+ /* see if we have at least 1 */
+ s = strchr(tmp,'*');
+ if(s)
+ *s = '.';
+ strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
+ strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
+
+ if (setrem(myrpt) == -1){
+ strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
+ return DC_ERROR;
+ }
+ return DC_COMPLETE;
+
- if (res == -1) {
- rmt_telem_finish(myrpt, mychannel);
- return DC_ERROR;
- }
+ case 6: /* MODE (FM,USB,LSB,AM) */
+ if(strlen(digitbuf) < 1)
+ break;
+
+ if(!multimode)
+ return DC_ERROR; /* Multimode radios only */
+
+ switch(*digitbuf){
+ case '1':
+ split_freq(mhz, decimals, myrpt->freq);
+ m=atoi(mhz);
+ if(m < 29) /* No FM allowed below 29MHz! */
+ return DC_ERROR;
+ myrpt->remmode = REM_MODE_FM;
+
+ rpt_telemetry(myrpt,REMMODE,NULL);
+ break;
+
+ case '2':
+ myrpt->remmode = REM_MODE_USB;
+ rpt_telemetry(myrpt,REMMODE,NULL);
+ break;
+
+ case '3':
+ myrpt->remmode = REM_MODE_LSB;
+ rpt_telemetry(myrpt,REMMODE,NULL);
+ break;
+
+ case '4':
+ myrpt->remmode = REM_MODE_AM;
+ rpt_telemetry(myrpt,REMMODE,NULL);
+ break;
+
+ default:
+ return DC_ERROR;
+ }
- if (myatoi(param) == 140) { /* Short status? */
- if (!res)
- res = rmt_telem_finish(myrpt, mychannel);
- if (res)
+ if(setrem(myrpt))
+ return DC_ERROR;
+ return DC_COMPLETEQUIET;
+ case 99:
+ /* cant log in when logged in */
+ if (myrpt->loginlevel[0])
+ return DC_ERROR;
+ *myrpt->loginuser = 0;
+ myrpt->loginlevel[0] = 0;
+ cp = ast_strdup(param);
+ cp1 = strchr(cp,',');
+ ast_mutex_lock(&myrpt->lock);
+ if (cp1)
+ {
+ *cp1 = 0;
+ cp2 = strchr(cp1 + 1,',');
+ if (cp2)
+ {
+ *cp2 = 0;
+ strncpy(myrpt->loginlevel,cp2 + 1,
+ sizeof(myrpt->loginlevel) - 1);
+ }
+ strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
+ ast_mutex_unlock(&myrpt->lock);
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ sprintf(str,"LOGIN,%s,%s",
+ myrpt->loginuser,myrpt->loginlevel);
+ donodelog(myrpt,str);
+ }
+ if (debug)
+ printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
+ rpt_telemetry(myrpt,REMLOGIN,NULL);
+ }
+ ast_free(cp);
+ return DC_COMPLETEQUIET;
+ case 100: /* RX PL Off */
+ myrpt->rxplon = 0;
+ setrem(myrpt);
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 101: /* RX PL On */
+ myrpt->rxplon = 1;
+ setrem(myrpt);
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 102: /* TX PL Off */
+ myrpt->txplon = 0;
+ setrem(myrpt);
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 103: /* TX PL On */
+ myrpt->txplon = 1;
+ setrem(myrpt);
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 104: /* Low Power */
+ if(!strcmp(myrpt->remoterig, remote_rig_ic706))
+ return DC_ERROR;
+ myrpt->powerlevel = REM_LOWPWR;
+ setrem(myrpt);
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 105: /* Medium Power */
+ if(!strcmp(myrpt->remoterig, remote_rig_ic706))
+ return DC_ERROR;
+ if (ISRIG_RTX(myrpt->remoterig)) return DC_ERROR;
+ myrpt->powerlevel = REM_MEDPWR;
+ setrem(myrpt);
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 106: /* Hi Power */
+ if(!strcmp(myrpt->remoterig, remote_rig_ic706))
return DC_ERROR;
+ myrpt->powerlevel = REM_HIPWR;
+ setrem(myrpt);
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 107: /* Bump down 20Hz */
+ multimode_bump_freq(myrpt, -20);
return DC_COMPLETE;
- }
-
- switch (myrpt->powerlevel) {
- case REM_LOWPWR:
- res = sayfile(mychannel, "rpt/lopwr") ;
- break;
- case REM_MEDPWR:
- res = sayfile(mychannel, "rpt/medpwr");
- break;
- case REM_HIPWR:
- res = sayfile(mychannel, "rpt/hipwr");
+ case 108: /* Bump down 100Hz */
+ multimode_bump_freq(myrpt, -100);
+ return DC_COMPLETE;
+ case 109: /* Bump down 500Hz */
+ multimode_bump_freq(myrpt, -500);
+ return DC_COMPLETE;
+ case 110: /* Bump up 20Hz */
+ multimode_bump_freq(myrpt, 20);
+ return DC_COMPLETE;
+ case 111: /* Bump up 100Hz */
+ multimode_bump_freq(myrpt, 100);
+ return DC_COMPLETE;
+ case 112: /* Bump up 500Hz */
+ multimode_bump_freq(myrpt, 500);
+ return DC_COMPLETE;
+ case 113: /* Scan down slow */
+ myrpt->scantimer = REM_SCANTIME;
+ myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 114: /* Scan down quick */
+ myrpt->scantimer = REM_SCANTIME;
+ myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 115: /* Scan down fast */
+ myrpt->scantimer = REM_SCANTIME;
+ myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 116: /* Scan up slow */
+ myrpt->scantimer = REM_SCANTIME;
+ myrpt->hfscanmode = HF_SCAN_UP_SLOW;
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 117: /* Scan up quick */
+ myrpt->scantimer = REM_SCANTIME;
+ myrpt->hfscanmode = HF_SCAN_UP_QUICK;
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 118: /* Scan up fast */
+ myrpt->scantimer = REM_SCANTIME;
+ myrpt->hfscanmode = HF_SCAN_UP_FAST;
+ rpt_telemetry(myrpt,REMXXX,(void *)p);
+ return DC_COMPLETEQUIET;
+ case 119: /* Tune Request */
+ if(debug > 3)
+ ast_log(LOG_NOTICE,"TUNE REQUEST\n");
+ /* if not currently going, and valid to do */
+ if((!myrpt->tunerequest) &&
+ ((!strcmp(myrpt->remoterig, remote_rig_ft897) ||
+ !strcmp(myrpt->remoterig, remote_rig_ic706)) )) {
+ myrpt->remotetx = 0;
+ ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
+ myrpt->tunerequest = 1;
+ rpt_telemetry(myrpt,TUNE,NULL);
+ return DC_COMPLETEQUIET;
+ }
+ return DC_ERROR;
+ case 5: /* Long Status */
+ rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
+ return DC_COMPLETEQUIET;
+ case 140: /* Short Status */
+ rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
+ return DC_COMPLETEQUIET;
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ do_dtmf_local(myrpt,remdtmfstr[p - 200]);
+ return DC_COMPLETEQUIET;
+ default:
break;
- }
- if (res || (sayfile(mychannel, "rpt/rxpl") == -1) ||
- (sayfile(mychannel, "rpt/frequency") == -1) ||
- (saycharstr(mychannel, myrpt->rxpl) == -1) ||
- (sayfile(mychannel, "rpt/txpl") == -1) ||
- (sayfile(mychannel, "rpt/frequency") == -1) ||
- (saycharstr(mychannel, myrpt->txpl) == -1) ||
- (sayfile(mychannel, "rpt/txpl") == -1) ||
- (sayfile(mychannel, ((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1) ||
- (sayfile(mychannel, "rpt/rxpl") == -1) ||
- (sayfile(mychannel, ((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1))
- {
- rmt_telem_finish(myrpt, mychannel);
- return DC_ERROR;
- }
- if (!res)
- res = rmt_telem_finish(myrpt, mychannel);
- if (res)
- return DC_ERROR;
-
- return DC_COMPLETE;
- default:
- return DC_ERROR;
}
-
return DC_INDETERMINATE;
}
-static int handle_remote_dtmf_digit(struct rpt *myrpt, char c, char *keyed, int phonemode)
+
+static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
{
- time_t now;
- int ret, res = 0, src;
+time_t now;
+int ret,res = 0,src;
+ if(debug > 6)
+ ast_log(LOG_NOTICE,"c=%c phonemode=%i dtmfidx=%i\n",c,phonemode,myrpt->dtmfidx);
+
+ time(&myrpt->last_activity_time);
/* Stop scan mode if in scan mode */
- if (myrpt->hfscanmode) {
- stop_scan(myrpt, 0);
+ if(myrpt->hfscanmode){
+ stop_scan(myrpt);
return 0;
}
time(&now);
/* if timed-out */
- if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now) {
+ if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
+ {
myrpt->dtmfidx = -1;
myrpt->dtmfbuf[0] = 0;
myrpt->dtmf_time_rem = 0;
}
/* if decode not active */
- if (myrpt->dtmfidx == -1) {
+ if (myrpt->dtmfidx == -1)
+ {
/* if not lead-in digit, dont worry */
if (c != myrpt->p.funcchar)
+ {
+ if (!myrpt->p.propagate_dtmf)
+ {
+ rpt_mutex_lock(&myrpt->lock);
+ do_dtmf_local(myrpt,c);
+ rpt_mutex_unlock(&myrpt->lock);
+ }
return 0;
+ }
myrpt->dtmfidx = 0;
myrpt->dtmfbuf[0] = 0;
myrpt->dtmf_time_rem = now;
return 0;
}
/* if too many in buffer, start over */
- if (myrpt->dtmfidx >= MAXDTMF) {
+ if (myrpt->dtmfidx >= MAXDTMF)
+ {
myrpt->dtmfidx = 0;
myrpt->dtmfbuf[0] = 0;
myrpt->dtmf_time_rem = now;
}
- if (c == myrpt->p.funcchar) {
+ if (c == myrpt->p.funcchar)
+ {
/* if star at beginning, or 2 together, erase buffer */
- if ((myrpt->dtmfidx < 1) || (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar)) {
+ if ((myrpt->dtmfidx < 1) ||
+ (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
+ {
myrpt->dtmfidx = 0;
myrpt->dtmfbuf[0] = 0;
myrpt->dtmf_time_rem = now;
@@ -5330,41 +10182,48 @@ static int handle_remote_dtmf_digit(struct rpt *myrpt, char c, char *keyed, int
src = SOURCE_RMT;
- if (phonemode > 1)
- src = SOURCE_DPHONE;
- else if (phonemode)
- src = SOURCE_PHONE;
+ if (phonemode == 2) src = SOURCE_DPHONE;
+ else if (phonemode) src = SOURCE_PHONE;
+ else if (phonemode == 4) src = SOURCE_ALT;
ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
- switch(ret) {
- case DC_INDETERMINATE:
- res = 0;
- break;
- case DC_DOKEY:
- if (keyed)
- *keyed = 1;
- res = 0;
- break;
- case DC_REQ_FLUSH:
- myrpt->dtmfidx = 0;
- myrpt->dtmfbuf[0] = 0;
- res = 0;
- break;
- case DC_COMPLETE:
- myrpt->totalexecdcommands++;
- myrpt->dailyexecdcommands++;
- ast_copy_string(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF);
- myrpt->dtmfbuf[0] = 0;
- myrpt->dtmfidx = -1;
- myrpt->dtmf_time_rem = 0;
- res = 1;
- break;
- case DC_ERROR:
- default:
- myrpt->dtmfbuf[0] = 0;
- myrpt->dtmfidx = -1;
- myrpt->dtmf_time_rem = 0;
- res = 0;
+ switch(ret){
+
+ case DC_INDETERMINATE:
+ res = 0;
+ break;
+
+ case DC_DOKEY:
+ if (keyed) *keyed = 1;
+ res = 0;
+ break;
+
+ case DC_REQ_FLUSH:
+ myrpt->dtmfidx = 0;
+ myrpt->dtmfbuf[0] = 0;
+ res = 0;
+ break;
+
+
+ case DC_COMPLETE:
+ res = 1;
+ case DC_COMPLETEQUIET:
+ myrpt->totalexecdcommands++;
+ myrpt->dailyexecdcommands++;
+ strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
+ myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
+ myrpt->dtmfbuf[0] = 0;
+ myrpt->dtmfidx = -1;
+ myrpt->dtmf_time_rem = 0;
+ break;
+
+ case DC_ERROR:
+ default:
+ myrpt->dtmfbuf[0] = 0;
+ myrpt->dtmfidx = -1;
+ myrpt->dtmf_time_rem = 0;
+ res = 0;
+ break;
}
return res;
@@ -5372,74 +10231,110 @@ static int handle_remote_dtmf_digit(struct rpt *myrpt, char c, char *keyed, int
static int handle_remote_data(struct rpt *myrpt, char *str)
{
- char cmd[300], dest[300], src[300], c;
- int seq, res;
-
- if (!strcmp(str, discstr))
+char tmp[300],cmd[300],dest[300],src[300],c;
+int seq,res;
+
+ /* put string in our buffer */
+ strncpy(tmp,str,sizeof(tmp) - 1);
+ if (!strcmp(tmp,discstr)) return 0;
+ if (!strcmp(tmp,newkeystr))
+ {
+ myrpt->newkey = 1;
+ return 0;
+ }
+
+#ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
+ if (tmp[0] == 'I')
+ {
+ if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
+ {
+ ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
+ return 0;
+ }
+ mdc1200_notify(myrpt,src,seq);
return 0;
- if (sscanf(str, "%s %s %s %d %c", cmd, dest, src, &seq, &c) != 5) {
- ast_log(LOG_WARNING, "Unable to parse link string %s\n", str);
+ }
+#endif
+ if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
+ {
+ ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
return 0;
}
- if (strcmp(cmd, "D")) {
- ast_log(LOG_WARNING, "Unable to parse link string %s\n", str);
+ if (strcmp(cmd,"D"))
+ {
+ ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
return 0;
}
/* if not for me, ignore */
- if (strcmp(dest, myrpt->name))
- return 0;
- res = handle_remote_dtmf_digit(myrpt, c, NULL, 0);
+ if (strcmp(dest,myrpt->name)) return 0;
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ sprintf(str,"DTMF,%c",c);
+ donodelog(myrpt,str);
+ }
+ c = func_xlat(myrpt,c,&myrpt->p.outxlat);
+ if (!c) return(0);
+ res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
if (res != 1)
return res;
- myrpt->remotetx = 0;
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
- if (!myrpt->remoterx) {
- ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_KEY);
- }
- if (ast_safe_sleep(myrpt->remchannel, 1000) == -1)
- return -1;
- res = telem_lookup(myrpt, myrpt->remchannel, myrpt->name, "functcomplete");
- rmt_telem_finish(myrpt, myrpt->remchannel);
- return res;
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ return 0;
}
static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
{
- int res;
+int res;
- if (keyed && *keyed && (c == myrpt->p.endchar)) {
- *keyed = 0;
- return DC_INDETERMINATE;
+
+ if(phonemode == 3) /* simplex phonemode, funcchar key/unkey toggle */
+ {
+ if (keyed && *keyed && ((c == myrpt->p.funcchar) || (c == myrpt->p.endchar)))
+ {
+ *keyed = 0; /* UNKEY */
+ return 0;
+ }
+ else if (keyed && !*keyed && (c = myrpt->p.funcchar))
+ {
+ *keyed = 1; /* KEY */
+ return 0;
+ }
+ }
+ else /* endchar unkey */
+ {
+
+ if (keyed && *keyed && (c == myrpt->p.endchar))
+ {
+ *keyed = 0;
+ return DC_INDETERMINATE;
+ }
}
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
- res = handle_remote_dtmf_digit(myrpt, c, keyed, phonemode);
+ sprintf(str,"DTMF(P),%c",c);
+ donodelog(myrpt,str);
+ }
+ res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
if (res != 1)
return res;
- myrpt->remotetx = 0;
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
- if (!myrpt->remoterx) {
- ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_KEY);
- }
- if (ast_safe_sleep(myrpt->remchannel, 1000) == -1)
- return -1;
- res = telem_lookup(myrpt, myrpt->remchannel, myrpt->name, "functcomplete");
- rmt_telem_finish(myrpt, myrpt->remchannel);
- return res;
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ return 0;
}
static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
{
- const char *val;
- char *s, *tele;
- char deststr[300] = "";
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(channel);
- AST_APP_ARG(extra);
- );
-
- val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, l->name);
- if (!val) {
- ast_log(LOG_ERROR, "attempt_reconnect: cannot find node %s\n", l->name);
+ char *val, *s, *s1, *s2, *tele;
+ char tmp[300], deststr[300] = "";
+ char sx[320],*sy;
+
+
+ val = node_lookup(myrpt,l->name);
+ if (!val)
+ {
+ fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
return -1;
}
@@ -5447,165 +10342,238 @@ static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
/* remove from queue */
remque((struct qelem *) l);
rpt_mutex_unlock(&myrpt->lock);
- s = ast_strdupa(val);
- AST_STANDARD_APP_ARGS(args, s);
-
- /* XXX This section doesn't make any sense. Why not just use args.channel? XXX */
- snprintf(deststr, sizeof(deststr), "IAX2/%s", args.channel);
+ strncpy(tmp,val,sizeof(tmp) - 1);
+ s = tmp;
+ s1 = strsep(&s,",");
+ if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
+ {
+ sy = strchr(s1,'/');
+ *sy = 0;
+ sprintf(sx,"%s:4569/%s",s1,sy + 1);
+ s1 = sx;
+ }
+ s2 = strsep(&s,",");
+ snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
tele = strchr(deststr, '/');
if (!tele) {
- ast_log(LOG_ERROR, "attempt_reconnect:Dial number (%s) must be in format tech/number\n", deststr);
+ fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
return -1;
}
*tele++ = 0;
l->elaptime = 0;
l->connecttime = 0;
- l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele, NULL);
- if (l->chan) {
+ l->thisconnected = 0;
+ l->newkey = 0;
+ l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
+ if (l->chan){
ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
- ast_channel_setwhentohangup_tv(l->chan, cancel_atimeout);
+#ifndef NEW_ASTERISK
+ l->chan->whentohangup = 0;
+#endif
l->chan->appl = "Apprpt";
l->chan->data = "(Remote Rx)";
- ast_verb(3, "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
deststr, tele, l->chan->name);
- if (l->chan->cid.cid_num)
+ if(l->chan->cid.cid_num)
ast_free(l->chan->cid.cid_num);
l->chan->cid.cid_num = ast_strdup(myrpt->name);
- ast_call(l->chan, tele, 999);
+ ast_call(l->chan,tele,999);
- } else {
- ast_verb(3, "Unable to place call to %s/%s on %s\n",
- deststr, tele, l->chan->name);
+ }
+ else
+ {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
+ deststr,tele,l->chan->name);
return -1;
}
rpt_mutex_lock(&myrpt->lock);
/* put back in queue */
- insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
+ insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
rpt_mutex_unlock(&myrpt->lock);
- ast_log(LOG_NOTICE, "Reconnect Attempt to %s in process\n", l->name);
+ ast_log(LOG_WARNING,"Reconnect Attempt to %s in process\n",l->name);
+ if (!l->phonemode) send_newkey(l->chan);
return 0;
}
/* 0 return=continue, 1 return = break, -1 return = error */
-static void local_dtmf_helper(struct rpt *myrpt, char c)
+static void local_dtmf_helper(struct rpt *myrpt,char c_in)
{
- int res;
- char cmd[MAXDTMF+1] = "";
+int res;
+pthread_attr_t attr;
+char cmd[MAXDTMF+1] = "",c;
+
+
+ c = c_in & 0x7f;
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
- if (c == myrpt->p.endchar) {
+ sprintf(str,"DTMF,MAIN,%c",c);
+ donodelog(myrpt,str);
+ }
+ if (c == myrpt->p.endchar)
+ {
/* if in simple mode, kill autopatch */
- if (myrpt->p.simple && myrpt->callmode) {
+ if (myrpt->p.simple && myrpt->callmode)
+ {
+ if(debug)
+ ast_log(LOG_WARNING, "simple mode autopatch kill\n");
rpt_mutex_lock(&myrpt->lock);
myrpt->callmode = 0;
+ myrpt->macropatch=0;
+ channel_revert(myrpt);
rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, TERM, NULL);
+ rpt_telemetry(myrpt,TERM,NULL);
return;
}
rpt_mutex_lock(&myrpt->lock);
myrpt->stopgen = 1;
- if (myrpt->cmdnode[0]) {
+ if (myrpt->cmdnode[0])
+ {
myrpt->cmdnode[0] = 0;
myrpt->dtmfidx = -1;
myrpt->dtmfbuf[0] = 0;
rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, COMPLETE, NULL);
- } else
+ rpt_telemetry(myrpt,COMPLETE,NULL);
+ return;
+ }
+ else if(!myrpt->inpadtest)
+ {
+ rpt_mutex_unlock(&myrpt->lock);
+ if (myrpt->p.propagate_phonedtmf)
+ do_dtmf_phone(myrpt,NULL,c);
+ return;
+ }
+ else
rpt_mutex_unlock(&myrpt->lock);
- return;
}
rpt_mutex_lock(&myrpt->lock);
- if (myrpt->cmdnode[0]) {
+ if (myrpt->cmdnode[0])
+ {
rpt_mutex_unlock(&myrpt->lock);
- send_link_dtmf(myrpt, c);
+ send_link_dtmf(myrpt,c);
return;
}
- if (!myrpt->p.simple) {
- if (c == myrpt->p.funcchar) {
+ if (!myrpt->p.simple)
+ {
+ if ((!myrpt->inpadtest)&&(c == myrpt->p.funcchar))
+ {
myrpt->dtmfidx = 0;
myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
rpt_mutex_unlock(&myrpt->lock);
time(&myrpt->dtmf_time);
return;
- } else if ((c != myrpt->p.endchar) && (myrpt->dtmfidx >= 0)) {
+ }
+ else if (((myrpt->inpadtest)||(c != myrpt->p.endchar)) && (myrpt->dtmfidx >= 0))
+ {
time(&myrpt->dtmf_time);
+
+ if (myrpt->dtmfidx < MAXDTMF)
+ {
+ int src;
- if (myrpt->dtmfidx < MAXDTMF) {
myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
-
- ast_copy_string(cmd, myrpt->dtmfbuf, sizeof(cmd));
-
+
+ strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
+
rpt_mutex_unlock(&myrpt->lock);
- res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL);
+ src = SOURCE_RPT;
+ if (c_in & 0x80) src = SOURCE_ALT;
+ res = collect_function_digits(myrpt, cmd, src, NULL);
rpt_mutex_lock(&myrpt->lock);
- switch(res) {
- case DC_INDETERMINATE:
+ switch(res){
+ case DC_INDETERMINATE:
break;
- case DC_REQ_FLUSH:
+ case DC_REQ_FLUSH:
myrpt->dtmfidx = 0;
myrpt->dtmfbuf[0] = 0;
break;
- case DC_COMPLETE:
+ case DC_COMPLETE:
+ case DC_COMPLETEQUIET:
myrpt->totalexecdcommands++;
myrpt->dailyexecdcommands++;
- ast_copy_string(myrpt->lastdtmfcommand, cmd, MAXDTMF);
+ strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
+ myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
myrpt->dtmfbuf[0] = 0;
myrpt->dtmfidx = -1;
myrpt->dtmf_time = 0;
break;
- case DC_ERROR:
- default:
+ case DC_ERROR:
+ default:
myrpt->dtmfbuf[0] = 0;
myrpt->dtmfidx = -1;
myrpt->dtmf_time = 0;
break;
}
- if (res != DC_INDETERMINATE) {
+ if(res != DC_INDETERMINATE) {
rpt_mutex_unlock(&myrpt->lock);
return;
}
}
}
- } else /* if simple */ {
- if ((!myrpt->callmode) && (c == myrpt->p.funcchar)) {
+ }
+ else /* if simple */
+ {
+ if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
+ {
myrpt->callmode = 1;
myrpt->patchnoct = 0;
myrpt->patchquiet = 0;
myrpt->patchfarenddisconnect = 0;
myrpt->patchdialtime = 0;
- ast_copy_string(myrpt->patchcontext, myrpt->p.ourcontext, sizeof(myrpt->patchcontext));
+ strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
myrpt->cidx = 0;
myrpt->exten[myrpt->cidx] = 0;
rpt_mutex_unlock(&myrpt->lock);
- ast_pthread_create_detached(&myrpt->rpt_call_thread, NULL, rpt_call, (void *)myrpt);
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
return;
}
}
- if (myrpt->callmode == 1) {
+ if (myrpt->callmode == 1)
+ {
myrpt->exten[myrpt->cidx++] = c;
myrpt->exten[myrpt->cidx] = 0;
/* if this exists */
- if (ast_exists_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
- myrpt->callmode = 2;
- rpt_mutex_unlock(&myrpt->lock);
- if (!myrpt->patchquiet)
- rpt_telemetry(myrpt, PROC, NULL);
- return;
+ if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
+ {
+ /* if this really it, end now */
+ if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
+ myrpt->exten,1,NULL))
+ {
+ myrpt->callmode = 2;
+ rpt_mutex_unlock(&myrpt->lock);
+ if(!myrpt->patchquiet)
+ rpt_telemetry(myrpt,PROC,NULL);
+ return;
+ }
+ else /* othewise, reset timer */
+ {
+ myrpt->calldigittimer = 1;
+ }
}
/* if can continue, do so */
- if (!ast_canmatch_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
+ if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
+ {
/* call has failed, inform user */
myrpt->callmode = 4;
}
rpt_mutex_unlock(&myrpt->lock);
return;
}
- if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) {
+ if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
+ {
myrpt->mydtmf = c;
}
rpt_mutex_unlock(&myrpt->lock);
+ if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
+ do_dtmf_phone(myrpt,NULL,c);
return;
}
@@ -5614,163 +10582,361 @@ static void local_dtmf_helper(struct rpt *myrpt, char c)
static void queue_id(struct rpt *myrpt)
{
- myrpt->mustid = myrpt->tailid = 0;
- myrpt->idtimer = myrpt->p.idtime; /* Reset our ID timer */
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, ID, NULL);
- rpt_mutex_lock(&myrpt->lock);
+ if(myrpt->p.idtime){ /* ID time must be non-zero */
+ myrpt->mustid = myrpt->tailid = 0;
+ myrpt->idtimer = myrpt->p.idtime; /* Reset our ID timer */
+ rpt_mutex_unlock(&myrpt->lock);
+ rpt_telemetry(myrpt,ID,NULL);
+ rpt_mutex_lock(&myrpt->lock);
+ }
}
/* Scheduler */
+/* must be called locked */
static void do_scheduler(struct rpt *myrpt)
{
- int res;
+ int i,res;
+
+#ifdef NEW_ASTERISK
struct ast_tm tmnow;
+#else
+ struct tm tmnow;
+#endif
+ struct ast_variable *skedlist;
+ char *strs[5],*vp,*val,value[100];
memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
- if ( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
+ if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
/* Try to get close to a 1 second resolution */
- if (myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
+ if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
return;
- ast_localtime(&myrpt->curtv, &tmnow, NULL);
+ rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
/* If midnight, then reset all daily statistics */
- if ((tmnow.tm_hour == 0) && (tmnow.tm_min == 0) && (tmnow.tm_sec == 0)) {
+ if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
myrpt->dailykeyups = 0;
myrpt->dailytxtime = 0;
myrpt->dailykerchunks = 0;
myrpt->dailyexecdcommands = 0;
}
-}
+ if(tmnow.tm_sec != 0)
+ return;
+
+ /* Code below only executes once per minute */
+
+
+ /* Don't schedule if remote */
+
+ if (myrpt->remote)
+ return;
+
+ /* Don't schedule if disabled */
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
+ if(debug > 6)
+ ast_log(LOG_NOTICE, "Scheduler disabled\n");
+ return;
+ }
+
+ if(!myrpt->p.skedstanzaname){ /* No stanza means we do nothing */
+ if(debug > 6)
+ ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
+ return;
+ }
+
+ /* get pointer to linked list of scheduler entries */
+ skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
+
+ if(debug > 6){
+ ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
+ tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
+ }
+ /* walk the list */
+ for(; skedlist; skedlist = skedlist->next){
+ if(debug > 6)
+ ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
+ strncpy(value,skedlist->value,99);
+ value[99] = 0;
+ /* point to the substrings for minute, hour, dom, month, and dow */
+ for( i = 0, vp = value ; i < 5; i++){
+ if(!*vp)
+ break;
+ while((*vp == ' ') || (*vp == 0x09)) /* get rid of any leading white space */
+ vp++;
+ strs[i] = vp; /* save pointer to beginning of substring */
+ while((*vp != ' ') && (*vp != 0x09) && (*vp != 0)) /* skip over substring */
+ vp++;
+ if(*vp)
+ *vp++ = 0; /* mark end of substring */
+ }
+ if(debug > 6)
+ ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
+ strs[0], strs[1], strs[2], strs[3], strs[4]);
+ if(i == 5){
+ if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
+ continue;
+ if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
+ continue;
+ if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
+ continue;
+ if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
+ continue;
+ if(atoi(strs[4]) == 7)
+ strs[4] = "0";
+ if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
+ continue;
+ if(debug)
+ ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
+ if(atoi(skedlist->name) == 0)
+ return; /* Zero is reserved for the startup macro */
+ val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
+ if (!val){
+ ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
+ return; /* Macro not found */
+ }
+ if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
+ ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
+ skedlist->name);
+ return; /* Macro buffer full */
+ }
+ myrpt->macrotimer = MACROTIME;
+ strncat(myrpt->macrobuf,val,MAXMACRO - 1);
+ }
+ else{
+ ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
+ skedlist->name, skedlist->value);
+ }
+ }
+
+}
/* single thread with one file (request) to dial */
static void *rpt(void *this)
{
- struct rpt *myrpt = (struct rpt *)this;
- char *tele, c;
- const char *idtalkover;
- int ms = MSWAIT, i, lasttx=0, val, remrx=0, identqueued, othertelemqueued, tailmessagequeued, ctqueued;
- struct ast_channel *who;
- ZT_CONFINFO ci; /* conference info */
- time_t t;
- struct rpt_link *l, *m;
- struct rpt_tele *telem;
- char tmpstr[300];
-
+struct rpt *myrpt = (struct rpt *)this;
+char *tele,*idtalkover,c,myfirst,*p;
+int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
+int tailmessagequeued,ctqueued,dtmfed,lastmyrx,localmsgqueued;
+struct ast_channel *who;
+ZT_CONFINFO ci; /* conference info */
+time_t t;
+struct rpt_link *l,*m;
+struct rpt_tele *telem;
+char tmpstr[300],lstr[MAXLINKLIST];
+
+
+ if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
+ sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
+ mkdir(tmpstr,0600);
rpt_mutex_lock(&myrpt->lock);
telem = myrpt->tele.next;
- while (telem != &myrpt->tele) {
- ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
+ while(telem != &myrpt->tele)
+ {
+ ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
telem = telem->next;
}
rpt_mutex_unlock(&myrpt->lock);
/* find our index, and load the vars initially */
- for (i = 0; i < nrpts; i++) {
- if (&rpt_vars[i] == myrpt) {
- load_rpt_vars(i, 0);
+ for(i = 0; i < nrpts; i++)
+ {
+ if (&rpt_vars[i] == myrpt)
+ {
+ load_rpt_vars(i,0);
break;
}
}
+
rpt_mutex_lock(&myrpt->lock);
- ast_copy_string(tmpstr, myrpt->rxchanname, sizeof(tmpstr));
- tele = strchr(tmpstr, '/');
- if (!tele) {
- ast_log(LOG_ERROR, "rpt:Rxchannel Dial number (%s) must be in format tech/number\n", myrpt->rxchanname);
+ while(myrpt->xlink)
+ {
+ myrpt->xlink = 3;
+ rpt_mutex_unlock(&myrpt->lock);
+ usleep(100000);
+ rpt_mutex_lock(&myrpt->lock);
+ }
+ if ((!strcmp(myrpt->remoterig, remote_rig_rbi)) &&
+ (ioperm(myrpt->p.iobase,1,1) == -1))
+ {
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
+ myrpt->rpt_thread = AST_PTHREADT_STOP;
+ pthread_exit(NULL);
+ }
+ strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
+ tele = strchr(tmpstr,'/');
+ if (!tele)
+ {
+ fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
rpt_mutex_unlock(&myrpt->lock);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
*tele++ = 0;
- myrpt->rxchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, tele, NULL);
- if (myrpt->rxchannel) {
- if (myrpt->rxchannel->_state == AST_STATE_BUSY) {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Rx channel\n");
+ myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
+ myrpt->zaprxchannel = NULL;
+ if (!strcasecmp(tmpstr,"Zap"))
+ myrpt->zaprxchannel = myrpt->rxchannel;
+ if (myrpt->rxchannel)
+ {
+ if (myrpt->rxchannel->_state == AST_STATE_BUSY)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->rxchannel);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
- ast_set_read_format(myrpt->rxchannel, AST_FORMAT_SLINEAR);
- ast_set_write_format(myrpt->rxchannel, AST_FORMAT_SLINEAR);
- ast_channel_setwhentohangup_tv(myrpt->rxchannel, cancel_atimeout);
+ ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
+ ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->rxchannel->cdr)
+ ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+#ifndef NEW_ASTERISK
+ myrpt->rxchannel->whentohangup = 0;
+#endif
myrpt->rxchannel->appl = "Apprpt";
myrpt->rxchannel->data = "(Repeater Rx)";
- ast_verb(3, "rpt (Rx) initiating call to %s/%s on %s\n",
- tmpstr, tele, myrpt->rxchannel->name);
- ast_call(myrpt->rxchannel, tele, 999);
- if (myrpt->rxchannel->_state != AST_STATE_UP) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
+ tmpstr,tele,myrpt->rxchannel->name);
+ ast_call(myrpt->rxchannel,tele,999);
+ if (myrpt->rxchannel->_state != AST_STATE_UP)
+ {
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->rxchannel);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
- } else {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Rx channel\n");
+ }
+ else
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
rpt_mutex_unlock(&myrpt->lock);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
- if (myrpt->txchanname) {
- ast_copy_string(tmpstr, myrpt->txchanname, sizeof(tmpstr));
- tele = strchr(tmpstr, '/');
- if (!tele) {
- ast_log(LOG_ERROR, "rpt:Txchannel Dial number (%s) must be in format tech/number\n", myrpt->txchanname);
+ myrpt->zaptxchannel = NULL;
+ if (myrpt->txchanname)
+ {
+ strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
+ tele = strchr(tmpstr,'/');
+ if (!tele)
+ {
+ fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->rxchannel);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
*tele++ = 0;
- myrpt->txchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, tele, NULL);
- if (myrpt->txchannel) {
- if (myrpt->txchannel->_state == AST_STATE_BUSY) {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n");
+ myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
+ if (!strcasecmp(tmpstr,"Zap"))
+ myrpt->zaptxchannel = myrpt->txchannel;
+ if (myrpt->txchannel)
+ {
+ if (myrpt->txchannel->_state == AST_STATE_BUSY)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->txchannel);
ast_hangup(myrpt->rxchannel);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
- ast_set_read_format(myrpt->txchannel, AST_FORMAT_SLINEAR);
- ast_set_write_format(myrpt->txchannel, AST_FORMAT_SLINEAR);
- ast_channel_setwhentohangup_tv(myrpt->txchannel, cancel_atimeout);
+ ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
+ ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->txchannel->cdr)
+ ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+#ifndef NEW_ASTERISK
+ myrpt->txchannel->whentohangup = 0;
+#endif
myrpt->txchannel->appl = "Apprpt";
myrpt->txchannel->data = "(Repeater Tx)";
- ast_verb(3, "rpt (Tx) initiating call to %s/%s on %s\n",
- tmpstr, tele, myrpt->txchannel->name);
- ast_call(myrpt->txchannel, tele, 999);
- if (myrpt->rxchannel->_state != AST_STATE_UP) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
+ tmpstr,tele,myrpt->txchannel->name);
+ ast_call(myrpt->txchannel,tele,999);
+ if (myrpt->rxchannel->_state != AST_STATE_UP)
+ {
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->rxchannel);
ast_hangup(myrpt->txchannel);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
- } else {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n");
+ }
+ else
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->rxchannel);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
- } else {
+ }
+ else
+ {
myrpt->txchannel = myrpt->rxchannel;
+ if (!strncasecmp(myrpt->rxchanname,"Zap",3))
+ myrpt->zaptxchannel = myrpt->txchannel;
+ }
+ ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
+ ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
+ /* allocate a pseudo-channel thru asterisk */
+ myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!myrpt->pchannel)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
+ rpt_mutex_unlock(&myrpt->lock);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ myrpt->rpt_thread = AST_PTHREADT_STOP;
+ pthread_exit(NULL);
+ }
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->pchannel->cdr)
+ ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+ if (!myrpt->zaprxchannel) myrpt->zaprxchannel = myrpt->pchannel;
+ if (!myrpt->zaptxchannel)
+ {
+ /* allocate a pseudo-channel thru asterisk */
+ myrpt->zaptxchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!myrpt->zaptxchannel)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
+ rpt_mutex_unlock(&myrpt->lock);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ myrpt->rpt_thread = AST_PTHREADT_STOP;
+ pthread_exit(NULL);
+ }
+ ast_set_read_format(myrpt->zaptxchannel,AST_FORMAT_SLINEAR);
+ ast_set_write_format(myrpt->zaptxchannel,AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->zaptxchannel->cdr)
+ ast_set_flag(myrpt->zaptxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
}
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_KEY);
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
/* allocate a pseudo-channel thru asterisk */
- myrpt->pchannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
- if (!myrpt->pchannel) {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
+ myrpt->monchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!myrpt->monchannel)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
rpt_mutex_unlock(&myrpt->lock);
if (myrpt->txchannel != myrpt->rxchannel)
ast_hangup(myrpt->txchannel);
@@ -5778,15 +10944,23 @@ static void *rpt(void *this)
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
+ ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
+ ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->monchannel->cdr)
+ ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
/* make a conference for the tx */
ci.chan = 0;
ci.confno = -1; /* make a new conf */
ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
/* first put the channel on the conference in proper mode */
- if (ioctl(myrpt->txchannel->fds[0], ZT_SETCONF, &ci) == -1) {
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->pchannel);
+ ast_hangup(myrpt->monchannel);
if (myrpt->txchannel != myrpt->rxchannel)
ast_hangup(myrpt->txchannel);
ast_hangup(myrpt->rxchannel);
@@ -5801,10 +10975,12 @@ static void *rpt(void *this)
ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? ZT_CONF_CONFANNMON :
(ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
/* first put the channel on the conference in announce mode */
- if (ioctl(myrpt->pchannel->fds[0], ZT_SETCONF, &ci) == -1) {
+ if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->pchannel);
+ ast_hangup(myrpt->monchannel);
if (myrpt->txchannel != myrpt->rxchannel)
ast_hangup(myrpt->txchannel);
ast_hangup(myrpt->rxchannel);
@@ -5813,34 +10989,127 @@ static void *rpt(void *this)
}
/* save pseudo channel conference number */
myrpt->conf = ci.confno;
+ /* make a conference for the pseudo */
+ ci.chan = 0;
+ if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
+ (myrpt->zaptxchannel == myrpt->txchannel))
+ {
+ /* get tx channel's port number */
+ if (ioctl(myrpt->txchannel->fds[0],ZT_CHANNO,&ci.confno) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->pchannel);
+ ast_hangup(myrpt->monchannel);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ myrpt->rpt_thread = AST_PTHREADT_STOP;
+ pthread_exit(NULL);
+ }
+ ci.confmode = ZT_CONF_MONITORTX;
+ }
+ else
+ {
+ ci.confno = myrpt->txconf;
+ ci.confmode = ZT_CONF_CONFANNMON;
+ }
+ /* first put the channel on the conference in announce mode */
+ if (ioctl(myrpt->monchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->pchannel);
+ ast_hangup(myrpt->monchannel);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ myrpt->rpt_thread = AST_PTHREADT_STOP;
+ pthread_exit(NULL);
+ }
+ /* allocate a pseudo-channel thru asterisk */
+ myrpt->parrotchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!myrpt->parrotchannel)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
+ rpt_mutex_unlock(&myrpt->lock);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ myrpt->rpt_thread = AST_PTHREADT_STOP;
+ pthread_exit(NULL);
+ }
+ ast_set_read_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
+ ast_set_write_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->parrotchannel->cdr)
+ ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
/* allocate a pseudo-channel thru asterisk */
- myrpt->txpchannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
- if (!myrpt->txpchannel) {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
+ myrpt->voxchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!myrpt->voxchannel)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
+ rpt_mutex_unlock(&myrpt->lock);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ myrpt->rpt_thread = AST_PTHREADT_STOP;
+ pthread_exit(NULL);
+ }
+ ast_set_read_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
+ ast_set_write_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->voxchannel->cdr)
+ ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+ /* allocate a pseudo-channel thru asterisk */
+ myrpt->txpchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!myrpt->txpchannel)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->pchannel);
+ ast_hangup(myrpt->monchannel);
if (myrpt->txchannel != myrpt->rxchannel)
ast_hangup(myrpt->txchannel);
ast_hangup(myrpt->rxchannel);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->txpchannel->cdr)
+ ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
/* make a conference for the tx */
ci.chan = 0;
ci.confno = myrpt->txconf;
ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER ;
/* first put the channel on the conference in proper mode */
- if (ioctl(myrpt->txpchannel->fds[0], ZT_SETCONF, &ci) == -1) {
+ if (ioctl(myrpt->txpchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->txpchannel);
- ast_hangup(myrpt->pchannel);
+ ast_hangup(myrpt->monchannel);
if (myrpt->txchannel != myrpt->rxchannel)
ast_hangup(myrpt->txchannel);
ast_hangup(myrpt->rxchannel);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
}
+ /* if serial io port, open it */
+ myrpt->iofd = -1;
+ if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
+ {
+ ast_log(LOG_ERROR, "Unable to open %s\n",myrpt->p.ioport);
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->pchannel);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ pthread_exit(NULL);
+ }
/* Now, the idea here is to copy from the physical rx channel buffer
into the pseudo tx buffer, and from the pseudo rx buffer into the
tx channel buffer */
@@ -5855,18 +11124,24 @@ static void *rpt(void *this)
myrpt->tounkeyed = 0;
myrpt->tonotify = 0;
myrpt->retxtimer = 0;
+ myrpt->rerxtimer = 0;
myrpt->skedtimer = 0;
myrpt->tailevent = 0;
lasttx = 0;
myrpt->keyed = 0;
- idtalkover = ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
+ myrpt->txkeyed = 0;
+ time(&myrpt->lastkeyedtime);
+ myrpt->lastkeyedtime -= RPT_LOCKOUT_SECS;
+ time(&myrpt->lasttxkeyedtime);
+ myrpt->lasttxkeyedtime -= RPT_LOCKOUT_SECS;
+ idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
myrpt->dtmfidx = -1;
myrpt->dtmfbuf[0] = 0;
myrpt->rem_dtmfidx = -1;
myrpt->rem_dtmfbuf[0] = 0;
myrpt->dtmf_time = 0;
myrpt->rem_dtmf_time = 0;
- myrpt->enable = 1;
+ myrpt->inpadtest = 0;
myrpt->disgorgetime = 0;
myrpt->lastnodewhichkeyedusup[0] = '\0';
myrpt->dailytxtime = 0;
@@ -5880,90 +11155,102 @@ static void *rpt(void *this)
myrpt->timeouts = 0;
myrpt->exten[0] = '\0';
myrpt->lastdtmfcommand[0] = '\0';
- if (myrpt->p.startupmacro) {
- snprintf(myrpt->macrobuf, sizeof(myrpt->macrobuf), "PPPP%s", myrpt->p.startupmacro);
- }
- if (myrpt->p.startupgosub) {
- snprintf(myrpt->gosubbuf, sizeof(myrpt->gosubbuf), "PPPP%s", myrpt->p.startupgosub);
+ voxinit_rpt(myrpt,1);
+ myrpt->wasvox = 0;
+ if (myrpt->p.startupmacro)
+ {
+ snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
}
rpt_mutex_unlock(&myrpt->lock);
- val = 0;
- ast_channel_setoption(myrpt->rxchannel, AST_OPTION_TONE_VERIFY, &val, sizeof(char), 0);
val = 1;
- ast_channel_setoption(myrpt->rxchannel, AST_OPTION_RELAXDTMF, &val, sizeof(char), 0);
- while (ms >= 0) {
- struct ast_frame *f;
- struct ast_channel *cs[300];
- int totx=0, elap=0, n, toexit = 0;
+ ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
+ val = 1;
+ ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
+ if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
+ dtmfed = 0;
+ if (myrpt->remoterig && !ISRIG_RTX(myrpt->remoterig)) setrem(myrpt);
+ lastmyrx = 0;
+ myfirst = 0;
+ while (ms >= 0)
+ {
+ struct ast_frame *f,*f1,*f2;
+ struct ast_channel *cs[300],*cs1[300];
+ int totx=0,elap=0,n,x,toexit=0;
/* DEBUG Dump */
- if ((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)) {
+ if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
struct rpt_link *zl;
struct rpt_tele *zt;
myrpt->disgorgetime = 0;
- ast_log(LOG_NOTICE, "********** Variable Dump Start (app_rpt) **********\n");
- ast_log(LOG_NOTICE, "totx = %d\n", totx);
- ast_log(LOG_NOTICE, "remrx = %d\n", remrx);
- ast_log(LOG_NOTICE, "lasttx = %d\n", lasttx);
- ast_log(LOG_NOTICE, "elap = %d\n", elap);
- ast_log(LOG_NOTICE, "toexit = %d\n", toexit);
-
- ast_log(LOG_NOTICE, "myrpt->keyed = %d\n", myrpt->keyed);
- ast_log(LOG_NOTICE, "myrpt->localtx = %d\n", myrpt->localtx);
- ast_log(LOG_NOTICE, "myrpt->callmode = %d\n", myrpt->callmode);
- ast_log(LOG_NOTICE, "myrpt->enable = %d\n", myrpt->enable);
- ast_log(LOG_NOTICE, "myrpt->mustid = %d\n", myrpt->mustid);
- ast_log(LOG_NOTICE, "myrpt->tounkeyed = %d\n", myrpt->tounkeyed);
- ast_log(LOG_NOTICE, "myrpt->tonotify = %d\n", myrpt->tonotify);
- ast_log(LOG_NOTICE, "myrpt->retxtimer = %ld\n", myrpt->retxtimer);
- ast_log(LOG_NOTICE, "myrpt->totimer = %d\n", myrpt->totimer);
- ast_log(LOG_NOTICE, "myrpt->tailtimer = %d\n", myrpt->tailtimer);
- ast_log(LOG_NOTICE, "myrpt->tailevent = %d\n", myrpt->tailevent);
+ ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
+ ast_log(LOG_NOTICE,"totx = %d\n",totx);
+ ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
+ ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
+ ast_log(LOG_NOTICE,"elap = %d\n",elap);
+ ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
+
+ ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
+ ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
+ ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
+ ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
+ ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
+ ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
+ ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
+ ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
+ ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
+ ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
zl = myrpt->links.next;
- while (zl != &myrpt->links) {
- ast_log(LOG_NOTICE, "*** Link Name: %s ***\n", zl->name);
- ast_log(LOG_NOTICE, " link->lasttx %d\n", zl->lasttx);
- ast_log(LOG_NOTICE, " link->lastrx %d\n", zl->lastrx);
- ast_log(LOG_NOTICE, " link->connected %d\n", zl->connected);
- ast_log(LOG_NOTICE, " link->hasconnected %d\n", zl->hasconnected);
- ast_log(LOG_NOTICE, " link->outbound %d\n", zl->outbound);
- ast_log(LOG_NOTICE, " link->disced %d\n", zl->disced);
- ast_log(LOG_NOTICE, " link->killme %d\n", zl->killme);
- ast_log(LOG_NOTICE, " link->disctime %ld\n", zl->disctime);
- ast_log(LOG_NOTICE, " link->retrytimer %ld\n", zl->retrytimer);
- ast_log(LOG_NOTICE, " link->retries = %d\n", zl->retries);
- ast_log(LOG_NOTICE, " link->reconnects = %d\n", zl->reconnects);
- zl = zl->next;
- }
-
+ while(zl != &myrpt->links){
+ ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",zl->name);
+ ast_log(LOG_NOTICE," link->lasttx %d\n",zl->lasttx);
+ ast_log(LOG_NOTICE," link->lastrx %d\n",zl->lastrx);
+ ast_log(LOG_NOTICE," link->connected %d\n",zl->connected);
+ ast_log(LOG_NOTICE," link->hasconnected %d\n",zl->hasconnected);
+ ast_log(LOG_NOTICE," link->outbound %d\n",zl->outbound);
+ ast_log(LOG_NOTICE," link->disced %d\n",zl->disced);
+ ast_log(LOG_NOTICE," link->killme %d\n",zl->killme);
+ ast_log(LOG_NOTICE," link->disctime %ld\n",zl->disctime);
+ ast_log(LOG_NOTICE," link->retrytimer %ld\n",zl->retrytimer);
+ ast_log(LOG_NOTICE," link->retries = %d\n",zl->retries);
+ ast_log(LOG_NOTICE," link->reconnects = %d\n",zl->reconnects);
+ ast_log(LOG_NOTICE," link->newkey = %d\n",zl->newkey);
+ zl = zl->next;
+ }
+
zt = myrpt->tele.next;
- if (zt != &myrpt->tele)
- ast_log(LOG_NOTICE, "*** Telemetry Queue ***\n");
- while (zt != &myrpt->tele) {
- ast_log(LOG_NOTICE, " Telemetry mode: %d\n", zt->mode);
- zt = zt->next;
- }
- ast_log(LOG_NOTICE, "******* Variable Dump End (app_rpt) *******\n");
+ if(zt != &myrpt->tele)
+ ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
+ while(zt != &myrpt->tele){
+ ast_log(LOG_NOTICE," Telemetry mode: %d\n",zt->mode);
+ zt = zt->next;
+ }
+ ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
+
}
- if (myrpt->reload) {
+
+ if (myrpt->reload)
+ {
struct rpt_tele *telem;
rpt_mutex_lock(&myrpt->lock);
telem = myrpt->tele.next;
- while (telem != &myrpt->tele) {
- ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
+ while(telem != &myrpt->tele)
+ {
+ ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
telem = telem->next;
}
myrpt->reload = 0;
rpt_mutex_unlock(&myrpt->lock);
usleep(10000);
/* find our index, and load the vars */
- for (i = 0; i < nrpts; i++) {
- if (&rpt_vars[i] == myrpt) {
- load_rpt_vars(i, 0);
+ for(i = 0; i < nrpts; i++)
+ {
+ if (&rpt_vars[i] == myrpt)
+ {
+ load_rpt_vars(i,0);
break;
}
}
@@ -5973,40 +11260,87 @@ static void *rpt(void *this)
if (ast_check_hangup(myrpt->rxchannel)) break;
if (ast_check_hangup(myrpt->txchannel)) break;
if (ast_check_hangup(myrpt->pchannel)) break;
+ if (ast_check_hangup(myrpt->monchannel)) break;
+ if (myrpt->parrotchannel &&
+ ast_check_hangup(myrpt->parrotchannel)) break;
+ if (myrpt->voxchannel &&
+ ast_check_hangup(myrpt->voxchannel)) break;
if (ast_check_hangup(myrpt->txpchannel)) break;
+ if (myrpt->zaptxchannel && ast_check_hangup(myrpt->zaptxchannel)) break;
- /* Update local tx with keyed if not parsing a command */
- myrpt->localtx = myrpt->keyed && (myrpt->dtmfidx == -1) && (!myrpt->cmdnode[0]);
+ /* Set local tx with keyed */
+ myrpt->localtx = myrpt->keyed;
/* If someone's connected, and they're transmitting from their end to us, set remrx true */
l = myrpt->links.next;
remrx = 0;
- while (l != &myrpt->links) {
- if (l->lastrx) {
+ while(l != &myrpt->links)
+ {
+ if (l->lastrx){
remrx = 1;
- if (l->name[0] != '0') /* Ignore '0' nodes */
+ if(l->name[0] != '0') /* Ignore '0' nodes */
strcpy(myrpt->lastnodewhichkeyedusup, l->name); /* Note the node which is doing the key up */
}
l = l->next;
}
/* Create a "must_id" flag for the cleanup ID */
- myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
+ if(myrpt->p.idtime) /* ID time must be non-zero */
+ myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
/* Build a fresh totx from myrpt->keyed and autopatch activated */
- totx = myrpt->callmode;
/* If full duplex, add local tx to totx */
- if (myrpt->p.duplex > 1) totx = totx || myrpt->localtx;
+ if (myrpt->p.duplex > 1)
+ {
+ totx = myrpt->callmode;
+ totx = totx || myrpt->localtx;
+ }
+ else
+ {
+ int myrx = myrpt->localtx || remrx || (!myrpt->callmode);
+
+ if (lastmyrx != myrx)
+ {
+ voxinit_rpt(myrpt,!myrx);
+ lastmyrx = myrx;
+ }
+ totx = 0;
+ if (myrpt->callmode && (myrpt->voxtotimer <= 0))
+ {
+ if (myrpt->voxtostate)
+ {
+ myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
+ myrpt->voxtostate = 0;
+ }
+ else
+ {
+ myrpt->voxtotimer = myrpt->p.voxrecover_ms;
+ myrpt->voxtostate = 1;
+ }
+ }
+ if (!myrpt->voxtostate)
+ totx = myrpt->callmode && myrpt->wasvox;
+ }
/* Traverse the telemetry list to see what's queued */
identqueued = 0;
+ localmsgqueued = 0;
othertelemqueued = 0;
tailmessagequeued = 0;
ctqueued = 0;
telem = myrpt->tele.next;
- while (telem != &myrpt->tele) {
- if ((telem->mode == ID) || (telem->mode == IDTALKOVER)) {
+ while(telem != &myrpt->tele)
+ {
+ if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
identqueued = 1; /* Identification telemetry */
- } else if (telem->mode == TAILMSG) {
+ }
+ else if(telem->mode == TAILMSG)
+ {
tailmessagequeued = 1; /* Tail message telemetry */
- } else {
- if (telem->mode != UNKEY)
+ }
+ else if(telem->mode == STATS_TIME_LOCAL)
+ {
+ localmsgqueued = 1; /* Local message */
+ }
+ else
+ {
+ if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
othertelemqueued = 1; /* Other telemetry */
else
ctqueued = 1; /* Courtesy tone telemetry */
@@ -6014,42 +11348,58 @@ static void *rpt(void *this)
telem = telem->next;
}
- /* Add in any "other" telemetry, if 3/4 or full duplex */
- if (myrpt->p.duplex > 0)
- totx = totx || othertelemqueued;
- /* Update external (to links) transmitter PTT state with everything but ID, CT, and tailmessage telemetry */
+ /* Add in any "other" telemetry, unless specified otherwise */
+ if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
+ /* Update external (to links) transmitter PTT state with everything but */
+ /* ID, CT, local messages, and tailmessage telemetry */
myrpt->exttx = totx;
+ totx = totx || myrpt->dtmf_local_timer;
/* If half or 3/4 duplex, add localtx to external link tx */
- if (myrpt->p.duplex < 2)
- myrpt->exttx = myrpt->exttx || myrpt->localtx;
+ if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
/* Add in ID telemetry to local transmitter */
totx = totx || remrx;
- /* If 3/4 or full duplex, add in ident and CT telemetry */
+ /* If 3/4 or full duplex, add in ident, CT telemetry, and local messages */
if (myrpt->p.duplex > 0)
- totx = totx || identqueued || ctqueued;
+ totx = totx || identqueued || ctqueued || localmsgqueued;
+ /* If full duplex, add local dtmf stuff active */
+ if (myrpt->p.duplex > 1)
+ {
+ totx = totx || (myrpt->dtmfidx > -1) ||
+ myrpt->cmdnode[0];
+ }
+ /* add in parrot stuff */
+ totx = totx || (myrpt->parrotstate > 1);
/* Reset time out timer variables if there is no activity */
- if (!totx) {
+ if (!totx)
+ {
myrpt->totimer = myrpt->p.totime;
myrpt->tounkeyed = 0;
myrpt->tonotify = 0;
- } else
- myrpt->tailtimer = myrpt->p.hangtime; /* Initialize tail timer */
+ }
+ else{
+ myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
+ myrpt->p.althangtime : /* Initialize tail timer */
+ myrpt->p.hangtime;
+ }
/* Disable the local transmitter if we are timed out */
totx = totx && myrpt->totimer;
/* if timed-out and not said already, say it */
- if ((!myrpt->totimer) && (!myrpt->tonotify)) {
+ if ((!myrpt->totimer) && (!myrpt->tonotify))
+ {
myrpt->tonotify = 1;
myrpt->timeouts++;
rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, TIMEOUT, NULL);
+ rpt_telemetry(myrpt,TIMEOUT,NULL);
rpt_mutex_lock(&myrpt->lock);
}
/* If unkey and re-key, reset time out timer */
- if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed)) {
+ if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
+ {
myrpt->tounkeyed = 1;
}
- if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed) {
+ if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
+ {
myrpt->totimer = myrpt->p.totime;
myrpt->tounkeyed = 0;
myrpt->tonotify = 0;
@@ -6057,38 +11407,37 @@ static void *rpt(void *this)
continue;
}
/* if timed-out and in circuit busy after call */
- if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4)) {
+ if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
+ {
+ if(debug)
+ ast_log(LOG_NOTICE, "timed-out and in circuit busy after call\n");
myrpt->callmode = 0;
+ myrpt->macropatch=0;
+ channel_revert(myrpt);
}
/* get rid of tail if timed out */
- if (!myrpt->totimer)
- myrpt->tailtimer = 0;
+ if (!myrpt->totimer) myrpt->tailtimer = 0;
/* if not timed-out, add in tail */
- if (myrpt->totimer)
- totx = totx || myrpt->tailtimer;
+ if (myrpt->totimer) totx = totx || myrpt->tailtimer;
/* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
/* If tail message, kill the message if someone keys up over it */
if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
- int hasid = 0, hastalkover = 0;
+ int hasid = 0,hastalkover = 0;
telem = myrpt->tele.next;
- while (telem != &myrpt->tele) {
- if (telem->mode == ID) {
- if (telem->chan)
- ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
+ while(telem != &myrpt->tele){
+ if(telem->mode == ID){
+ if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
hasid = 1;
}
- if (telem->mode == TAILMSG) {
- if (telem->chan)
- ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
- }
- if (telem->mode == IDTALKOVER)
- hastalkover = 1;
+ if(telem->mode == TAILMSG){
+ if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
+ }
+ if (telem->mode == IDTALKOVER) hastalkover = 1;
telem = telem->next;
}
rpt_mutex_unlock(&myrpt->lock);
- if (hasid && (!hastalkover))
- rpt_telemetry(myrpt, IDTALKOVER, NULL); /* Start Talkover ID */
+ if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL); /* Start Talkover ID */
rpt_mutex_lock(&myrpt->lock);
}
/* Try to be polite */
@@ -6096,24 +11445,25 @@ static void *rpt(void *this)
/* If within 30 seconds of the time to ID, try do it in the tail */
/* else if at ID time limit, do it right over the top of them */
/* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */
- if (myrpt->mustid && (!myrpt->idtimer))
+ if(myrpt->mustid && (!myrpt->idtimer))
queue_id(myrpt);
- if ((totx && (!myrpt->exttx) &&
- (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer)) {
- myrpt->tailid = 1;
- }
+ if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
+ (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer)) /* ID time must be non-zero */
+ {
+ myrpt->tailid = 1;
+ }
/* If tail timer expires, then check for tail messages */
- if (myrpt->tailevent) {
+ if(myrpt->tailevent){
myrpt->tailevent = 0;
- if (myrpt->tailid) {
+ if(myrpt->tailid){
totx = 1;
queue_id(myrpt);
}
- else if ((myrpt->p.tailmsg.msgs[0]) &&
- (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)) {
+ else if ((myrpt->p.tailmessages[0]) &&
+ (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
totx = 1;
myrpt->tmsgtimer = myrpt->p.tailmessagetime;
rpt_mutex_unlock(&myrpt->lock);
@@ -6125,48 +11475,115 @@ static void *rpt(void *this)
/* Main TX control */
/* let telemetry transmit anyway (regardless of timeout) */
- if (myrpt->p.duplex > 0)
- totx = totx || (myrpt->tele.next != &myrpt->tele);
- if (totx && (!lasttx)) {
+ if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
+ totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
+ myrpt->txrealkeyed = totx;
+ totx = totx || (!AST_LIST_EMPTY(&myrpt->txq));
+ if (totx && (!lasttx))
+ {
+ char mydate[100],myfname[100];
+ time_t myt;
+
+ if (myrpt->monstream) ast_closestream(myrpt->monstream);
+ if (myrpt->p.archivedir)
+ {
+ long blocksleft;
+
+ time(&myt);
+ strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
+ localtime(&myt));
+ sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
+ myrpt->name,mydate);
+ myrpt->monstream = ast_writefile(myfname,"wav49",
+ "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
+ if (myrpt->p.monminblocks)
+ {
+ blocksleft = diskavail(myrpt);
+ if (blocksleft >= myrpt->p.monminblocks)
+ donodelog(myrpt,"TXKEY,MAIN");
+ } else donodelog(myrpt,"TXKEY,MAIN");
+ }
lasttx = 1;
+ myrpt->txkeyed = 1;
+ time(&myrpt->lasttxkeyedtime);
myrpt->dailykeyups++;
myrpt->totalkeyups++;
rpt_mutex_unlock(&myrpt->lock);
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_KEY);
+ ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
rpt_mutex_lock(&myrpt->lock);
}
- totx = totx && myrpt->enable;
- if ((!totx) && lasttx) {
+ if ((!totx) && lasttx)
+ {
+ if (myrpt->monstream) ast_closestream(myrpt->monstream);
+ myrpt->monstream = NULL;
+
lasttx = 0;
+ myrpt->txkeyed = 0;
+ time(&myrpt->lasttxkeyedtime);
rpt_mutex_unlock(&myrpt->lock);
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
+ ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
rpt_mutex_lock(&myrpt->lock);
+ donodelog(myrpt,"TXUNKEY,MAIN");
}
time(&t);
/* if DTMF timeout */
- if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t)) {
+ if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
+ {
+ myrpt->inpadtest = 0;
myrpt->dtmfidx = -1;
myrpt->dtmfbuf[0] = 0;
}
/* if remote DTMF timeout */
- if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t)) {
+ if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
+ {
+ myrpt->inpadtest = 0;
myrpt->rem_dtmfidx = -1;
myrpt->rem_dtmfbuf[0] = 0;
}
+ if (myrpt->exttx && myrpt->parrotchannel &&
+ myrpt->p.parrotmode && (!myrpt->parrotstate))
+ {
+ char myfname[300];
+
+ ci.confno = myrpt->conf;
+ ci.confmode = ZT_CONF_CONFANNMON;
+ ci.chan = 0;
+
+ /* first put the channel on the conference in announce mode */
+ if (ioctl(myrpt->parrotchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
+ break;
+ }
+
+ sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
+ strcat(myfname,".wav");
+ unlink(myfname);
+ sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
+ myrpt->parrotstate = 1;
+ myrpt->parrottimer = myrpt->p.parrottime;
+ if (myrpt->parrotstream)
+ ast_closestream(myrpt->parrotstream);
+ myrpt->parrotstream = NULL;
+ myrpt->parrotstream = ast_writefile(myfname,"wav",
+ "app_rpt Parrot",O_CREAT | O_TRUNC,0,0600);
+ }
+
/* Reconnect */
l = myrpt->links.next;
- while (l != &myrpt->links) {
- if (l->killme) {
+ while(l != &myrpt->links)
+ {
+ if (l->killme)
+ {
/* remove from queue */
remque((struct qelem *) l);
- if (!strcmp(myrpt->cmdnode, l->name))
+ if (!strcmp(myrpt->cmdnode,l->name))
myrpt->cmdnode[0] = 0;
rpt_mutex_unlock(&myrpt->lock);
/* hang-up on call to device */
- if (l->chan)
- ast_hangup(l->chan);
+ if (l->chan) ast_hangup(l->chan);
ast_hangup(l->pchan);
ast_free(l);
rpt_mutex_lock(&myrpt->lock);
@@ -6179,277 +11596,659 @@ static void *rpt(void *this)
n = 0;
cs[n++] = myrpt->rxchannel;
cs[n++] = myrpt->pchannel;
+ cs[n++] = myrpt->monchannel;
+ if (myrpt->parrotchannel) cs[n++] = myrpt->parrotchannel;
+ if (myrpt->voxchannel) cs[n++] = myrpt->voxchannel;
cs[n++] = myrpt->txpchannel;
- if (myrpt->txchannel != myrpt->rxchannel)
- cs[n++] = myrpt->txchannel;
+ if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
+ if (myrpt->zaptxchannel != myrpt->txchannel)
+ cs[n++] = myrpt->zaptxchannel;
l = myrpt->links.next;
- while (l != &myrpt->links) {
- if ((!l->killme) && (!l->disctime) && l->chan) {
+ while(l != &myrpt->links)
+ {
+ if ((!l->killme) && (!l->disctime) && l->chan)
+ {
cs[n++] = l->chan;
cs[n++] = l->pchan;
}
l = l->next;
}
+ if ((myrpt->topkeystate == 1) &&
+ ((t - myrpt->topkeytime) > TOPKEYWAIT))
+ {
+ myrpt->topkeystate = 2;
+ qsort(myrpt->topkey,TOPKEYN,sizeof(struct rpt_topkey),
+ topcompar);
+ }
rpt_mutex_unlock(&myrpt->lock);
+
+ if (myrpt->topkeystate == 2)
+ {
+ rpt_telemetry(myrpt,TOPKEY,NULL);
+ myrpt->topkeystate = 3;
+ }
ms = MSWAIT;
- who = ast_waitfor_n(cs, n, &ms);
- if (who == NULL)
- ms = 0;
+ for(x = 0; x < n; x++)
+ {
+ int s = -(-x - myrpt->scram - 1) % n;
+ cs1[x] = cs[s];
+ }
+ myrpt->scram++;
+ who = ast_waitfor_n(cs1,n,&ms);
+ if (who == NULL) ms = 0;
elap = MSWAIT - ms;
rpt_mutex_lock(&myrpt->lock);
l = myrpt->links.next;
- while (l != &myrpt->links) {
- if (!l->lasttx) {
- if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME) {
+ while(l != &myrpt->links)
+ {
+ int myrx;
+
+ if (l->voxtotimer) l->voxtotimer -= elap;
+ if (l->voxtotimer < 0) l->voxtotimer = 0;
+
+ if (l->lasttx != l->lasttx1)
+ {
+ voxinit_link(l,!l->lasttx);
+ l->lasttx1 = l->lasttx;
+ }
+ myrx = l->lastrealrx;
+ if ((l->phonemode) && (l->phonevox))
+ {
+ myrx = myrx || (!AST_LIST_EMPTY(&l->rxq));
+ if (l->voxtotimer <= 0)
+ {
+ if (l->voxtostate)
+ {
+ l->voxtotimer = myrpt->p.voxtimeout_ms;
+ l->voxtostate = 0;
+ }
+ else
+ {
+ l->voxtotimer = myrpt->p.voxrecover_ms;
+ l->voxtostate = 1;
+ }
+ }
+ if (!l->voxtostate)
+ myrx = myrx || l->wasvox ;
+ }
+ l->lastrx = myrx;
+ if (l->linklisttimer)
+ {
+ l->linklisttimer -= elap;
+ if (l->linklisttimer < 0) l->linklisttimer = 0;
+ }
+ if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
+ {
+ struct ast_frame lf;
+
+ memset(&lf,0,sizeof(lf));
+ lf.frametype = AST_FRAME_TEXT;
+ lf.subclass = 0;
+ lf.offset = 0;
+ lf.mallocd = 0;
+ lf.samples = 0;
+ l->linklisttimer = LINKLISTTIME;
+ strcpy(lstr,"L ");
+ __mklinklist(myrpt,l,lstr + 2);
+ if (l->chan)
+ {
+ lf.datalen = strlen(lstr) + 1;
+ lf.data = lstr;
+ ast_write(l->chan,&lf);
+ if (debug > 6) ast_log(LOG_NOTICE,
+ "@@@@ node %s sent node string %s to node %s\n",
+ myrpt->name,lstr,l->name);
+ }
+ }
+ if (l->newkey)
+ {
+ if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
+ {
l->retxtimer = 0;
- if (l->chan)
- ast_indicate(l->chan, AST_CONTROL_RADIO_UNKEY);
+ if (l->chan && l->phonemode == 0)
+ {
+ if (l->lasttx)
+ ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
+ else
+ ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
+ }
+ }
+ if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
+ {
+ if (debug == 7) printf("@@@@ rx un-key\n");
+ l->lastrealrx = 0;
+ l->rerxtimer = 0;
+ if (l->lastrx1)
+ {
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ sprintf(str,"RXUNKEY(T),%s",l->name);
+ donodelog(myrpt,str);
+ }
+ if(myrpt->p.duplex)
+ rpt_telemetry(myrpt,LINKUNKEY,l);
+ l->lastrx1 = 0;
+ }
}
- } else
- l->retxtimer = 0;
- if (l->disctime) { /* Disconnect timer active on a channel ? */
+ }
+ if (l->disctime) /* Disconnect timer active on a channel ? */
+ {
l->disctime -= elap;
if (l->disctime <= 0) /* Disconnect timer expired on inbound channel ? */
l->disctime = 0; /* Yep */
}
- if (l->retrytimer) {
+ if (l->retrytimer)
+ {
l->retrytimer -= elap;
- if (l->retrytimer < 0)
- l->retrytimer = 0;
+ if (l->retrytimer < 0) l->retrytimer = 0;
}
/* Tally connect time */
l->connecttime += elap;
/* ignore non-timing channels */
- if (l->elaptime < 0) {
+ if (l->elaptime < 0)
+ {
l = l->next;
continue;
}
l->elaptime += elap;
/* if connection has taken too long */
if ((l->elaptime > MAXCONNECTTIME) &&
- ((!l->chan) || (l->chan->_state != AST_STATE_UP))) {
+ ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
+ {
l->elaptime = 0;
rpt_mutex_unlock(&myrpt->lock);
- if (l->chan)
- ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
+ if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
rpt_mutex_lock(&myrpt->lock);
break;
}
if ((!l->chan) && (!l->retrytimer) && l->outbound &&
- (l->retries++ < MAX_RETRIES) && (l->hasconnected)) {
- if (l->chan)
- ast_hangup(l->chan);
+ (l->retries++ < l->max_retries) && (l->hasconnected))
+ {
+ if (l->chan) ast_hangup(l->chan);
+ l->chan = 0;
rpt_mutex_unlock(&myrpt->lock);
- if ((l->name[0] != '0') && (!l->isremote)) {
- l->retrytimer = MAX_RETRIES + 1;
- } else {
- if (attempt_reconnect(myrpt, l) == -1) {
+ if ((l->name[0] != '0') && (!l->isremote))
+ {
+ if (attempt_reconnect(myrpt,l) == -1)
+ {
l->retrytimer = RETRY_TIMER_MS;
- }
+ }
+ }
+ else
+ {
+ l->retrytimer = l->max_retries + 1;
}
+
rpt_mutex_lock(&myrpt->lock);
break;
}
- if ((!l->chan) && (!l->retrytimer) && l->outbound && (l->retries >= MAX_RETRIES)) {
+ if ((!l->chan) && (!l->retrytimer) && l->outbound &&
+ (l->retries >= l->max_retries))
+ {
/* remove from queue */
remque((struct qelem *) l);
- if (!strcmp(myrpt->cmdnode, l->name))
+ if (!strcmp(myrpt->cmdnode,l->name))
myrpt->cmdnode[0] = 0;
rpt_mutex_unlock(&myrpt->lock);
- if (l->name[0] != '0') {
+ if (l->name[0] != '0')
+ {
if (!l->hasconnected)
- rpt_telemetry(myrpt, CONNFAIL, l);
+ rpt_telemetry(myrpt,CONNFAIL,l);
+ else rpt_telemetry(myrpt,REMDISC,l);
+ }
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ if (!l->hasconnected)
+ sprintf(str,"LINKFAIL,%s",l->name);
else
- rpt_telemetry(myrpt, REMDISC, l);
+ sprintf(str,"LINKDISC,%s",l->name);
+ donodelog(myrpt,str);
}
/* hang-up on call to device */
ast_hangup(l->pchan);
ast_free(l);
- rpt_mutex_lock(&myrpt->lock);
+ rpt_mutex_lock(&myrpt->lock);
break;
}
- if ((!l->chan) && (!l->disctime) && (!l->outbound)) {
- /* remove from queue */
- remque((struct qelem *) l);
- if (!strcmp(myrpt->cmdnode, l->name))
- myrpt->cmdnode[0] = 0;
- rpt_mutex_unlock(&myrpt->lock);
- if (l->name[0] != '0') {
- rpt_telemetry(myrpt, REMDISC, l);
+ if ((!l->chan) && (!l->disctime) && (!l->outbound))
+ {
+ if(debug)ast_log(LOG_NOTICE, "LINKDISC AA\n");
+ /* remove from queue */
+ remque((struct qelem *) l);
+ if(myrpt->links.next==&myrpt->links)channel_revert(myrpt);
+ if (!strcmp(myrpt->cmdnode,l->name))myrpt->cmdnode[0] = 0;
+ rpt_mutex_unlock(&myrpt->lock);
+ if (l->name[0] != '0')
+ {
+ rpt_telemetry(myrpt,REMDISC,l);
}
- /* hang-up on call to device */
- ast_hangup(l->pchan);
- ast_free(l);
- rpt_mutex_lock(&myrpt->lock);
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+ sprintf(str,"LINKDISC,%s",l->name);
+ donodelog(myrpt,str);
+ }
+ /* hang-up on call to device */
+ ast_hangup(l->pchan);
+ ast_free(l);
+ rpt_mutex_lock(&myrpt->lock);
+ break;
+ }
+ l = l->next;
+ }
+ if (myrpt->linkposttimer)
+ {
+ myrpt->linkposttimer -= elap;
+ if (myrpt->linkposttimer < 0) myrpt->linkposttimer = 0;
+ }
+ if (myrpt->linkposttimer <= 0)
+ {
+ int nstr;
+ char lst,*str;
+ time_t now;
+
+ myrpt->linkposttimer = LINKPOSTTIME;
+ nstr = 0;
+ for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
+ {
+ /* if is not a real link, ignore it */
+ if (l->name[0] == '0') continue;
+ nstr += strlen(l->name) + 1;
+ }
+ str = ast_malloc(nstr + 256);
+ if (!str)
+ {
+ ast_log(LOG_NOTICE,"Cannot ast_malloc()\n");
break;
}
- l = l->next;
+ nstr = 0;
+ strcpy(str,"nodes=");
+ for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
+ {
+ /* if is not a real link, ignore it */
+ if (l->name[0] == '0') continue;
+ lst = 'T';
+ if (!l->mode) lst = 'R';
+ if (!l->thisconnected) lst = 'C';
+ if (nstr) strcat(str,",");
+ sprintf(str + strlen(str),"%c%s",lst,l->name);
+ nstr = 1;
+ }
+ p = strstr(tdesc, "version");
+ if(p){
+ int vmajor,vminor;
+ if(sscanf(p, "version %d.%d", &vmajor, &vminor) == 2)
+ sprintf(str + strlen(str),"&apprptvers=%d.%d",vmajor,vminor);
+ }
+ time(&now);
+ sprintf(str + strlen(str),"&apprptuptime=%d",(int)(now-starttime));
+ sprintf(str + strlen(str),
+ "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
+ myrpt->totalkerchunks,myrpt->totalkeyups,(int) myrpt->totaltxtime/1000,
+ myrpt->timeouts,myrpt->totalexecdcommands);
+ rpt_mutex_unlock(&myrpt->lock);
+ statpost(myrpt,str);
+ rpt_mutex_lock(&myrpt->lock);
+ ast_free(str);
+ }
+ if (myrpt->keyposttimer)
+ {
+ myrpt->keyposttimer -= elap;
+ if (myrpt->keyposttimer < 0) myrpt->keyposttimer = 0;
+ }
+ if (myrpt->keyposttimer <= 0)
+ {
+ char str[100];
+ int n = 0;
+ time_t now;
+
+ myrpt->keyposttimer = KEYPOSTTIME;
+ time(&now);
+ if (myrpt->lastkeyedtime)
+ {
+ n = (int)(now - myrpt->lastkeyedtime);
+ }
+ sprintf(str,"keyed=%d&keytime=%d",myrpt->keyed,n);
+ rpt_mutex_unlock(&myrpt->lock);
+ statpost(myrpt,str);
+ rpt_mutex_lock(&myrpt->lock);
}
- if (totx) {
+ if(totx){
myrpt->dailytxtime += elap;
myrpt->totaltxtime += elap;
}
i = myrpt->tailtimer;
- if (myrpt->tailtimer)
- myrpt->tailtimer -= elap;
- if (myrpt->tailtimer < 0)
- myrpt->tailtimer = 0;
- if ((i) && (myrpt->tailtimer == 0))
+ if (myrpt->tailtimer) myrpt->tailtimer -= elap;
+ if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
+ if((i) && (myrpt->tailtimer == 0))
myrpt->tailevent = 1;
- if (myrpt->totimer)
- myrpt->totimer -= elap;
- if (myrpt->totimer < 0)
- myrpt->totimer = 0;
- if (myrpt->idtimer)
- myrpt->idtimer -= elap;
- if (myrpt->idtimer < 0)
- myrpt->idtimer = 0;
- if (myrpt->tmsgtimer)
- myrpt->tmsgtimer -= elap;
- if (myrpt->tmsgtimer < 0)
- myrpt->tmsgtimer = 0;
+ if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
+ if (myrpt->totimer < 0) myrpt->totimer = 0;
+ if (myrpt->idtimer) myrpt->idtimer -= elap;
+ if (myrpt->idtimer < 0) myrpt->idtimer = 0;
+ if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
+ if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
+ if (myrpt->voxtotimer) myrpt->voxtotimer -= elap;
+ if (myrpt->voxtotimer < 0) myrpt->voxtotimer = 0;
+ if (myrpt->exttx)
+ {
+ myrpt->parrottimer = myrpt->p.parrottime;
+ }
+ else
+ {
+ if (myrpt->parrottimer) myrpt->parrottimer -= elap;
+ if (myrpt->parrottimer < 0) myrpt->parrottimer = 0;
+ }
/* do macro timers */
- if (myrpt->macrotimer)
- myrpt->macrotimer -= elap;
- if (myrpt->macrotimer < 0)
- myrpt->macrotimer = 0;
- /* do gosub timers */
- if (myrpt->gosubtimer)
- myrpt->gosubtimer -= elap;
- if (myrpt->gosubtimer < 0)
- myrpt->gosubtimer = 0;
+ if (myrpt->macrotimer) myrpt->macrotimer -= elap;
+ if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
+ /* do local dtmf timer */
+ if (myrpt->dtmf_local_timer)
+ {
+ if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
+ if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
+ }
+ do_dtmf_local(myrpt,0);
/* Execute scheduler appx. every 2 tenths of a second */
- if (myrpt->skedtimer <= 0) {
+ if (myrpt->skedtimer <= 0){
myrpt->skedtimer = 200;
do_scheduler(myrpt);
- } else
- myrpt->skedtimer -= elap;
- if (!ms) {
+ }
+ else
+ myrpt->skedtimer -=elap;
+ if (!ms)
+ {
rpt_mutex_unlock(&myrpt->lock);
continue;
}
+ if (myrpt->p.parrotmode && (myrpt->parrotstate == 1) &&
+ (myrpt->parrottimer <= 0))
+ {
+
+ ci.confno = 0;
+ ci.confmode = 0;
+ ci.chan = 0;
+
+ /* first put the channel on the conference in announce mode */
+ if (ioctl(myrpt->parrotchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
+ break;
+ }
+ if (myrpt->parrotstream)
+ ast_closestream(myrpt->parrotstream);
+ myrpt->parrotstream = NULL;
+ myrpt->parrotstate = 2;
+ rpt_telemetry(myrpt,PARROT,(struct rpt_link *) myrpt->parrotcnt++);
+ }
+ if (myrpt->cmdAction.state == CMD_STATE_READY)
+ { /* there is a command waiting to be processed */
+ int status;
+ myrpt->cmdAction.state = CMD_STATE_EXECUTING;
+ // lose the lock
+ rpt_mutex_unlock(&myrpt->lock);
+ // do the function
+ status = (*function_table[myrpt->cmdAction.functionNumber].function)(myrpt,myrpt->cmdAction.param, myrpt->cmdAction.digits, myrpt->cmdAction.command_source, NULL);
+ // get the lock again
+ rpt_mutex_lock(&myrpt->lock);
+ myrpt->cmdAction.state = CMD_STATE_IDLE;
+ } /* if myrpt->cmdAction.state == CMD_STATE_READY */
+
c = myrpt->macrobuf[0];
- if (c && (!myrpt->macrotimer)) {
+ time(&t);
+ if (c && (!myrpt->macrotimer) &&
+ starttime && (t > (starttime + START_DELAY)))
+ {
+ char cin = c & 0x7f;
myrpt->macrotimer = MACROTIME;
- memmove(myrpt->macrobuf, myrpt->macrobuf + 1, sizeof(myrpt->macrobuf) - 1);
- if ((c == 'p') || (c == 'P'))
+ memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
+ if ((cin == 'p') || (cin == 'P'))
myrpt->macrotimer = MACROPTIME;
rpt_mutex_unlock(&myrpt->lock);
- local_dtmf_helper(myrpt, c);
- } else
- rpt_mutex_unlock(&myrpt->lock);
- c = myrpt->gosubbuf[0];
- if (c && (!myrpt->gosubtimer)) {
- myrpt->gosubtimer = GOSUBTIME;
- memmove(myrpt->gosubbuf, myrpt->gosubbuf + 1, sizeof(myrpt->gosubbuf) - 1);
- if ((c == 'p') || (c == 'P'))
- myrpt->gosubtimer = GOSUBPTIME;
- rpt_mutex_unlock(&myrpt->lock);
- local_dtmf_helper(myrpt, c);
- } else
- rpt_mutex_unlock(&myrpt->lock);
- if (who == myrpt->rxchannel) { /* if it was a read from rx */
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ sprintf(str,"DTMF(M),MAIN,%c",cin);
+ donodelog(myrpt,str);
+ }
+ local_dtmf_helper(myrpt,c);
+ } else rpt_mutex_unlock(&myrpt->lock);
+ if (who == myrpt->rxchannel) /* if it was a read from rx */
+ {
+ int ismuted;
+
f = ast_read(myrpt->rxchannel);
- if (!f) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (!f)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
break;
}
- if (f->frametype == AST_FRAME_VOICE) {
+ if (f->frametype == AST_FRAME_VOICE)
+ {
#ifdef _MDC_DECODE_H_
unsigned char ubuf[2560];
short *sp;
int n;
#endif
- if (!myrpt->localtx) {
- memset(f->data, 0, f->datalen);
+ if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
+ memset(f->data,0,f->datalen);
}
#ifdef _MDC_DECODE_H_
sp = (short *) f->data;
/* convert block to unsigned char */
- for (n = 0; n < f->datalen / 2; n++) {
+ for(n = 0; n < f->datalen / 2; n++)
+ {
ubuf[n] = (*sp++ >> 8) + 128;
}
- n = mdc_decoder_process_samples(myrpt->mdc, ubuf, f->datalen / 2);
- if (n == 1) {
- unsigned char op, arg;
- unsigned short unitID;
-
- mdc_decoder_get_packet(myrpt->mdc, &op, &arg, &unitID);
- if (debug > 2) {
- ast_log(LOG_NOTICE, "Got (single-length) packet:\n");
- ast_log(LOG_NOTICE, "op: %02x, arg: %02x, UnitID: %04x\n", op & 255, arg & 255, unitID);
- }
- if ((op == 1) && (arg == 0)) {
- myrpt->lastunit = unitID;
- }
+ n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
+ if (n == 1)
+ {
+ unsigned char op,arg;
+ unsigned short unitID;
+
+ mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
+ if (debug > 2)
+ {
+ ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
+ ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
+ op & 255,arg & 255,unitID);
+ }
+ if ((op == 1) && (arg == 0))
+ {
+ myrpt->lastunit = unitID;
+ mdc1200_notify(myrpt,NULL,myrpt->lastunit);
+ mdc1200_send(myrpt,myrpt->lastunit);
+ }
}
- if ((debug > 2) && (i == 2)) {
- unsigned char op, arg, ex1, ex2, ex3, ex4;
+ if ((debug > 2) && (i == 2))
+ {
+ unsigned char op,arg,ex1,ex2,ex3,ex4;
unsigned short unitID;
- mdc_decoder_get_double_packet(myrpt->mdc, &op, &arg, &unitID, &ex1, &ex2, &ex3, &ex4);
- ast_log(LOG_NOTICE, "Got (double-length) packet:\n");
- ast_log(LOG_NOTICE, "op: %02x, arg: %02x, UnitID: %04x\n", op & 255, arg & 255, unitID);
- ast_log(LOG_NOTICE, "ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
+ mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
+ &ex1,&ex2,&ex3,&ex4);
+ ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
+ ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
+ op & 255,arg & 255,unitID);
+ ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
}
#endif
#ifdef __RPT_NOTCH
/* apply inbound filters, if any */
- rpt_filter(myrpt, f->data, f->datalen / 2);
+ rpt_filter(myrpt,f->data,f->datalen / 2);
+#endif
+ if (ioctl(myrpt->zaprxchannel->fds[0], ZT_GETCONFMUTE, &ismuted) == -1)
+ {
+ ismuted = 0;
+ }
+ if (dtmfed) ismuted = 1;
+ dtmfed = 0;
+ if (ismuted)
+ {
+ memset(f->data,0,f->datalen);
+ if (myrpt->lastf1)
+ memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
+ if (myrpt->lastf2)
+ memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
+ }
+ if (f) f2 = ast_frdup(f);
+ else f2 = NULL;
+ f1 = myrpt->lastf2;
+ myrpt->lastf2 = myrpt->lastf1;
+ myrpt->lastf1 = f2;
+ if (ismuted)
+ {
+ if (myrpt->lastf1)
+ memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
+ if (myrpt->lastf2)
+ memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
+ }
+ if (f1)
+ {
+ ast_write(myrpt->pchannel,f1);
+ ast_frfree(f1);
+ }
+ }
+#ifndef OLD_ASTERISK
+ else if (f->frametype == AST_FRAME_DTMF_BEGIN)
+ {
+ if (myrpt->lastf1)
+ memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
+ if (myrpt->lastf2)
+ memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
+ dtmfed = 1;
+ }
#endif
- ast_write(myrpt->pchannel, f);
- } else if (f->frametype == AST_FRAME_DTMF) {
+ else if (f->frametype == AST_FRAME_DTMF)
+ {
c = (char) f->subclass; /* get DTMF char */
ast_frfree(f);
- if (!myrpt->keyed)
- continue;
- local_dtmf_helper(myrpt, c);
+ if (myrpt->lastf1)
+ memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
+ if (myrpt->lastf2)
+ memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
+ dtmfed = 1;
+ if (!myrpt->keyed) continue;
+ c = func_xlat(myrpt,c,&myrpt->p.inxlat);
+ if (c) local_dtmf_helper(myrpt,c);
continue;
- } else if (f->frametype == AST_FRAME_CONTROL) {
- if (f->subclass == AST_CONTROL_HANGUP) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ }
+ else 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 ((!lasttx) || (myrpt->p.duplex > 1)) {
- ast_debug(8, "@@@@ rx key\n");
+ if (f->subclass == AST_CONTROL_RADIO_KEY)
+ {
+ if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
+ {
+ if (debug == 7) printf("@@@@ rx key\n");
myrpt->keyed = 1;
+ time(&myrpt->lastkeyedtime);
+ myrpt->keyposttimer = KEYPOSTSHORTTIME;
+ }
+ if (myrpt->p.archivedir)
+ {
+ donodelog(myrpt,"RXKEY,MAIN");
}
+ if (f->datalen && f->data)
+ {
+ char *val, busy = 0;
+
+ if (debug) ast_log(LOG_NOTICE,"Got PL %s on node %s\n",(char *)f->data,myrpt->name);
+ // ctcss code autopatch initiate
+ if (strstr((char *)f->data,"/M/")&& !myrpt->macropatch)
+ {
+ char val[16];
+ strcat(val,"*6");
+ myrpt->macropatch=1;
+ rpt_mutex_lock(&myrpt->lock);
+ if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
+ rpt_mutex_unlock(&myrpt->lock);
+ busy=1;
+ }
+ if(!busy){
+ myrpt->macrotimer = MACROTIME;
+ strncat(myrpt->macrobuf,val,MAXMACRO - 1);
+ if (!busy) strcpy(myrpt->lasttone,(char*)f->data);
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ }
+ else if (strcmp((char *)f->data,myrpt->lasttone))
+ {
+ val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.tonemacro, (char *)f->data);
+ if (val)
+ {
+ if (debug) ast_log(LOG_NOTICE,"Tone %s doing %s on node %s\n",(char *) f->data,val,myrpt->name);
+ rpt_mutex_lock(&myrpt->lock);
+ if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
+ rpt_mutex_unlock(&myrpt->lock);
+ busy=1;
+ }
+ if(!busy){
+ myrpt->macrotimer = MACROTIME;
+ strncat(myrpt->macrobuf,val,MAXMACRO - 1);
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ }
+ if (!busy) strcpy(myrpt->lasttone,(char*)f->data);
+ }
+ } else myrpt->lasttone[0] = 0;
}
/* if RX un-key */
- if (f->subclass == AST_CONTROL_RADIO_UNKEY) {
- if ((!lasttx) || (myrpt->p.duplex > 1)) {
- ast_debug(8, "@@@@ rx un-key\n");
- if (myrpt->keyed) {
- rpt_telemetry(myrpt, UNKEY, NULL);
+ if (f->subclass == AST_CONTROL_RADIO_UNKEY)
+ {
+ if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
+ {
+ if (debug == 7) printf("@@@@ rx un-key\n");
+ if(myrpt->p.duplex && myrpt->keyed) {
+ rpt_telemetry(myrpt,UNKEY,NULL);
}
- myrpt->keyed = 0;
+ }
+ myrpt->keyed = 0;
+ time(&myrpt->lastkeyedtime);
+ myrpt->keyposttimer = KEYPOSTSHORTTIME;
+ if (myrpt->p.archivedir)
+ {
+ donodelog(myrpt,"RXUNKEY,MAIN");
}
}
}
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 */
+ {
f = ast_read(myrpt->pchannel);
- if (!f) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (!f)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
break;
}
- if (f->frametype == AST_FRAME_VOICE) {
- ast_write(myrpt->txpchannel, f);
+ if (f->frametype == AST_FRAME_VOICE)
+ {
+ ast_write(myrpt->txpchannel,f);
}
- if (f->frametype == AST_FRAME_CONTROL) {
- if (f->subclass == AST_CONTROL_HANGUP) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (f->frametype == AST_FRAME_CONTROL)
+ {
+ if (f->subclass == AST_CONTROL_HANGUP)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
@@ -6457,15 +12256,85 @@ static void *rpt(void *this)
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 */
+ {
f = ast_read(myrpt->txchannel);
- if (!f) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ 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;
+ }
+ if (who == myrpt->zaptxchannel) /* if it was a read from pseudo-tx */
+ {
+ f = ast_read(myrpt->zaptxchannel);
+ if (!f)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
break;
}
- if (f->frametype == AST_FRAME_CONTROL) {
- if (f->subclass == AST_CONTROL_HANGUP) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (f->frametype == AST_FRAME_VOICE)
+ {
+ struct ast_frame *f1;
+
+ if (myrpt->p.duplex < 2)
+ {
+ if (myrpt->txrealkeyed)
+ {
+ if ((!myfirst) && myrpt->callmode)
+ {
+ x = 0;
+ AST_LIST_TRAVERSE(&myrpt->txq, f1,
+ frame_list) x++;
+ for(;x < myrpt->p.simplexpatchdelay; x++)
+ {
+ f1 = ast_frdup(f);
+ memset(f1->data,0,f1->datalen);
+ AST_LIST_INSERT_TAIL(&myrpt->txq,f1,frame_list);
+ }
+ myfirst = 1;
+ }
+ f1 = ast_frdup(f);
+ AST_LIST_INSERT_TAIL(&myrpt->txq,
+ f1,frame_list);
+ } else myfirst = 0;
+ x = 0;
+ AST_LIST_TRAVERSE(&myrpt->txq, f1,
+ frame_list) x++;
+ if (!x)
+ {
+ memset(f->data,0,f->datalen);
+ }
+ else
+ {
+ ast_frfree(f);
+ f = AST_LIST_REMOVE_HEAD(&myrpt->txq,
+ frame_list);
+ }
+ }
+ else
+ {
+ while((f1 = AST_LIST_REMOVE_HEAD(&myrpt->txq,
+ frame_list))) ast_frfree(f1);
+ }
+ ast_write(myrpt->txchannel,f);
+ }
+ if (f->frametype == AST_FRAME_CONTROL)
+ {
+ if (f->subclass == AST_CONTROL_HANGUP)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
@@ -6476,35 +12345,72 @@ static void *rpt(void *this)
toexit = 0;
rpt_mutex_lock(&myrpt->lock);
l = myrpt->links.next;
- while (l != &myrpt->links) {
- if (l->disctime) {
+ while(l != &myrpt->links)
+ {
+ int remnomute;
+ struct timeval now;
+
+ if (l->disctime)
+ {
l = l->next;
continue;
}
- if (who == l->chan) { /* if it was a read from rx */
- remrx = 0;
- /* see if any other links are receiving */
- m = myrpt->links.next;
- while (m != &myrpt->links) {
- /* if not us, count it */
- if ((m != l) && (m->lastrx))
- remrx = 1;
- m = m->next;
- }
- rpt_mutex_unlock(&myrpt->lock);
- totx = (((l->isremote) ? myrpt->localtx :
+
+ remrx = 0;
+ /* see if any other links are receiving */
+ m = myrpt->links.next;
+ while(m != &myrpt->links)
+ {
+ /* if not us, count it */
+ if ((m != l) && (m->lastrx)) remrx = 1;
+ m = m->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ now = ast_tvnow();
+ if ((who == l->chan) || (!l->lastlinktv.tv_sec) ||
+ (ast_tvdiff_ms(now,l->lastlinktv) >= 19))
+ {
+ l->lastlinktv = now;
+ remnomute = myrpt->localtx &&
+ (!(myrpt->cmdnode[0] ||
+ (myrpt->dtmfidx > -1)));
+ totx = (((l->isremote) ? (remnomute) :
myrpt->exttx) || remrx) && l->mode;
- if (l->chan && (l->lasttx != totx)) {
- if (totx) {
- ast_indicate(l->chan, AST_CONTROL_RADIO_KEY);
- } else {
- ast_indicate(l->chan, AST_CONTROL_RADIO_UNKEY);
+ if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
+ {
+ if (totx)
+ {
+ ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
+ }
+ else
+ {
+ ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
+ }
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ if (totx)
+ sprintf(str,"TXKEY,%s",l->name);
+ else
+ sprintf(str,"TXUNKEY,%s",l->name);
+ donodelog(myrpt,str);
}
}
l->lasttx = totx;
+ }
+ rpt_mutex_lock(&myrpt->lock);
+ if (who == l->chan) /* if it was a read from rx */
+ {
+ rpt_mutex_unlock(&myrpt->lock);
f = ast_read(l->chan);
- if (!f) {
- if ((!l->disced) && (!l->outbound)) {
+ if (!f)
+ {
+ rpt_mutex_lock(&myrpt->lock);
+ __kickshort(myrpt);
+ rpt_mutex_unlock(&myrpt->lock);
+ if ((!l->disced) && (!l->outbound))
+ {
if ((l->name[0] == '0') || l->isremote)
l->disctime = 1;
else
@@ -6515,31 +12421,49 @@ static void *rpt(void *this)
break;
}
- if (l->retrytimer) {
+ if (l->retrytimer)
+ {
+ ast_hangup(l->chan);
+ l->chan = 0;
rpt_mutex_lock(&myrpt->lock);
break;
}
- if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected)) {
+ if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
+ {
rpt_mutex_lock(&myrpt->lock);
- ast_hangup(l->chan);
+ if (l->chan) ast_hangup(l->chan);
l->chan = 0;
- rpt_mutex_unlock(&myrpt->lock);
- if (attempt_reconnect(myrpt, l) == -1) {
- l->retrytimer = RETRY_TIMER_MS;
- }
- rpt_mutex_lock(&myrpt->lock);
+ l->hasconnected = 1;
+ l->retrytimer = RETRY_TIMER_MS;
+ l->elaptime = 0;
+ l->connecttime = 0;
+ l->thisconnected = 0;
break;
}
rpt_mutex_lock(&myrpt->lock);
/* remove from queue */
remque((struct qelem *) l);
- if (!strcmp(myrpt->cmdnode, l->name))
+ if (!strcmp(myrpt->cmdnode,l->name))
myrpt->cmdnode[0] = 0;
+ __kickshort(myrpt);
rpt_mutex_unlock(&myrpt->lock);
if (!l->hasconnected)
- rpt_telemetry(myrpt, CONNFAIL, l);
- else if (l->disced != 2)
- rpt_telemetry(myrpt, REMDISC, l);
+ rpt_telemetry(myrpt,CONNFAIL,l);
+ else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ if (!l->hasconnected)
+ sprintf(str,"LINKFAIL,%s",l->name);
+ else
+ sprintf(str,"LINKDISC,%s",l->name);
+ donodelog(myrpt,str);
+ }
+ if (l->lastf1) ast_frfree(l->lastf1);
+ l->lastf1 = NULL;
+ if (l->lastf2) ast_frfree(l->lastf2);
+ l->lastf2 = NULL;
/* hang-up on call to device */
ast_hangup(l->chan);
ast_hangup(l->pchan);
@@ -6547,43 +12471,192 @@ static void *rpt(void *this)
rpt_mutex_lock(&myrpt->lock);
break;
}
- if (f->frametype == AST_FRAME_VOICE) {
- if (!l->lastrx) {
- memset(f->data, 0, f->datalen);
+ if (f->frametype == AST_FRAME_VOICE)
+ {
+ int ismuted,n1;
+
+ if ((l->phonemode) && (l->phonevox))
+ {
+ n1 = dovox(&l->vox,
+ f->data,f->datalen / 2);
+ if (n1 != l->wasvox)
+ {
+ if (debug)ast_log(LOG_DEBUG,"Link Node %s, vox %d\n",l->name,n1);
+ l->wasvox = n1;
+ l->voxtostate = 0;
+ if (n1) l->voxtotimer = myrpt->p.voxtimeout_ms;
+ else l->voxtotimer = 0;
+ }
+ if (l->lastrealrx || n1)
+ {
+ if (!myfirst)
+ {
+ x = 0;
+ AST_LIST_TRAVERSE(&l->rxq, f1,
+ frame_list) x++;
+ for(;x < myrpt->p.simplexphonedelay; x++)
+ {
+ f1 = ast_frdup(f);
+ memset(f1->data,0,f1->datalen);
+ AST_LIST_INSERT_TAIL(&l->rxq,
+ f1,frame_list);
+ }
+ myfirst = 1;
+ }
+ f1 = ast_frdup(f);
+ AST_LIST_INSERT_TAIL(&l->rxq,f1,frame_list);
+ } else myfirst = 0;
+ x = 0;
+ AST_LIST_TRAVERSE(&l->rxq, f1,frame_list) x++;
+ if (!x)
+ {
+ memset(f->data,0,f->datalen);
+ }
+ else
+ {
+ ast_frfree(f);
+ f = AST_LIST_REMOVE_HEAD(&l->rxq,frame_list);
+ }
+ if (ioctl(l->chan->fds[0], ZT_GETCONFMUTE, &ismuted) == -1)
+ {
+ ismuted = 0;
+ }
+ /* if not receiving, zero-out audio */
+ ismuted |= (!l->lastrx);
+ if (l->dtmfed && l->phonemode) ismuted = 1;
+ l->dtmfed = 0;
+ if (ismuted)
+ {
+ memset(f->data,0,f->datalen);
+ if (l->lastf1)
+ memset(l->lastf1->data,0,l->lastf1->datalen);
+ if (l->lastf2)
+ memset(l->lastf2->data,0,l->lastf2->datalen);
+ }
+ if (f) f2 = ast_frdup(f);
+ else f2 = NULL;
+ f1 = l->lastf2;
+ l->lastf2 = l->lastf1;
+ l->lastf1 = f2;
+ if (ismuted)
+ {
+ if (l->lastf1)
+ memset(l->lastf1->data,0,l->lastf1->datalen);
+ if (l->lastf2)
+ memset(l->lastf2->data,0,l->lastf2->datalen);
+ }
+ if (f1)
+ {
+ ast_write(l->pchan,f1);
+ ast_frfree(f1);
+ }
+ }
+ else
+ {
+ if (!l->lastrx)
+ memset(f->data,0,f->datalen);
+ ast_write(l->pchan,f);
}
- ast_write(l->pchan, f);
}
- if (f->frametype == AST_FRAME_TEXT) {
- handle_link_data(myrpt, l, f->data);
+#ifndef OLD_ASTERISK
+ else if (f->frametype == AST_FRAME_DTMF_BEGIN)
+ {
+ if (l->lastf1)
+ memset(l->lastf1->data,0,l->lastf1->datalen);
+ if (l->lastf2)
+ memset(l->lastf2->data,0,l->lastf2->datalen);
+ l->dtmfed = 1;
+ }
+#endif
+ if (f->frametype == AST_FRAME_TEXT)
+ {
+ handle_link_data(myrpt,l,f->data);
}
- if (f->frametype == AST_FRAME_DTMF) {
- handle_link_phone_dtmf(myrpt, l, f->subclass);
+ if (f->frametype == AST_FRAME_DTMF)
+ {
+ if (l->lastf1)
+ memset(l->lastf1->data,0,l->lastf1->datalen);
+ if (l->lastf2)
+ memset(l->lastf2->data,0,l->lastf2->datalen);
+ l->dtmfed = 1;
+ handle_link_phone_dtmf(myrpt,l,f->subclass);
}
- if (f->frametype == AST_FRAME_CONTROL) {
- if (f->subclass == AST_CONTROL_ANSWER) {
+ if (f->frametype == AST_FRAME_CONTROL)
+ {
+ if (f->subclass == AST_CONTROL_ANSWER)
+ {
char lconnected = l->connected;
+
+ __kickshort(myrpt);
l->connected = 1;
l->hasconnected = 1;
+ l->thisconnected = 1;
l->elaptime = -1;
- l->retries = 0;
+ if (!l->phonemode) send_newkey(l->chan);
+ if (!l->isremote) l->retries = 0;
if (!lconnected)
- rpt_telemetry(myrpt, CONNECTED, l);
+ {
+ rpt_telemetry(myrpt,CONNECTED,l);
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ if (l->mode)
+ sprintf(str,"LINKTRX,%s",l->name);
+ else
+ sprintf(str,"LINKMONITOR,%s",l->name);
+ donodelog(myrpt,str);
+ }
+ }
else
l->reconnects++;
}
/* if RX key */
- if (f->subclass == AST_CONTROL_RADIO_KEY) {
- ast_debug(8, "@@@@ rx key\n");
- l->lastrx = 1;
+ if (f->subclass == AST_CONTROL_RADIO_KEY)
+ {
+ if (debug == 7 ) printf("@@@@ rx key\n");
+ l->lastrealrx = 1;
+ l->rerxtimer = 0;
+ if (!l->lastrx1)
+ {
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ sprintf(str,"RXKEY,%s",l->name);
+ donodelog(myrpt,str);
+ }
+ l->lastrx1 = 1;
+ }
}
/* if RX un-key */
- if (f->subclass == AST_CONTROL_RADIO_UNKEY) {
- ast_debug(8, "@@@@ rx un-key\n");
- l->lastrx = 0;
+ if (f->subclass == AST_CONTROL_RADIO_UNKEY)
+ {
+ if (debug == 7) printf("@@@@ rx un-key\n");
+ l->lastrealrx = 0;
+ l->rerxtimer = 0;
+ if (l->lastrx1)
+ {
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ sprintf(str,"RXUNKEY,%s",l->name);
+ donodelog(myrpt,str);
+ }
+ l->lastrx1 = 0;
+ if(myrpt->p.duplex)
+ rpt_telemetry(myrpt,LINKUNKEY,l);
+ }
}
- if (f->subclass == AST_CONTROL_HANGUP) {
+ if (f->subclass == AST_CONTROL_HANGUP)
+ {
ast_frfree(f);
- if ((!l->outbound) && (!l->disced)) {
+ rpt_mutex_lock(&myrpt->lock);
+ __kickshort(myrpt);
+ rpt_mutex_unlock(&myrpt->lock);
+ if ((!l->outbound) && (!l->disced))
+ {
if ((l->name[0] == '0') || l->isremote)
l->disctime = 1;
else
@@ -6593,31 +12666,49 @@ static void *rpt(void *this)
l->chan = 0;
break;
}
- if (l->retrytimer) {
+ if (l->retrytimer)
+ {
+ if (l->chan) ast_hangup(l->chan);
+ l->chan = 0;
rpt_mutex_lock(&myrpt->lock);
break;
}
- if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected)) {
+ if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
+ {
rpt_mutex_lock(&myrpt->lock);
- ast_hangup(l->chan);
+ if (l->chan) ast_hangup(l->chan);
l->chan = 0;
- rpt_mutex_unlock(&myrpt->lock);
- if (attempt_reconnect(myrpt, l) == -1) {
- l->retrytimer = RETRY_TIMER_MS;
- }
- rpt_mutex_lock(&myrpt->lock);
+ l->hasconnected = 1;
+ l->elaptime = 0;
+ l->retrytimer = RETRY_TIMER_MS;
+ l->connecttime = 0;
+ l->thisconnected = 0;
break;
}
rpt_mutex_lock(&myrpt->lock);
/* remove from queue */
remque((struct qelem *) l);
- if (!strcmp(myrpt->cmdnode, l->name))
+ if (!strcmp(myrpt->cmdnode,l->name))
myrpt->cmdnode[0] = 0;
+ __kickshort(myrpt);
rpt_mutex_unlock(&myrpt->lock);
if (!l->hasconnected)
- rpt_telemetry(myrpt, CONNFAIL, l);
- else if (l->disced != 2)
- rpt_telemetry(myrpt, REMDISC, l);
+ rpt_telemetry(myrpt,CONNFAIL,l);
+ else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ if (!l->hasconnected)
+ sprintf(str,"LINKFAIL,%s",l->name);
+ else
+ sprintf(str,"LINKDISC,%s",l->name);
+ donodelog(myrpt,str);
+ }
+ if (l->lastf1) ast_frfree(l->lastf1);
+ l->lastf1 = NULL;
+ if (l->lastf2) ast_frfree(l->lastf2);
+ l->lastf2 = NULL;
/* hang-up on call to device */
ast_hangup(l->chan);
ast_hangup(l->pchan);
@@ -6630,22 +12721,26 @@ static void *rpt(void *this)
rpt_mutex_lock(&myrpt->lock);
break;
}
- if (who == l->pchan) {
+ if (who == l->pchan)
+ {
rpt_mutex_unlock(&myrpt->lock);
f = ast_read(l->pchan);
- if (!f) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (!f)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
toexit = 1;
rpt_mutex_lock(&myrpt->lock);
break;
}
- if (f->frametype == AST_FRAME_VOICE) {
- if (l->chan)
- ast_write(l->chan, f);
+ if (f->frametype == AST_FRAME_VOICE)
+ {
+ if (l->chan) ast_write(l->chan,f);
}
- if (f->frametype == AST_FRAME_CONTROL) {
- if (f->subclass == AST_CONTROL_HANGUP) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (f->frametype == AST_FRAME_CONTROL)
+ {
+ if (f->subclass == AST_CONTROL_HANGUP)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
toexit = 1;
rpt_mutex_lock(&myrpt->lock);
@@ -6659,17 +12754,114 @@ static void *rpt(void *this)
l = l->next;
}
rpt_mutex_unlock(&myrpt->lock);
- if (toexit)
- break;
- if (who == myrpt->txpchannel) { /* if it was a read from remote tx */
+ if (toexit) break;
+ if (who == myrpt->monchannel)
+ {
+ f = ast_read(myrpt->monchannel);
+ if (!f)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
+ break;
+ }
+ if (f->frametype == AST_FRAME_VOICE)
+ {
+ if (myrpt->monstream)
+ ast_writestream(myrpt->monstream,f);
+ }
+ 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;
+ }
+ if (myrpt->parrotchannel && (who == myrpt->parrotchannel))
+ {
+ f = ast_read(myrpt->parrotchannel);
+ if (!f)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
+ break;
+ }
+ if (!myrpt->p.parrotmode)
+ {
+ char myfname[300];
+
+ if (myrpt->parrotstream)
+ {
+ ast_closestream(myrpt->parrotstream);
+ myrpt->parrotstream = 0;
+ }
+ sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
+ strcat(myfname,".wav");
+ unlink(myfname);
+ } else if (f->frametype == AST_FRAME_VOICE)
+ {
+ if (myrpt->parrotstream)
+ ast_writestream(myrpt->parrotstream,f);
+ }
+ 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;
+ }
+ if (myrpt->voxchannel && (who == myrpt->voxchannel))
+ {
+ f = ast_read(myrpt->voxchannel);
+ if (!f)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
+ break;
+ }
+ if (f->frametype == AST_FRAME_VOICE)
+ {
+ n = dovox(&myrpt->vox,f->data,f->datalen / 2);
+ if (n != myrpt->wasvox)
+ {
+ if (debug) ast_log(LOG_DEBUG,"Node %s, vox %d\n",myrpt->name,n);
+ myrpt->wasvox = n;
+ myrpt->voxtostate = 0;
+ if (n) myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
+ else myrpt->voxtotimer = 0;
+ }
+ }
+ 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;
+ }
+ if (who == myrpt->txpchannel) /* if it was a read from remote tx */
+ {
f = ast_read(myrpt->txpchannel);
- if (!f) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (!f)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
break;
}
- if (f->frametype == AST_FRAME_CONTROL) {
- if (f->subclass == AST_CONTROL_HANGUP) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (f->frametype == AST_FRAME_CONTROL)
+ {
+ if (f->subclass == AST_CONTROL_HANGUP)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
@@ -6680,66 +12872,93 @@ static void *rpt(void *this)
}
usleep(100000);
ast_hangup(myrpt->pchannel);
+ ast_hangup(myrpt->monchannel);
+ if (myrpt->parrotchannel) ast_hangup(myrpt->parrotchannel);
+ myrpt->parrotstate = 0;
+ if (myrpt->voxchannel) ast_hangup(myrpt->voxchannel);
ast_hangup(myrpt->txpchannel);
- if (myrpt->txchannel != myrpt->rxchannel)
- ast_hangup(myrpt->txchannel);
+ if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
+ if (myrpt->zaptxchannel != myrpt->txchannel) ast_hangup(myrpt->zaptxchannel);
+ if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
+ myrpt->lastf1 = NULL;
+ if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
+ myrpt->lastf2 = NULL;
ast_hangup(myrpt->rxchannel);
rpt_mutex_lock(&myrpt->lock);
l = myrpt->links.next;
- while (l != &myrpt->links) {
+ while(l != &myrpt->links)
+ {
struct rpt_link *ll = l;
/* remove from queue */
remque((struct qelem *) l);
/* hang-up on call to device */
- if (l->chan)
- ast_hangup(l->chan);
+ if (l->chan) ast_hangup(l->chan);
ast_hangup(l->pchan);
l = l->next;
ast_free(ll);
}
+ if (myrpt->xlink == 1) myrpt->xlink = 2;
rpt_mutex_unlock(&myrpt->lock);
- ast_debug(1, "@@@@ rpt:Hung up channel\n");
+ if (debug) printf("@@@@ rpt:Hung up channel\n");
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
return NULL;
}
-static void *rpt_master(void *config)
+static void *rpt_master(void *ignore)
{
- int i, n;
- struct ast_config *cfg;
- char *this;
- const char *val;
+int i,n;
+pthread_attr_t attr;
+struct ast_config *cfg;
+char *this,*val;
+ /* init nodelog queue */
+ nodelog.next = nodelog.prev = &nodelog;
/* go thru all the specified repeaters */
this = NULL;
n = 0;
- rpt_vars[n].cfg = config;
+#ifndef OLD_ASTERISK
+ /* wait until asterisk starts */
+ while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
+ usleep(250000);
+#endif
+#ifdef NEW_ASTERISK
+ rpt_vars[n].cfg = ast_config_load("rpt.conf",config_flags);
+#else
+ rpt_vars[n].cfg = ast_config_load("rpt.conf");
+#endif
cfg = rpt_vars[n].cfg;
if (!cfg) {
ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
pthread_exit(NULL);
}
- while ((this = ast_category_browse(cfg, this)) != NULL) {
- for (i = 0; i < strlen(this); i++) {
- if ((this[i] < '0') || (this[i] > '9'))
+ while((this = ast_category_browse(cfg,this)) != NULL)
+ {
+ for(i = 0 ; i < strlen(this) ; i++){
+ if((this[i] < '0') || (this[i] > '9'))
break;
}
- if (i != strlen(this))
- continue; /* Not a node defn */
- memset(&rpt_vars[n], 0, sizeof(rpt_vars[n]));
+ if(i != strlen(this)) continue; /* Not a node defn */
+ memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
rpt_vars[n].name = ast_strdup(this);
- val = ast_variable_retrieve(cfg, this, "rxchannel");
- if (val)
- rpt_vars[n].rxchanname = ast_strdup(val);
- val = ast_variable_retrieve(cfg, this, "txchannel");
- if (val)
- rpt_vars[n].txchanname = ast_strdup(val);
- val = ast_variable_retrieve(cfg, this, "remote");
- if (val)
- rpt_vars[n].remote = ast_strdup(val);
+ val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
+ if (val) rpt_vars[n].rxchanname = ast_strdup(val);
+ val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
+ if (val) rpt_vars[n].txchanname = ast_strdup(val);
+ rpt_vars[n].remote = 0;
+ rpt_vars[n].remoterig = "";
+ val = (char *) ast_variable_retrieve(cfg,this,"remote");
+ if (val)
+ {
+ rpt_vars[n].remoterig = ast_strdup(val);
+ rpt_vars[n].remote = 1;
+ }
+ val = (char *) ast_variable_retrieve(cfg,this,"radiotype");
+ if (val) rpt_vars[n].remoterig = ast_strdup(val);
ast_mutex_init(&rpt_vars[n].lock);
+ ast_mutex_init(&rpt_vars[n].remlock);
+ ast_mutex_init(&rpt_vars[n].statpost_lock);
rpt_vars[n].tele.next = &rpt_vars[n].tele;
rpt_vars[n].tele.prev = &rpt_vars[n].tele;
rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
@@ -6753,55 +12972,137 @@ static void *rpt_master(void *config)
ast_config_destroy(cfg);
/* start em all */
- for (i = 0; i < n; i++) {
- load_rpt_vars(i, 1);
+ for(i = 0; i < n; i++)
+ {
+ load_rpt_vars(i,1);
/* if is a remote, dont start one for it */
- if (rpt_vars[i].remote) {
- ast_copy_string(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq));
- ast_copy_string(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl));
- ast_copy_string(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl));
- rpt_vars[i].remmode = REM_MODE_FM;
- rpt_vars[i].offset = REM_SIMPLEX;
- rpt_vars[i].powerlevel = REM_MEDPWR;
+ if (rpt_vars[i].remote)
+ {
+ if(retreive_memory(&rpt_vars[i],"init")){ /* Try to retreive initial memory channel */
+ if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
+ strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
+ else
+ strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
+ strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
+
+ strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
+ rpt_vars[i].remmode = REM_MODE_FM;
+ rpt_vars[i].offset = REM_SIMPLEX;
+ rpt_vars[i].powerlevel = REM_LOWPWR;
+ }
continue;
}
- if (!rpt_vars[i].p.ident) {
- ast_log(LOG_WARNING, "Did not specify ident for node %s\n", rpt_vars[i].name);
+ else /* is a normal repeater */
+ {
+ rpt_vars[i].p.memory = rpt_vars[i].name;
+ if(retreive_memory(&rpt_vars[i],"radiofreq")){ /* Try to retreive initial memory channel */
+ if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
+ strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
+ else if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx150))
+ strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
+ strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
+
+ strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
+ rpt_vars[i].remmode = REM_MODE_FM;
+ rpt_vars[i].offset = REM_SIMPLEX;
+ rpt_vars[i].powerlevel = REM_LOWPWR;
+ }
+ ast_log(LOG_NOTICE,"Normal Repeater Init %s %s %s\n",rpt_vars[i].name, rpt_vars[i].remoterig, rpt_vars[i].freq);
+ }
+ if (!rpt_vars[i].p.ident)
+ {
+ ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
ast_config_destroy(cfg);
pthread_exit(NULL);
}
- ast_pthread_create_detached(&rpt_vars[i].rpt_thread, NULL, rpt, (void *) &rpt_vars[i]);
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
}
usleep(500000);
- for (;;) {
+ time(&starttime);
+ for(;;)
+ {
/* Now monitor each thread, and restart it if necessary */
- for (i = 0; i < n; i++) {
+ for(i = 0; i < n; i++)
+ {
int rv;
- if (rpt_vars[i].remote)
- continue;
+ if (rpt_vars[i].remote) continue;
if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
rv = -1;
else
- rv = pthread_kill(rpt_vars[i].rpt_thread, 0);
- if (rv) {
- if (time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15) {
- if (rpt_vars[i].threadrestarts >= 5) {
- ast_log(LOG_ERROR, "Continual RPT thread restarts, killing Asterisk\n");
- ast_cli_command(STDERR_FILENO, "restart now");
- } else {
- ast_log(LOG_NOTICE, "RPT thread restarted on %s\n", rpt_vars[i].name);
+ rv = pthread_kill(rpt_vars[i].rpt_thread,0);
+ if (rv)
+ {
+ if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
+ {
+ if(rpt_vars[i].threadrestarts >= 5)
+ {
+ ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
+ exit(1); /* Stuck in a restart loop, kill Asterisk and start over */
+ }
+ else
+ {
+ ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
rpt_vars[i].threadrestarts++;
}
- } else
+ }
+ else
rpt_vars[i].threadrestarts = 0;
rpt_vars[i].lastthreadrestarttime = time(NULL);
- ast_pthread_create_detached(&rpt_vars[i].rpt_thread, NULL, rpt, (void *) &rpt_vars[i]);
- ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
+ /* if (!rpt_vars[i].xlink) */
+ ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
}
}
+ for(;;)
+ {
+ struct nodelog *nodep;
+ char *space,datestr[100],fname[300];
+ int fd;
+
+ ast_mutex_lock(&nodeloglock);
+ nodep = nodelog.next;
+ if(nodep == &nodelog) /* if nothing in queue */
+ {
+ ast_mutex_unlock(&nodeloglock);
+ break;
+ }
+ remque((struct qelem *)nodep);
+ ast_mutex_unlock(&nodeloglock);
+ space = strchr(nodep->str,' ');
+ if (!space)
+ {
+ ast_free(nodep);
+ continue;
+ }
+ *space = 0;
+ strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
+ localtime(&nodep->timestamp));
+ sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
+ nodep->str,datestr);
+ fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
+ if (fd == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
+ ast_free(nodep);
+ continue;
+ }
+ if (write(fd,space + 1,strlen(space + 1)) !=
+ strlen(space + 1))
+ {
+ ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
+ ast_free(nodep);
+ continue;
+ }
+ close(fd);
+ ast_free(nodep);
+ }
usleep(2000000);
}
ast_config_destroy(cfg);
@@ -6810,182 +13111,426 @@ static void *rpt_master(void *config)
static int rpt_exec(struct ast_channel *chan, void *data)
{
- int res = -1, i, rem_totx, n, phone_mode = 0;
- char *tmp, keyed = 0;
- char *options = NULL, *tele, c;
- struct rpt *myrpt;
- struct ast_frame *f;
+ int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
+ int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
+ int ismuted,dtmfed,phone_vox = 0;
+#ifdef OLD_ASTERISK
+ struct localuser *u;
+#endif
+ char tmp[256], keyed = 0,keyed1 = 0;
+ char *options,*stringp,*tele,c,*altp,*memp;
+ char sx[320],*sy;
+ struct rpt *myrpt;
+ struct ast_frame *f,*f1,*f2;
struct ast_channel *who;
struct ast_channel *cs[20];
- struct rpt_link *l;
+ struct rpt_link *l;
ZT_CONFINFO ci; /* conference info */
ZT_PARAMS par;
- int ms, elap;
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(node);
- AST_APP_ARG(options);
- );
+ int ms,elap,nullfd;
+ time_t t,last_timeout_warning;
+ struct zt_radio_param z;
+ struct rpt_tele *telem;
+ int numlinks;
+ nullfd = open("/dev/null",O_RDWR);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
return -1;
}
- tmp = ast_strdupa((char *)data);
- AST_STANDARD_APP_ARGS(args, tmp);
+
+ strncpy(tmp, (char *)data, sizeof(tmp)-1);
+ time(&t);
+ /* if time has externally shifted negative, screw it */
+ if (t < starttime) t = starttime + START_DELAY;
+ if ((!starttime) || (t < (starttime + START_DELAY)))
+ {
+ ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
+ ast_safe_sleep(chan,3000);
+ return -1;
+ }
+
+ ast_log(LOG_NOTICE,"parsing argument=%s \n",tmp);
+
+ altp=strstr(tmp, "|*");
+ if(altp){
+ altp[0]=0;
+ altp++;
+ }
+
+ memp=strstr(tmp, "|M");
+ if(memp){
+ memp[0]=0;
+ memp+=2;
+ }
+
+ stringp=tmp;
+ strsep(&stringp, "|");
+ options = stringp;
+
+ ast_log(LOG_NOTICE,"options=%s \n",options);
+ if(memp>0)ast_log(LOG_NOTICE,"memp=%s \n",memp);
+ if(altp>0)ast_log(LOG_NOTICE,"altp=%s \n",altp);
+
myrpt = NULL;
/* see if we can find our specified one */
- for (i = 0; i < nrpts; i++) {
+ for(i = 0; i < nrpts; i++)
+ {
/* if name matches, assign it and exit loop */
- if (!strcmp(args.node, rpt_vars[i].name)) {
+ if (!strcmp(tmp,rpt_vars[i].name))
+ {
myrpt = &rpt_vars[i];
break;
}
}
- if (myrpt == NULL) {
- ast_log(LOG_WARNING, "Cannot find specified system node %s\n", args.node);
- return -1;
+
+ pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "");
+
+ if (myrpt == NULL)
+ {
+ pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "NODE_NOT_FOUND");
+ ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
+ return (priority_jump(NULL,chan));
+ }
+
+ numlinks=linkcount(myrpt);
+
+ if(options && *options == 'q')
+ {
+ int res=0;
+ char buf2[128];
+
+ if(myrpt->keyed)
+ pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "1");
+ else
+ pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "0");
+
+ if(myrpt->txkeyed)
+ pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "1");
+ else
+ pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "0");
+
+ snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_XLINK", myrpt->xlink);
+ pbx_builtin_setvar(chan, buf2);
+ snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_LINKS", numlinks);
+ pbx_builtin_setvar(chan, buf2);
+ snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_WASCHAN", myrpt->waschan);
+ pbx_builtin_setvar(chan, buf2);
+ snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_NOWCHAN", myrpt->nowchan);
+ pbx_builtin_setvar(chan, buf2);
+ snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_DUPLEX", myrpt->p.duplex);
+ pbx_builtin_setvar(chan, buf2);
+ snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PARROT", myrpt->p.parrotmode);
+ pbx_builtin_setvar(chan, buf2);
+ //snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PHONEVOX", myrpt->phonevox);
+ //pbx_builtin_setvar(chan, buf2);
+ //snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CONNECTED", myrpt->connected);
+ //pbx_builtin_setvar(chan, buf2);
+ snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CALLMODE", myrpt->callmode);
+ pbx_builtin_setvar(chan, buf2);
+ snprintf(buf2,sizeof(buf2),"%s=%s", "RPT_STAT_LASTTONE", myrpt->lasttone);
+ pbx_builtin_setvar(chan, buf2);
+
+ res=priority_jump(myrpt,chan);
+ return res;
+ }
+
+ if(options && *options == 'o')
+ {
+ return(channel_revert(myrpt));
+ }
+
+ #if 0
+ if((altp)&&(*options == 'Z'))
+ {
+ rpt_push_alt_macro(myrpt,altp);
+ return 0;
}
+ #endif
+
/* if not phone access, must be an IAX connection */
- if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R'))) {
+ if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R') || (*options == 'S')))
+ {
+ int val;
+
+ pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "0");
+
+ myrpt->bargechan=0;
+ if(options && strstr(options, "f")>0)
+ {
+ myrpt->bargechan=1;
+ }
+
+ if(memp>0)
+ {
+ char radiochan;
+ radiochan=strtod(data,NULL);
+ // if(myrpt->nowchan!=0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
+
+ if(numlinks>0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
+ {
+ pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "1");
+ ast_log(LOG_NOTICE, "Radio Channel Busy.\n");
+ return (priority_jump(myrpt,chan));
+ }
+ else if(radiochan!=myrpt->nowchan || myrpt->bargechan)
+ {
+ channel_steer(myrpt,memp);
+ }
+ }
+ if(altp)rpt_push_alt_macro(myrpt,altp);
phone_mode = 1;
- if (*options == 'D')
- phone_mode = 2;
- ast_set_callerid(chan, "0", "app_rpt user", "0");
- } else {
- if (strncmp(chan->name, "IAX2", 4)) {
+ if (*options == 'D') phone_mode = 2;
+ if (*options == 'S') phone_mode = 3;
+ ast_set_callerid(chan,"0","app_rpt user","0");
+ val = 1;
+ ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
+ if ((*(options + 1) == 'V') || (*(options + 1) == 'v')) phone_vox = 1;
+ }
+ else
+ {
+#ifdef ALLOW_LOCAL_CHANNELS
+ /* Check to insure the connection is IAX2 or Local*/
+ if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
+ ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
+ return -1;
+ }
+#else
+ if (strncmp(chan->name,"IAX2",4))
+ {
ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
return -1;
}
+#endif
+ if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){ /* Do not allow incoming radio connections if disabled */
+ ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
+ return -1;
+ }
}
- if (*args.options == 'R') {
+ if (options && (*options == 'R'))
+ {
/* Parts of this section taken from app_parkandannounce */
- int m, lot, timeout = 0;
- char tmp[256];
- char *s;
- AST_DECLARE_APP_ARGS(optionarg,
- AST_APP_ARG(template);
- AST_APP_ARG(timeout);
- AST_APP_ARG(return_context);
- );
+ char *return_context;
+ int l, m, lot, timeout = 0;
+ char tmp[256],*template;
+ char *working, *context, *exten, *priority;
+ char *s,*orig_s;
rpt_mutex_lock(&myrpt->lock);
m = myrpt->callmode;
rpt_mutex_unlock(&myrpt->lock);
- if ((!myrpt->p.nobusyout) && m) {
- if (chan->_state != AST_STATE_UP) {
- ast_indicate(chan, AST_CONTROL_BUSY);
- }
- while (ast_safe_sleep(chan, 10000) != -1) {
- /* This used to be a busy loop. It's probably better to yield the processor here. */
- usleep(1);
+ if ((!myrpt->p.nobusyout) && m)
+ {
+ if (chan->_state != AST_STATE_UP)
+ {
+ ast_indicate(chan,AST_CONTROL_BUSY);
}
+ while(ast_safe_sleep(chan,10000) != -1);
return -1;
}
- if (chan->_state != AST_STATE_UP) {
+ if (chan->_state != AST_STATE_UP)
+ {
ast_answer(chan);
+ if (!phone_mode) send_newkey(chan);
+ }
+
+ l=strlen(options)+2;
+ orig_s=ast_malloc(l);
+ if(!orig_s) {
+ ast_log(LOG_WARNING, "Out of memory\n");
+ return -1;
}
+ s=orig_s;
+ strncpy(s,options,l);
- s = ast_strdupa(options);
- AST_STANDARD_APP_ARGS(optionarg, s);
- if (optionarg.argc == 0 || ast_strlen_zero(optionarg.template)) {
+ template=strsep(&s,"|");
+ if(!template) {
ast_log(LOG_WARNING, "An announce template must be defined\n");
+ ast_free(orig_s);
return -1;
}
- if (optionarg.argc >= 2) {
- timeout = atoi(optionarg.timeout) * 1000;
+ if(s) {
+ timeout = atoi(strsep(&s, "|"));
+ timeout *= 1000;
}
- if (!ast_strlen_zero(optionarg.return_context)) {
- if (ast_parseable_goto(chan, optionarg.return_context)) {
- ast_verb(3, "Warning: Return Context Invalid, call will return to default|s\n");
+ return_context = s;
+
+ if(return_context != NULL) {
+ /* set the return context. Code borrowed from the Goto builtin */
+
+ working = return_context;
+ context = strsep(&working, "|");
+ exten = strsep(&working, "|");
+ if(!exten) {
+ /* Only a priority in this one */
+ priority = context;
+ exten = NULL;
+ context = NULL;
+ } else {
+ priority = strsep(&working, "|");
+ if(!priority) {
+ /* Only an extension and priority in this one */
+ priority = exten;
+ exten = context;
+ context = NULL;
}
}
+ if(atoi(priority) < 0) {
+ ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
+ ast_free(orig_s);
+ return -1;
+ }
+ /* At this point we have a priority and maybe an extension and a context */
+ chan->priority = atoi(priority);
+#ifdef OLD_ASTERISK
+ if(exten && strcasecmp(exten, "BYEXTENSION"))
+#else
+ if(exten)
+#endif
+ strncpy(chan->exten, exten, sizeof(chan->exten)-1);
+ if(context)
+ strncpy(chan->context, context, sizeof(chan->context)-1);
+ } else { /* increment the priority by default*/
+ chan->priority++;
+ }
+ if(option_verbose > 2) {
+ ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
+ if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
+ ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
+ }
+ }
+
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
ast_masq_park_call(chan, NULL, timeout, &lot);
- ast_verb(3, "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, optionarg.return_context);
- snprintf(tmp, sizeof(tmp), "%d,%s", lot, optionarg.template + 1);
- rpt_telemetry(myrpt, REV_PATCH, tmp);
+ if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
+
+ snprintf(tmp,sizeof(tmp) - 1,"%d,%s",lot,template + 1);
+
+ rpt_telemetry(myrpt,REV_PATCH,tmp);
+
+ ast_free(orig_s);
return 0;
+
}
- if (!options) {
- struct ast_hostent ahp;
- struct hostent *hp;
- struct in_addr ia;
- char hisip[100], nodeip[100];
- const char *val;
- char *s, *s1, *s2;
+ if (!options)
+ {
+ struct ast_hostent ahp;
+ struct hostent *hp;
+ struct in_addr ia;
+ char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
/* look at callerid to see what node this comes from */
- if (!chan->cid.cid_num) { /* if doesn't have caller id */
- ast_log(LOG_WARNING, "Doesn't have callerid on %s\n", args.node);
+ if (!chan->cid.cid_num) /* if doesn't have caller id */
+ {
+ ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
return -1;
}
-
/* get his IP from IAX2 module */
- pbx_substitute_variables_helper(chan, "${IAXPEER(CURRENTCHANNEL)}", hisip, sizeof(hisip) - 1);
- if (ast_strlen_zero(hisip)) {
+ memset(hisip,0,sizeof(hisip));
+#ifdef ALLOW_LOCAL_CHANNELS
+ /* set IP address if this is a local connection*/
+ if (strncmp(chan->name,"Local",5)==0) {
+ strcpy(hisip,"127.0.0.1");
+ } else {
+ pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
+ }
+#else
+ pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
+#endif
+
+ if (!hisip[0])
+ {
ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
return -1;
}
- if (!strcmp(myrpt->name, chan->cid.cid_num)) {
+ ast_callerid_parse(chan->cid.cid_num,&b,&b1);
+ ast_shrink_phone_number(b1);
+ if (!strcmp(myrpt->name,b1))
+ {
ast_log(LOG_WARNING, "Trying to link to self!!\n");
return -1;
}
- if (*(chan->cid.cid_num) < '1') {
- ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n", chan->cid.cid_num);
+ if (*b1 < '1')
+ {
+ ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
return -1;
}
+
/* look for his reported node string */
- val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, chan->cid.cid_num);
- if (!val) {
- ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n", chan->cid.cid_num);
+ val = node_lookup(myrpt,b1);
+ if (!val)
+ {
+ ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
return -1;
}
- ast_copy_string(tmp, val, sizeof(tmp));
+ strncpy(tmp,val,sizeof(tmp) - 1);
s = tmp;
- s1 = strsep(&s, ",");
- s2 = strsep(&s, ",");
- if (!s2) {
- ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n", chan->cid.cid_num);
+ s1 = strsep(&s,",");
+ if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
+ {
+ sy = strchr(s1,'/');
+ *sy = 0;
+ sprintf(sx,"%s:4569/%s",s1,sy + 1);
+ s1 = sx;
+ }
+ s2 = strsep(&s,",");
+ if (!s2)
+ {
+ ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
return -1;
}
- if (strcmp(s2, "NONE")) {
+ if (strcmp(s2,"NONE")) {
hp = ast_gethostbyname(s2, &ahp);
- if (!hp) {
- ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n", chan->cid.cid_num, s2);
+ if (!hp)
+ {
+ ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
return -1;
}
- memcpy(&ia, hp->h_addr, sizeof(in_addr_t));
- ast_copy_string(nodeip, ast_inet_ntoa(ia), sizeof(nodeip));
- if (strcmp(hisip, nodeip)) {
- char *s3 = strchr(s1, '@');
- if (s3)
- s1 = s3 + 1;
- s3 = strchr(s1, '/');
- if (s3)
- *s3 = 0;
+ memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
+#ifdef OLD_ASTERISK
+ ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
+#else
+ strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
+#endif
+ s3 = strchr(hisip,':');
+ if (s3) *s3 = 0;
+ if (strcmp(hisip,nodeip))
+ {
+ s3 = strchr(s1,'@');
+ if (s3) s1 = s3 + 1;
+ s3 = strchr(s1,'/');
+ if (s3) *s3 = 0;
+ s3 = strchr(s1,':');
+ if (s3) *s3 = 0;
hp = ast_gethostbyname(s1, &ahp);
- if (!hp) {
- ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n", chan->cid.cid_num, s1);
+ if (!hp)
+ {
+ ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
return -1;
}
- memcpy(&ia, hp->h_addr, sizeof(in_addr_t));
- ast_copy_string(nodeip, ast_inet_ntoa(ia), sizeof(nodeip));
- if (strcmp(hisip, nodeip)) {
- ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n", chan->cid.cid_num, nodeip, hisip);
+ memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
+#ifdef OLD_ASTERISK
+ ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
+#else
+ strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
+#endif
+ if (strcmp(hisip,nodeip))
+ {
+ ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
return -1;
}
}
@@ -6993,423 +13538,987 @@ static int rpt_exec(struct ast_channel *chan, void *data)
}
/* if is not a remote */
- if (!myrpt->remote) {
+ if (!myrpt->remote)
+ {
+ char *b,*b1;
int reconnects = 0;
+ rpt_mutex_lock(&myrpt->lock);
+ i = myrpt->xlink;
+ rpt_mutex_unlock(&myrpt->lock);
+ if (i)
+ {
+ ast_log(LOG_WARNING, "Cannot connect to node %s, system busy\n",myrpt->name);
+ return -1;
+ }
/* look at callerid to see what node this comes from */
- if (!chan->cid.cid_num) { /* if doesn't have caller id */
- ast_log(LOG_WARNING, "Doesnt have callerid on %s\n", args.node);
+ if (!chan->cid.cid_num) /* if doesn't have caller id */
+ {
+ ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
return -1;
}
- if (!strcmp(myrpt->name, chan->cid.cid_num)) {
+ ast_callerid_parse(chan->cid.cid_num,&b,&b1);
+ ast_shrink_phone_number(b1);
+ if (!strcmp(myrpt->name,b1))
+ {
ast_log(LOG_WARNING, "Trying to link to self!!\n");
return -1;
}
rpt_mutex_lock(&myrpt->lock);
l = myrpt->links.next;
/* try to find this one in queue */
- while (l != &myrpt->links) {
- if (l->name[0] == '0') {
+ while(l != &myrpt->links)
+ {
+ if (l->name[0] == '0')
+ {
l = l->next;
continue;
}
/* if found matching string */
- if (!strcmp(l->name, chan->cid.cid_num))
- break;
+ if (!strcmp(l->name,b1)) break;
l = l->next;
}
/* if found */
- if (l != &myrpt->links) {
+ if (l != &myrpt->links)
+ {
l->killme = 1;
- l->retries = MAX_RETRIES + 1;
+ l->retries = l->max_retries + 1;
l->disced = 2;
reconnects = l->reconnects;
reconnects++;
- rpt_mutex_unlock(&myrpt->lock);
+ rpt_mutex_unlock(&myrpt->lock);
usleep(500000);
} else
rpt_mutex_unlock(&myrpt->lock);
/* establish call in tranceive mode */
- l = ast_calloc(1, sizeof(*l));
- if (!l) {
+ l = ast_malloc(sizeof(struct rpt_link));
+ if (!l)
+ {
ast_log(LOG_WARNING, "Unable to malloc\n");
pthread_exit(NULL);
}
+ /* zero the silly thing */
+ memset((char *)l,0,sizeof(struct rpt_link));
l->mode = 1;
- ast_copy_string(l->name, chan->cid.cid_num, sizeof(l->name));
+ strncpy(l->name,b1,MAXNODESTR - 1);
l->isremote = 0;
l->chan = chan;
l->connected = 1;
+ l->thisconnected = 1;
l->hasconnected = 1;
l->reconnects = reconnects;
l->phonemode = phone_mode;
- ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
- ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
+ l->phonevox = phone_vox;
+ l->lastf1 = NULL;
+ l->lastf2 = NULL;
+ l->dtmfed = 0;
+ voxinit_link(l,1);
+ ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
+ ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
/* allocate a pseudo-channel thru asterisk */
- l->pchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
- if (!l->pchan) {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
+ l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!l->pchan)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
pthread_exit(NULL);
}
- ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
- ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
+ ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
+ ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (l->pchan->cdr)
+ ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
/* make a conference for the tx */
ci.chan = 0;
ci.confno = myrpt->conf;
ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
/* first put the channel on the conference in proper mode */
- if (ioctl(l->pchan->fds[0], ZT_SETCONF, &ci) == -1) {
+ if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
+ {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
rpt_mutex_lock(&myrpt->lock);
- if (phone_mode > 1)
- l->lastrx = 1;
+ if ((phone_mode == 2) && (!phone_vox)) l->lastrealrx = 1;
+ l->max_retries = MAX_RETRIES;
/* insert at end of queue */
- insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
+ insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
+ __kickshort(myrpt);
rpt_mutex_unlock(&myrpt->lock);
if (chan->_state != AST_STATE_UP) {
ast_answer(chan);
+ if (!phone_mode) send_newkey(chan);
}
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+
+ if (l->phonemode)
+ sprintf(str,"LINK(P),%s",l->name);
+ else
+ sprintf(str,"LINK,%s",l->name);
+ donodelog(myrpt,str);
+ }
+ if (!phone_mode) send_newkey(chan);
return AST_PBX_KEEPALIVE;
}
+ /* well, then it is a remote */
rpt_mutex_lock(&myrpt->lock);
/* if remote, error if anyone else already linked */
- if (myrpt->remoteon) {
+ if (myrpt->remoteon)
+ {
rpt_mutex_unlock(&myrpt->lock);
usleep(500000);
- if (myrpt->remoteon) {
- ast_log(LOG_WARNING, "Trying to use busy link on %s\n", args.node);
+ if (myrpt->remoteon)
+ {
+ ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (chan->cdr)
+ ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
return -1;
}
rpt_mutex_lock(&myrpt->lock);
}
- myrpt->remoteon = 1;
- if (ioperm(myrpt->p.iobase, 1, 1) == -1) {
+ if (myrpt->p.rptnode)
+ {
+ char killedit = 0;
+ time_t now;
+
+ time(&now);
+ for(i = 0; i < nrpts; i++)
+ {
+ if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
+ {
+ if ((rpt_vars[i].links.next != &rpt_vars[i].links) ||
+ rpt_vars[i].keyed ||
+ ((rpt_vars[i].lastkeyedtime + RPT_LOCKOUT_SECS) > now) ||
+ rpt_vars[i].txkeyed ||
+ ((rpt_vars[i].lasttxkeyedtime + RPT_LOCKOUT_SECS) > now))
+ {
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_log(LOG_WARNING, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars[i].name,tmp);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (chan->cdr)
+ ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+ return -1;
+ }
+ while(rpt_vars[i].xlink != 3)
+ {
+ if (!killedit)
+ {
+ ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
+ rpt_vars[i].xlink = 1;
+ killedit = 1;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ if (ast_safe_sleep(chan,500) == -1)
+ {
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (chan->cdr)
+ ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+ return -1;
+ }
+ rpt_mutex_lock(&myrpt->lock);
+ }
+ break;
+ }
+ }
+ }
+
+ if ( (!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16)) &&
+ (ioperm(myrpt->p.iobase,1,1) == -1))
+ {
rpt_mutex_unlock(&myrpt->lock);
- ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n", myrpt->p.iobase);
+ ast_log(LOG_WARNING, "Can't get io permission on IO port %x hex\n",myrpt->p.iobase);
return -1;
}
+ myrpt->remoteon = 1;
+#ifdef OLD_ASTERISK
+ LOCAL_USER_ADD(u);
+#endif
rpt_mutex_unlock(&myrpt->lock);
/* find our index, and load the vars initially */
- for (i = 0; i < nrpts; i++) {
- if (&rpt_vars[i] == myrpt) {
- load_rpt_vars(i, 0);
+ for(i = 0; i < nrpts; i++)
+ {
+ if (&rpt_vars[i] == myrpt)
+ {
+ load_rpt_vars(i,0);
break;
}
}
rpt_mutex_lock(&myrpt->lock);
- tele = strchr(myrpt->rxchanname, '/');
- if (!tele) {
- ast_log(LOG_ERROR, "rpt:Dial number must be in format tech/number\n");
+ tele = strchr(myrpt->rxchanname,'/');
+ if (!tele)
+ {
+ fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
rpt_mutex_unlock(&myrpt->lock);
pthread_exit(NULL);
}
*tele++ = 0;
- myrpt->rxchannel = ast_request(myrpt->rxchanname, AST_FORMAT_SLINEAR, tele, NULL);
- if (myrpt->rxchannel) {
- ast_set_read_format(myrpt->rxchannel, AST_FORMAT_SLINEAR);
- ast_set_write_format(myrpt->rxchannel, AST_FORMAT_SLINEAR);
- ast_channel_setwhentohangup_tv(myrpt->rxchannel, cancel_atimeout);
+ myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
+ myrpt->zaprxchannel = NULL;
+ if (!strcasecmp(myrpt->rxchanname,"Zap"))
+ myrpt->zaprxchannel = myrpt->rxchannel;
+ if (myrpt->rxchannel)
+ {
+ ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
+ ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->rxchannel->cdr)
+ ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+#ifndef NEW_ASTERISK
+ myrpt->rxchannel->whentohangup = 0;
+#endif
myrpt->rxchannel->appl = "Apprpt";
myrpt->rxchannel->data = "(Link Rx)";
- ast_verb(3, "rpt (Rx) initiating call to %s/%s on %s\n",
- myrpt->rxchanname, tele, myrpt->rxchannel->name);
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
+ myrpt->rxchanname,tele,myrpt->rxchannel->name);
rpt_mutex_unlock(&myrpt->lock);
- ast_call(myrpt->rxchannel, tele, 999);
+ ast_call(myrpt->rxchannel,tele,999);
rpt_mutex_lock(&myrpt->lock);
- } else {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Rx channel\n");
+ }
+ else
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
rpt_mutex_unlock(&myrpt->lock);
pthread_exit(NULL);
}
*--tele = '/';
- if (myrpt->txchanname) {
- tele = strchr(myrpt->txchanname, '/');
- if (!tele) {
- ast_log(LOG_ERROR, "rpt:Dial number must be in format tech/number\n");
+ myrpt->zaptxchannel = NULL;
+ if (myrpt->txchanname)
+ {
+ tele = strchr(myrpt->txchanname,'/');
+ if (!tele)
+ {
+ fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->rxchannel);
pthread_exit(NULL);
}
*tele++ = 0;
- myrpt->txchannel = ast_request(myrpt->txchanname, AST_FORMAT_SLINEAR, tele, NULL);
- if (myrpt->txchannel) {
- ast_set_read_format(myrpt->txchannel, AST_FORMAT_SLINEAR);
- ast_set_write_format(myrpt->txchannel, AST_FORMAT_SLINEAR);
- ast_channel_setwhentohangup_tv(myrpt->txchannel, cancel_atimeout);
+ myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
+ if (!strncasecmp(myrpt->txchanname,"Zap",3))
+ myrpt->zaptxchannel = myrpt->txchannel;
+ if (myrpt->txchannel)
+ {
+ ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
+ ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->txchannel->cdr)
+ ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+#ifndef NEW_ASTERISK
+ myrpt->txchannel->whentohangup = 0;
+#endif
myrpt->txchannel->appl = "Apprpt";
myrpt->txchannel->data = "(Link Tx)";
- ast_verb(3, "rpt (Tx) initiating call to %s/%s on %s\n",
- myrpt->txchanname, tele, myrpt->txchannel->name);
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
+ myrpt->txchanname,tele,myrpt->txchannel->name);
rpt_mutex_unlock(&myrpt->lock);
- ast_call(myrpt->txchannel, tele, 999);
+ ast_call(myrpt->txchannel,tele,999);
rpt_mutex_lock(&myrpt->lock);
- } else {
- ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n");
+ }
+ else
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->rxchannel);
pthread_exit(NULL);
}
*--tele = '/';
- } else {
+ }
+ else
+ {
myrpt->txchannel = myrpt->rxchannel;
+ if (!strncasecmp(myrpt->rxchanname,"Zap",3))
+ myrpt->zaptxchannel = myrpt->rxchannel;
+ }
+ /* allocate a pseudo-channel thru asterisk */
+ myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+ if (!myrpt->pchannel)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
+ rpt_mutex_unlock(&myrpt->lock);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ pthread_exit(NULL);
+ }
+ ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
+ ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
+#ifdef AST_CDR_FLAG_POST_DISABLED
+ if (myrpt->pchannel->cdr)
+ ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
+#endif
+ if (!myrpt->zaprxchannel) myrpt->zaprxchannel = myrpt->pchannel;
+ if (!myrpt->zaptxchannel) myrpt->zaptxchannel = myrpt->pchannel;
+ /* make a conference for the pseudo */
+ ci.chan = 0;
+ ci.confno = -1; /* make a new conf */
+ ci.confmode = ZT_CONF_CONFANNMON ;
+ /* first put the channel on the conference in announce/monitor mode */
+ if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->pchannel);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ pthread_exit(NULL);
+ }
+ /* save pseudo channel conference number */
+ myrpt->conf = myrpt->txconf = ci.confno;
+ /* if serial io port, open it */
+ myrpt->iofd = -1;
+ if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
+ {
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->pchannel);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ pthread_exit(NULL);
+ }
+ iskenwood_pci4 = 0;
+ memset(&z,0,sizeof(z));
+ if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->zaptxchannel))
+ {
+ z.radpar = ZT_RADPAR_REMMODE;
+ z.data = ZT_RADPAR_REM_NONE;
+ res = ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z);
+ /* if PCIRADIO and kenwood selected */
+ if ((!res) && (!strcmp(myrpt->remoterig,remote_rig_kenwood)))
+ {
+ z.radpar = ZT_RADPAR_UIOMODE;
+ z.data = 1;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
+ return -1;
+ }
+ z.radpar = ZT_RADPAR_UIODATA;
+ z.data = 3;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot set UIODATA\n");
+ return -1;
+ }
+ i = ZT_OFFHOOK;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_HOOK,&i) == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot set hook\n");
+ return -1;
+ }
+ iskenwood_pci4 = 1;
+ }
+ }
+ if (myrpt->txchannel == myrpt->zaptxchannel)
+ {
+ i = ZT_ONHOOK;
+ ioctl(myrpt->zaptxchannel->fds[0],ZT_HOOK,&i);
+ /* if PCIRADIO and Yaesu ft897/ICOM IC-706 selected */
+ if ((myrpt->iofd < 1) && (!res) &&
+ ((!strcmp(myrpt->remoterig,remote_rig_ft897)) ||
+ (!strcmp(myrpt->remoterig,remote_rig_ic706)) ||
+ (!strcmp(myrpt->remoterig,remote_rig_tm271))))
+ {
+ z.radpar = ZT_RADPAR_UIOMODE;
+ z.data = 1;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
+ return -1;
+ }
+ z.radpar = ZT_RADPAR_UIODATA;
+ z.data = 3;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot set UIODATA\n");
+ return -1;
+ }
+ }
}
myrpt->remoterx = 0;
myrpt->remotetx = 0;
myrpt->retxtimer = 0;
+ myrpt->rerxtimer = 0;
myrpt->remoteon = 1;
myrpt->dtmfidx = -1;
myrpt->dtmfbuf[0] = 0;
myrpt->dtmf_time_rem = 0;
myrpt->hfscanmode = 0;
myrpt->hfscanstatus = 0;
- if (myrpt->p.startupmacro) {
- myrpt->remchannel = chan; /* Save copy of channel */
- snprintf(myrpt->macrobuf, sizeof(myrpt->macrobuf), "PPPP%s", myrpt->p.startupmacro);
- }
- if (myrpt->p.startupgosub) {
- myrpt->remchannel = chan; /* Save copy of channel */
- snprintf(myrpt->gosubbuf, sizeof(myrpt->gosubbuf), "PPPP%s", myrpt->p.startupgosub);
+ if (myrpt->p.startupmacro)
+ {
+ snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
}
+ time(&myrpt->start_time);
+ myrpt->last_activity_time = myrpt->start_time;
+ last_timeout_warning = 0;
myrpt->reload = 0;
+ myrpt->tele.next = &myrpt->tele;
+ myrpt->tele.prev = &myrpt->tele;
+ myrpt->newkey = 0;
rpt_mutex_unlock(&myrpt->lock);
- setrem(myrpt);
ast_set_write_format(chan, AST_FORMAT_SLINEAR);
ast_set_read_format(chan, AST_FORMAT_SLINEAR);
+ rem_rx = 0;
+ remkeyed = 0;
/* if we are on 2w loop and are a remote, turn EC on */
- if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel)) {
+ if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
+ {
i = 128;
- ioctl(myrpt->rxchannel->fds[0], ZT_ECHOCANCEL, &i);
+ ioctl(myrpt->zaprxchannel->fds[0],ZT_ECHOCANCEL,&i);
}
if (chan->_state != AST_STATE_UP) {
ast_answer(chan);
+ if (!phone_mode) send_newkey(chan);
}
- if (ioctl(myrpt->txchannel->fds[0], ZT_GET_PARAMS, &par) != -1) {
- if (par.rxisoffhook) {
- ast_indicate(chan, AST_CONTROL_RADIO_KEY);
- myrpt->remoterx = 1;
+ if (myrpt->rxchannel == myrpt->zaprxchannel)
+ {
+ if (ioctl(myrpt->zaprxchannel->fds[0],ZT_GET_PARAMS,&par) != -1)
+ {
+ if (par.rxisoffhook)
+ {
+ ast_indicate(chan,AST_CONTROL_RADIO_KEY);
+ myrpt->remoterx = 1;
+ remkeyed = 1;
+ }
}
}
+ if (myrpt->p.archivedir)
+ {
+ char mycmd[100],mydate[100],*b,*b1;
+ time_t myt;
+ long blocksleft;
+
+
+ mkdir(myrpt->p.archivedir,0600);
+ sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
+ mkdir(mycmd,0600);
+ time(&myt);
+ strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
+ localtime(&myt));
+ sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
+ myrpt->p.archivedir,myrpt->name,mydate);
+ if (myrpt->p.monminblocks)
+ {
+ blocksleft = diskavail(myrpt);
+ if (myrpt->p.remotetimeout)
+ {
+ blocksleft -= (myrpt->p.remotetimeout *
+ MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
+ }
+ if (blocksleft >= myrpt->p.monminblocks)
+ ast_cli_command(nullfd,mycmd);
+ } else ast_cli_command(nullfd,mycmd);
+ /* look at callerid to see what node this comes from */
+ if (!chan->cid.cid_num) /* if doesn't have caller id */
+ {
+ b1 = "0";
+ } else {
+ ast_callerid_parse(chan->cid.cid_num,&b,&b1);
+ ast_shrink_phone_number(b1);
+ }
+ sprintf(mycmd,"CONNECT,%s",b1);
+ donodelog(myrpt,mycmd);
+ }
+ myrpt->loginuser[0] = 0;
+ myrpt->loginlevel[0] = 0;
+ myrpt->authtelltimer = 0;
+ myrpt->authtimer = 0;
+ authtold = 0;
+ authreq = 0;
+ if (myrpt->p.authlevel > 1) authreq = 1;
+ setrem(myrpt);
n = 0;
+ dtmfed = 0;
cs[n++] = chan;
cs[n++] = myrpt->rxchannel;
+ cs[n++] = myrpt->pchannel;
if (myrpt->rxchannel != myrpt->txchannel)
cs[n++] = myrpt->txchannel;
- for (;;) {
- if (ast_check_hangup(chan))
- break;
- if (ast_check_hangup(myrpt->rxchannel))
- break;
- if (myrpt->reload) {
+ if (!phone_mode) send_newkey(chan);
+ /* start un-locked */
+ for(;;)
+ {
+ if (ast_check_hangup(chan)) break;
+ if (ast_check_hangup(myrpt->rxchannel)) break;
+ notremming = 0;
+ setting = 0;
+ reming = 0;
+ telem = myrpt->tele.next;
+ while(telem != &myrpt->tele)
+ {
+ if (telem->mode == SETREMOTE) setting = 1;
+ if ((telem->mode == SETREMOTE) ||
+ (telem->mode == SCAN) ||
+ (telem->mode == TUNE)) reming = 1;
+ else notremming = 1;
+ telem = telem->next;
+ }
+ if (myrpt->reload)
+ {
myrpt->reload = 0;
- rpt_mutex_unlock(&myrpt->lock);
/* find our index, and load the vars */
- for (i = 0; i < nrpts; i++) {
- if (&rpt_vars[i] == myrpt) {
- load_rpt_vars(i, 0);
+ for(i = 0; i < nrpts; i++)
+ {
+ if (&rpt_vars[i] == myrpt)
+ {
+ load_rpt_vars(i,0);
break;
}
}
- rpt_mutex_lock(&myrpt->lock);
+ }
+ time(&t);
+ if (myrpt->p.remotetimeout)
+ {
+ time_t r;
+
+ r = (t - myrpt->start_time);
+ if (r >= myrpt->p.remotetimeout)
+ {
+ saynode(myrpt,chan,myrpt->name);
+ sayfile(chan,"rpt/timeout");
+ ast_safe_sleep(chan,1000);
+ break;
+ }
+ if ((myrpt->p.remotetimeoutwarning) &&
+ (r >= (myrpt->p.remotetimeout -
+ myrpt->p.remotetimeoutwarning)) &&
+ (r <= (myrpt->p.remotetimeout -
+ myrpt->p.remotetimeoutwarningfreq)))
+ {
+ if (myrpt->p.remotetimeoutwarningfreq)
+ {
+ if ((t - last_timeout_warning) >=
+ myrpt->p.remotetimeoutwarningfreq)
+ {
+ time(&last_timeout_warning);
+ rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
+ }
+ }
+ else
+ {
+ if (!last_timeout_warning)
+ {
+ time(&last_timeout_warning);
+ rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
+ }
+ }
+ }
+ }
+ if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
+ {
+ time_t r;
+
+ r = (t - myrpt->last_activity_time);
+ if (r >= myrpt->p.remoteinacttimeout)
+ {
+ saynode(myrpt,chan,myrpt->name);
+ ast_safe_sleep(chan,1000);
+ break;
+ }
+ if ((myrpt->p.remotetimeoutwarning) &&
+ (r >= (myrpt->p.remoteinacttimeout -
+ myrpt->p.remotetimeoutwarning)) &&
+ (r <= (myrpt->p.remoteinacttimeout -
+ myrpt->p.remotetimeoutwarningfreq)))
+ {
+ if (myrpt->p.remotetimeoutwarningfreq)
+ {
+ if ((t - last_timeout_warning) >=
+ myrpt->p.remotetimeoutwarningfreq)
+ {
+ time(&last_timeout_warning);
+ rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
+ }
+ }
+ else
+ {
+ if (!last_timeout_warning)
+ {
+ time(&last_timeout_warning);
+ rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
+ }
+ }
+ }
}
ms = MSWAIT;
- who = ast_waitfor_n(cs, n, &ms);
- if (who == NULL)
- ms = 0;
+ who = ast_waitfor_n(cs,n,&ms);
+ if (who == NULL) ms = 0;
elap = MSWAIT - ms;
- if (myrpt->macrotimer)
- myrpt->macrotimer -= elap;
- if (myrpt->macrotimer < 0)
- myrpt->macrotimer = 0;
- if (myrpt->gosubtimer)
- myrpt->gosubtimer -= elap;
- if (myrpt->gosubtimer < 0)
- myrpt->gosubtimer = 0;
+ if (myrpt->macrotimer) myrpt->macrotimer -= elap;
+ if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
+ if (!ms) continue;
+ /* do local dtmf timer */
+ if (myrpt->dtmf_local_timer)
+ {
+ if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
+ if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
+ }
+ rpt_mutex_lock(&myrpt->lock);
+ do_dtmf_local(myrpt,0);
rpt_mutex_unlock(&myrpt->lock);
- if (!ms)
- continue;
- rem_totx = keyed;
-
-
- if ((!myrpt->remoterx) && (!myrpt->remotetx)) {
- if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME) {
- myrpt->retxtimer = 0;
- ast_indicate(chan, AST_CONTROL_RADIO_UNKEY);
+ //
+ rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
+ rem_totx |= keyed && (!myrpt->tunerequest);
+ rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
+ if(!strcmp(myrpt->remoterig, remote_rig_ic706))
+ rem_totx |= myrpt->tunerequest;
+ //
+ if((debug > 6) && rem_totx) {
+ ast_log(LOG_NOTICE,"Set rem_totx=%i. dtmf_local_timer=%i phone_mode=%i keyed=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,phone_mode,keyed,myrpt->tunerequest);
+ }
+ if (keyed && (!keyed1))
+ {
+ keyed1 = 1;
+ }
+
+ if (!keyed && (keyed1))
+ {
+ time_t myt;
+
+ keyed1 = 0;
+ time(&myt);
+ /* if login necessary, and not too soon */
+ if ((myrpt->p.authlevel) &&
+ (!myrpt->loginlevel[0]) &&
+ (myt > (t + 3)))
+ {
+ authreq = 1;
+ authtold = 0;
+ myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
}
- } else
- myrpt->retxtimer = 0;
- if (rem_totx && (!myrpt->remotetx)) { /* Remote base radio TX key */
- myrpt->remotetx = 1;
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_KEY);
}
- if ((!rem_totx) && myrpt->remotetx) { /* Remote base radio TX unkey */
- myrpt->remotetx = 0;
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
+
+ if (rem_rx && (!myrpt->remoterx))
+ {
+ myrpt->remoterx = 1;
+ ast_indicate(chan,AST_CONTROL_RADIO_KEY);
+ }
+ if ((!rem_rx) && (myrpt->remoterx))
+ {
+ myrpt->remoterx = 0;
+ ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
+ }
+ /* if auth requested, and not authed yet */
+ if (authreq && (!myrpt->loginlevel[0]))
+ {
+ if ((!authtold) && ((myrpt->authtelltimer += elap)
+ >= AUTHTELLTIME))
+ {
+ authtold = 1;
+ rpt_telemetry(myrpt,LOGINREQ,NULL);
+ }
+ if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
+ {
+ break; /* if not logged in, hang up after a time */
+ }
}
+ if (myrpt->newkey)
+ {
+ if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
+ {
+ myrpt->retxtimer = 0;
+ if ((myrpt->remoterx) && (!myrpt->remotetx))
+ ast_indicate(chan,AST_CONTROL_RADIO_KEY);
+ else
+ ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
+ }
- if (myrpt->tunerequest && (!strcmp(myrpt->remote, remote_rig_ft897))) { /* ft-897 specific for now... */
- myrpt->tunerequest = 0;
- set_mode_ft897(myrpt, REM_MODE_AM);
- simple_command_ft897(myrpt, 8);
+ if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
+ {
+ keyed = 0;
+ myrpt->rerxtimer = 0;
+ }
+ }
+ if (rem_totx && (!myrpt->remotetx))
+ {
+ /* if not authed, and needed, do not transmit */
+ if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
+ {
+ if(debug > 6)
+ ast_log(LOG_NOTICE,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,myrpt->tunerequest);
+
+ myrpt->remotetx = 1;
+ /* asdf maw ??? is this really what you want? Doesn't it always get executed? */
+ if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
+ {
+ time(&myrpt->last_activity_time);
+ if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
+ {
+ z.radpar = ZT_RADPAR_UIODATA;
+ z.data = 1;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot set UIODATA\n");
+ return -1;
+ }
+ }
+ else
+ {
+ ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
+ }
+ if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
+ }
+ }
+ }
+ if ((!rem_totx) && myrpt->remotetx) /* Remote base radio TX unkey */
+ {
myrpt->remotetx = 0;
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
- if (!myrpt->remoterx)
- ast_indicate(chan, AST_CONTROL_RADIO_KEY);
- if (play_tone(chan, 800, 6000, 8192) == -1)
- break;
-
- rmt_telem_finish(myrpt, chan);
- set_mode_ft897(myrpt, 0x88);
- setrem(myrpt);
+ if(!myrpt->remtxfreqok){
+ rpt_telemetry(myrpt,UNAUTHTX,NULL);
+ }
+ if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
+ {
+ z.radpar = ZT_RADPAR_UIODATA;
+ z.data = 3;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot set UIODATA\n");
+ return -1;
+ }
+ }
+ else
+ {
+ ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
+ }
+ if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
}
-
- if (myrpt->hfscanmode) {
+ if (myrpt->hfscanmode){
myrpt->scantimer -= elap;
- if (myrpt->scantimer <= 0) {
- myrpt->scantimer = REM_SCANTIME;
- service_scan(myrpt);
+ if(myrpt->scantimer <= 0){
+ if (!reming)
+ {
+ myrpt->scantimer = REM_SCANTIME;
+ rpt_telemetry(myrpt,SCAN,0);
+ } else myrpt->scantimer = 1;
}
}
- if (who == chan) { /* if it was a read from incoming */
+ rpt_mutex_lock(&myrpt->lock);
+ c = myrpt->macrobuf[0];
+ if (c && (!myrpt->macrotimer))
+ {
+ myrpt->macrotimer = MACROTIME;
+ memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
+ if ((c == 'p') || (c == 'P'))
+ myrpt->macrotimer = MACROPTIME;
+ rpt_mutex_unlock(&myrpt->lock);
+ if (myrpt->p.archivedir)
+ {
+ char str[100];
+ sprintf(str,"DTMF(M),%c",c);
+ donodelog(myrpt,str);
+ }
+ if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
+ continue;
+ } else rpt_mutex_unlock(&myrpt->lock);
+ if (who == chan) /* if it was a read from incomming */
+ {
f = ast_read(chan);
- if (!f) {
- ast_debug(1, "@@@@ link:Hung Up\n");
+ if (!f)
+ {
+ if (debug) printf("@@@@ link:Hung Up\n");
break;
}
- if (f->frametype == AST_FRAME_VOICE) {
+ if (f->frametype == AST_FRAME_VOICE)
+ {
+ if (ioctl(chan->fds[0], ZT_GETCONFMUTE, &ismuted) == -1)
+ {
+ ismuted = 0;
+ }
/* if not transmitting, zero-out audio */
- if (!myrpt->remotetx)
- memset(f->data, 0, f->datalen);
- ast_write(myrpt->txchannel, f);
- }
- if (f->frametype == AST_FRAME_DTMF) {
- myrpt->remchannel = chan; /* Save copy of channel */
- if (handle_remote_phone_dtmf(myrpt, f->subclass, &keyed, phone_mode) == -1) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ ismuted |= (!myrpt->remotetx);
+ if (dtmfed && phone_mode) ismuted = 1;
+ dtmfed = 0;
+ if (ismuted)
+ {
+ memset(f->data,0,f->datalen);
+ if (myrpt->lastf1)
+ memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
+ if (myrpt->lastf2)
+ memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
+ }
+ if (f) f2 = ast_frdup(f);
+ else f2 = NULL;
+ f1 = myrpt->lastf2;
+ myrpt->lastf2 = myrpt->lastf1;
+ myrpt->lastf1 = f2;
+ if (ismuted)
+ {
+ if (myrpt->lastf1)
+ memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
+ if (myrpt->lastf2)
+ memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
+ }
+ if (f1)
+ {
+ if (phone_mode)
+ ast_write(myrpt->txchannel,f1);
+ else
+ ast_write(myrpt->txchannel,f);
+ ast_frfree(f1);
+ }
+ }
+#ifndef OLD_ASTERISK
+ else if (f->frametype == AST_FRAME_DTMF_BEGIN)
+ {
+ if (myrpt->lastf1)
+ memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
+ if (myrpt->lastf2)
+ memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
+ dtmfed = 1;
+ }
+#endif
+ if (f->frametype == AST_FRAME_DTMF)
+ {
+ if (myrpt->lastf1)
+ memset(myrpt->lastf1->data,0,myrpt->lastf1->datalen);
+ if (myrpt->lastf2)
+ memset(myrpt->lastf2->data,0,myrpt->lastf2->datalen);
+ dtmfed = 1;
+ if (handle_remote_phone_dtmf(myrpt,f->subclass,&keyed,phone_mode) == -1)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
}
- if (f->frametype == AST_FRAME_TEXT) {
- myrpt->remchannel = chan; /* Save copy of channel */
- if (handle_remote_data(myrpt, f->data) == -1) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (f->frametype == AST_FRAME_TEXT)
+ {
+ if (handle_remote_data(myrpt,f->data) == -1)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
}
- if (f->frametype == AST_FRAME_CONTROL) {
- if (f->subclass == AST_CONTROL_HANGUP) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ 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) {
- ast_debug(8, "@@@@ rx key\n");
+ if (f->subclass == AST_CONTROL_RADIO_KEY)
+ {
+ if (debug == 7) printf("@@@@ rx key\n");
keyed = 1;
+ myrpt->rerxtimer = 0;
}
/* if RX un-key */
- if (f->subclass == AST_CONTROL_RADIO_UNKEY) {
- ast_debug(8, "@@@@ rx un-key\n");
+ if (f->subclass == AST_CONTROL_RADIO_UNKEY)
+ {
+ myrpt->rerxtimer = 0;
+ if (debug == 7) printf("@@@@ rx un-key\n");
keyed = 0;
}
}
- if (myrpt->hfscanstatus) {
- myrpt->remchannel = chan; /* Save copy of channel */
- myrpt->remotetx = 0;
- ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
- if (!myrpt->remoterx) {
- ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_KEY);
- }
- if (myrpt->hfscanstatus < 0) {
- if (myrpt->hfscanstatus == -1) {
- if (ast_safe_sleep(myrpt->remchannel, 1000) == -1)
- break;
- }
- sayfile(myrpt->remchannel, "rpt/stop");
- } else {
- saynum(myrpt->remchannel, myrpt->hfscanstatus );
- }
- rmt_telem_finish(myrpt, myrpt->remchannel);
- myrpt->hfscanstatus = 0;
- }
ast_frfree(f);
- rpt_mutex_lock(&myrpt->lock);
- c = myrpt->macrobuf[0];
- if (c && (!myrpt->macrotimer)) {
- myrpt->macrotimer = MACROTIME;
- memmove(myrpt->macrobuf, myrpt->macrobuf + 1, sizeof(myrpt->macrobuf) - 1);
- if ((c == 'p') || (c == 'P'))
- myrpt->macrotimer = MACROPTIME;
- rpt_mutex_unlock(&myrpt->lock);
- if (handle_remote_dtmf_digit(myrpt, c, &keyed, 0) == -1)
- break;
- continue;
- }
- c = myrpt->gosubbuf[0];
- if (c && (!myrpt->gosubtimer)) {
- myrpt->gosubtimer = GOSUBTIME;
- memmove(myrpt->gosubbuf, myrpt->gosubbuf + 1, sizeof(myrpt->gosubbuf) - 1);
- if ((c == 'p') || (c == 'P'))
- myrpt->gosubtimer = GOSUBPTIME;
- rpt_mutex_unlock(&myrpt->lock);
- if (handle_remote_dtmf_digit(myrpt, c, &keyed, 0) == -1)
- break;
- continue;
- }
- rpt_mutex_unlock(&myrpt->lock);
continue;
}
- if (who == myrpt->rxchannel) { /* if it was a read from radio */
+ if (who == myrpt->rxchannel) /* if it was a read from radio */
+ {
f = ast_read(myrpt->rxchannel);
- if (!f) {
- ast_debug(1, "@@@@ link:Hung Up\n");
+ if (!f)
+ {
+ if (debug) printf("@@@@ link:Hung Up\n");
break;
}
- if (f->frametype == AST_FRAME_VOICE) {
- if ((myrpt->remote) && (myrpt->remotetx))
- memset(f->data, 0, f->datalen);
- ast_write(chan, f);
- } else if (f->frametype == AST_FRAME_CONTROL) {
- if (f->subclass == AST_CONTROL_HANGUP) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (f->frametype == AST_FRAME_VOICE)
+ {
+ int myreming = 0;
+
+ if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
+ myreming = reming;
+
+ if (myreming || (!remkeyed) ||
+ ((myrpt->remote) && (myrpt->remotetx)) ||
+ ((myrpt->remmode != REM_MODE_FM) &&
+ notremming))
+ memset(f->data,0,f->datalen);
+ ast_write(myrpt->pchannel,f);
+ }
+ else 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) {
- ast_debug(8, "@@@@ remote rx key\n");
- if (!myrpt->remotetx) {
- ast_indicate(chan, AST_CONTROL_RADIO_KEY);
- myrpt->remoterx = 1;
+ if (f->subclass == AST_CONTROL_RADIO_KEY)
+ {
+ if (debug == 7) printf("@@@@ remote rx key\n");
+ if (!myrpt->remotetx)
+ {
+ remkeyed = 1;
}
}
/* if RX un-key */
- if (f->subclass == AST_CONTROL_RADIO_UNKEY) {
- ast_debug(8, "@@@@ remote rx un-key\n");
- if (!myrpt->remotetx) {
- ast_indicate(chan, AST_CONTROL_RADIO_UNKEY);
- myrpt->remoterx = 0;
+ if (f->subclass == AST_CONTROL_RADIO_UNKEY)
+ {
+ if (debug == 7) printf("@@@@ remote rx un-key\n");
+ if (!myrpt->remotetx)
+ {
+ remkeyed = 0;
}
}
}
ast_frfree(f);
continue;
}
- if ((myrpt->rxchannel != myrpt->txchannel) && (who == myrpt->txchannel)) {
- /* do this cuz you have to */
+ if (who == myrpt->pchannel) /* if is remote mix output */
+ {
+ f = ast_read(myrpt->pchannel);
+ if (!f)
+ {
+ if (debug) printf("@@@@ link:Hung Up\n");
+ break;
+ }
+ if (f->frametype == AST_FRAME_VOICE)
+ {
+ ast_write(chan,f);
+ }
+ 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;
+ }
+ if ((myrpt->rxchannel != myrpt->txchannel) &&
+ (who == myrpt->txchannel)) /* do this cuz you have to */
+ {
f = ast_read(myrpt->txchannel);
- if (!f) {
- ast_debug(1, "@@@@ link:Hung Up\n");
+ if (!f)
+ {
+ if (debug) printf("@@@@ link:Hung Up\n");
break;
}
- if (f->frametype == AST_FRAME_CONTROL) {
- if (f->subclass == AST_CONTROL_HANGUP) {
- ast_debug(1, "@@@@ rpt:Hung Up\n");
+ if (f->frametype == AST_FRAME_CONTROL)
+ {
+ if (f->subclass == AST_CONTROL_HANGUP)
+ {
+ if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
@@ -7417,64 +14526,684 @@ static int rpt_exec(struct ast_channel *chan, void *data)
ast_frfree(f);
continue;
}
+ }
+ if (myrpt->p.archivedir)
+ {
+ char mycmd[100],*b,*b1;
+ /* look at callerid to see what node this comes from */
+ if (!chan->cid.cid_num) /* if doesn't have caller id */
+ {
+ b1 = "0";
+ } else {
+ ast_callerid_parse(chan->cid.cid_num,&b,&b1);
+ ast_shrink_phone_number(b1);
+ }
+ sprintf(mycmd,"DISCONNECT,%s",b1);
+ donodelog(myrpt,mycmd);
}
+ /* wait for telem to be done */
+ while(myrpt->tele.next != &myrpt->tele) usleep(100000);
+ sprintf(tmp,"mixmonitor stop %s",chan->name);
+ ast_cli_command(nullfd,tmp);
+ close(nullfd);
rpt_mutex_lock(&myrpt->lock);
- if (myrpt->rxchannel != myrpt->txchannel)
- ast_hangup(myrpt->txchannel);
- ast_hangup(myrpt->rxchannel);
myrpt->hfscanmode = 0;
myrpt->hfscanstatus = 0;
myrpt->remoteon = 0;
rpt_mutex_unlock(&myrpt->lock);
+ if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
+ myrpt->lastf1 = NULL;
+ if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
+ myrpt->lastf2 = NULL;
+ if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
+ {
+ z.radpar = ZT_RADPAR_UIOMODE;
+ z.data = 3;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
+ return -1;
+ }
+ z.radpar = ZT_RADPAR_UIODATA;
+ z.data = 3;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot set UIODATA\n");
+ return -1;
+ }
+ i = ZT_OFFHOOK;
+ if (ioctl(myrpt->zaptxchannel->fds[0],ZT_HOOK,&i) == -1)
+ {
+ ast_log(LOG_ERROR,"Cannot set hook\n");
+ return -1;
+ }
+ }
+ if (myrpt->iofd) close(myrpt->iofd);
+ myrpt->iofd = -1;
+ ast_hangup(myrpt->pchannel);
+ if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
closerem(myrpt);
+ if (myrpt->p.rptnode)
+ {
+ rpt_mutex_lock(&myrpt->lock);
+ for(i = 0; i < nrpts; i++)
+ {
+ if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
+ {
+ rpt_vars[i].xlink = 0;
+ break;
+ }
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ }
+#ifdef OLD_ASTERISK
+ LOCAL_USER_REMOVE(u);
+#endif
return res;
}
+#ifndef OLD_ASTERISK
+/*!\brief callback to display list of locally configured nodes
+ \addtogroup Group_AMI
+ */
+static int manager_rpt_local_nodes(struct mansession *s, const struct message *m)
+{
+ int i;
+ astman_append(s, "<?xml version=\"1.0\"?>\r\n");
+ astman_append(s, "<nodes>\r\n");
+ for (i=0; i< nrpts; i++)
+ {
+ astman_append(s, " <node>%s</node>\r\n", rpt_vars[i].name);
+ } /* for i */
+ astman_append(s, "</nodes>\r\n");
+ astman_append(s, "\r\n"); /* Properly terminate Manager output */
+ return RESULT_SUCCESS;
+} /* manager_rpt_local_nodes() */
+
+
+
+/*
+ * Append Success and ActionID to manager response message
+ */
+
+static void rpt_manager_success(struct mansession *s, const struct message *m)
+{
+ const char *id = astman_get_header(m, "ActionID");
+ if (!ast_strlen_zero(id))
+ astman_append(s, "ActionID: %s\r\n", id);
+ astman_append(s, "Response: Success\r\n");
+}
+
+/*
+* Dump statistics to manager session
+*/
+
+static int rpt_manager_do_stats(struct mansession *s, const struct message *m, char *str)
+{
+ int i,j,numoflinks;
+ int dailytxtime, dailykerchunks;
+ time_t now;
+ int totalkerchunks, dailykeyups, totalkeyups, timeouts;
+ int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
+ long long totaltxtime;
+ struct rpt_link *l;
+ char *listoflinks[MAX_STAT_LINKS];
+ char *lastdtmfcommand,*parrot_ena;
+ char *tot_state, *ider_state, *patch_state;
+ char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
+ char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
+ char *transmitterkeyed;
+ const char *node = astman_get_header(m, "Node");
+ struct rpt *myrpt;
+
+ static char *not_applicable = "N/A";
+
+ tot_state = ider_state =
+ patch_state = reverse_patch_state =
+ input_signal = not_applicable;
+ called_number = lastdtmfcommand = transmitterkeyed = NULL;
+
+ time(&now);
+ for(i = 0; i < nrpts; i++)
+ {
+ if ((node)&&(!strcmp(node,rpt_vars[i].name))){
+ rpt_manager_success(s,m);
+
+ myrpt = &rpt_vars[i];
+
+ if(myrpt->remote){ /* Remote base ? */
+ char *loginuser, *loginlevel, *freq, *rxpl, *txpl, *modestr;
+ char offset,powerlevel,rxplon,txplon,remoteon,remmode,reportfmstuff;
+ char offsetc,powerlevelc;
+
+ loginuser = loginlevel = freq = rxpl = txpl = NULL;
+ /* Make a copy of all stat variables while locked */
+ rpt_mutex_lock(&myrpt->lock); /* LOCK */
+ if((remoteon = myrpt->remoteon)){
+ if(!ast_strlen_zero(myrpt->loginuser))
+ loginuser = ast_strdup(myrpt->loginuser);
+ if(!ast_strlen_zero(myrpt->loginlevel))
+ loginlevel = ast_strdup(myrpt->loginlevel);
+ if(!ast_strlen_zero(myrpt->freq))
+ freq = ast_strdup(myrpt->freq);
+ if(!ast_strlen_zero(myrpt->rxpl))
+ rxpl = ast_strdup(myrpt->rxpl);
+ if(!ast_strlen_zero(myrpt->txpl))
+ txpl = ast_strdup(myrpt->txpl);
+ remmode = myrpt->remmode;
+ offset = myrpt->offset;
+ powerlevel = myrpt->powerlevel;
+ rxplon = myrpt->rxplon;
+ txplon = myrpt->txplon;
+ }
+ rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
+ astman_append(s, "IsRemoteBase: YES\r\n");
+ astman_append(s, "RemoteOn: %s\r\n",(remoteon) ? "YES": "NO");
+ if(remoteon){
+ if(loginuser){
+ astman_append(s, "LogInUser: %s\r\n", loginuser);
+ ast_free(loginuser);
+ }
+ if(loginlevel){
+ astman_append(s, "LogInLevel: %s\r\n", loginlevel);
+ ast_free(loginlevel);
+ }
+ if(freq){
+ astman_append(s, "Freq: %s\r\n", freq);
+ ast_free(freq);
+ }
+ reportfmstuff = 0;
+ switch(remmode){
+ case REM_MODE_FM:
+ modestr = "FM";
+ reportfmstuff = 1;
+ break;
+ case REM_MODE_AM:
+ modestr = "AM";
+ break;
+ case REM_MODE_USB:
+ modestr = "USB";
+ break;
+ default:
+ modestr = "LSB";
+ break;
+ }
+ astman_append(s, "RemMode: %s\r\n", modestr);
+ if(reportfmstuff){
+ switch(offset){
+ case REM_SIMPLEX:
+ offsetc = 'S';
+ break;
+ case REM_MINUS:
+ offsetc = '-';
+ break;
+ default:
+ offsetc = '+';
+ break;
+ }
+ astman_append(s, "RemOffset: %c\r\n", offsetc);
+ if(rxplon && rxpl){
+ astman_append(s, "RxPl: %s\r\n",rxpl);
+ free(rxpl);
+ }
+ if(txplon && txpl){
+ astman_append(s, "TxPl: %s\r\n",txpl);
+ free(txpl);
+ }
+ }
+ switch(powerlevel){
+ case REM_LOWPWR:
+ powerlevelc = 'L';
+ break;
+ case REM_MEDPWR:
+ powerlevelc = 'M';
+ break;
+ default:
+ powerlevelc = 'H';
+ break;
+ }
+ astman_append(s,"PowerLevel: %c\r\n", powerlevelc);
+ }
+ astman_append(s, "\r\n");
+ return 0; /* End of remote base status reporting */
+ }
+
+ /* ELSE Process as a repeater node */
+ /* Make a copy of all stat variables while locked */
+ rpt_mutex_lock(&myrpt->lock); /* LOCK */
+ dailytxtime = myrpt->dailytxtime;
+ totaltxtime = myrpt->totaltxtime;
+ dailykeyups = myrpt->dailykeyups;
+ totalkeyups = myrpt->totalkeyups;
+ dailykerchunks = myrpt->dailykerchunks;
+ totalkerchunks = myrpt->totalkerchunks;
+ dailyexecdcommands = myrpt->dailyexecdcommands;
+ totalexecdcommands = myrpt->totalexecdcommands;
+ timeouts = myrpt->timeouts;
+
+
+ /* Traverse the list of connected nodes */
+ reverse_patch_state = "DOWN";
+ numoflinks = 0;
+ l = myrpt->links.next;
+ while(l && (l != &myrpt->links)){
+ if(numoflinks >= MAX_STAT_LINKS){
+ ast_log(LOG_NOTICE,
+ "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
+ break;
+ }
+ if (l->name[0] == '0'){ /* Skip '0' nodes */
+ reverse_patch_state = "UP";
+ l = l->next;
+ continue;
+ }
+ listoflinks[numoflinks] = ast_strdup(l->name);
+ if(listoflinks[numoflinks] == NULL){
+ break;
+ }
+ else{
+ numoflinks++;
+ }
+ l = l->next;
+ }
+
+ if(myrpt->keyed)
+ input_signal = "YES";
+ else
+ input_signal = "NO";
+
+ if(myrpt->txkeyed)
+ transmitterkeyed = "YES";
+ else
+ transmitterkeyed = "NO";
+
+ if(myrpt->p.parrotmode)
+ parrot_ena = "ENABLED";
+ else
+ parrot_ena = "DISABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
+ sys_ena = "DISABLED";
+ else
+ sys_ena = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
+ tot_ena = "DISABLED";
+ else
+ tot_ena = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
+ link_ena = "DISABLED";
+ else
+ link_ena = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
+ patch_ena = "DISABLED";
+ else
+ patch_ena = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
+ sch_ena = "DISABLED";
+ else
+ sch_ena = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
+ user_funs = "DISABLED";
+ else
+ user_funs = "ENABLED";
+
+ if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
+ tail_type = "ALTERNATE";
+ else
+ tail_type = "STANDARD";
+
+ if(!myrpt->totimer)
+ tot_state = "TIMED OUT!";
+ else if(myrpt->totimer != myrpt->p.totime)
+ tot_state = "ARMED";
+ else
+ tot_state = "RESET";
+
+ if(myrpt->tailid)
+ ider_state = "QUEUED IN TAIL";
+ else if(myrpt->mustid)
+ ider_state = "QUEUED FOR CLEANUP";
+ else
+ ider_state = "CLEAN";
+
+ switch(myrpt->callmode){
+ case 1:
+ patch_state = "DIALING";
+ break;
+ case 2:
+ patch_state = "CONNECTING";
+ break;
+ case 3:
+ patch_state = "UP";
+ break;
+
+ case 4:
+ patch_state = "CALL FAILED";
+ break;
+
+ default:
+ patch_state = "DOWN";
+ }
+
+ if(strlen(myrpt->exten)){
+ called_number = ast_strdup(myrpt->exten);
+ }
+
+ if(strlen(myrpt->lastdtmfcommand)){
+ lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
+ }
+ rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
+
+ astman_append(s, "IsRemoteBase: NO\r\n");
+ astman_append(s, "NodeState: %d\r\n", myrpt->p.sysstate_cur);
+ astman_append(s, "SignalOnInput: %s\r\n", input_signal);
+ astman_append(s, "TransmitterKeyed: %s\r\n", transmitterkeyed);
+ astman_append(s, "Transmitter: %s\r\n", sys_ena);
+ astman_append(s, "Parrot: %s\r\n", parrot_ena);
+ astman_append(s, "Scheduler: %s\r\n", sch_ena);
+ astman_append(s, "TailLength: %s\r\n", tail_type);
+ astman_append(s, "TimeOutTimer: %s\r\n", tot_ena);
+ astman_append(s, "TimeOutTimerState: %s\r\n", tot_state);
+ astman_append(s, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts);
+ astman_append(s, "IdentifierState: %s\r\n", ider_state);
+ astman_append(s, "KerchunksToday: %d\r\n", dailykerchunks);
+ astman_append(s, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks);
+ astman_append(s, "KeyupsToday: %d\r\n", dailykeyups);
+ astman_append(s, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups);
+ astman_append(s, "DtmfCommandsToday: %d\r\n", dailyexecdcommands);
+ astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
+ astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
+ (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
+ hours = dailytxtime/3600000;
+ dailytxtime %= 3600000;
+ minutes = dailytxtime/60000;
+ dailytxtime %= 60000;
+ seconds = dailytxtime/1000;
+ dailytxtime %= 1000;
+
+ astman_append(s, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
+ hours, minutes, seconds, dailytxtime);
+
+ hours = (int) totaltxtime/3600000;
+ totaltxtime %= 3600000;
+ minutes = (int) totaltxtime/60000;
+ totaltxtime %= 60000;
+ seconds = (int) totaltxtime/1000;
+ totaltxtime %= 1000;
+
+ astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
+ hours, minutes, seconds, (int) totaltxtime);
+
+ sprintf(str, "NodesCurrentlyConnectedToUs: ");
+ if(!numoflinks){
+ strcat(str,"<NONE>");
+ }
+ else{
+ for(j = 0 ;j < numoflinks; j++){
+ sprintf(str+strlen(str), "%s", listoflinks[j]);
+ if(j < numoflinks - 1)
+ strcat(str,",");
+ }
+ }
+ astman_append(s,"%s\r\n", str);
+
+ astman_append(s, "Autopatch: %s\r\n", patch_ena);
+ astman_append(s, "AutopatchState: %s\r\n", patch_state);
+ astman_append(s, "AutopatchCalledNumber: %s\r\n",
+ (called_number && strlen(called_number)) ? called_number : not_applicable);
+ astman_append(s, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state);
+ astman_append(s, "UserLinkingCommands: %s\r\n", link_ena);
+ astman_append(s, "UserFunctions: %s\r\n", user_funs);
+
+ for(j = 0; j < numoflinks; j++){ /* ast_free() all link names */
+ ast_free(listoflinks[j]);
+ }
+ if(called_number){
+ ast_free(called_number);
+ }
+ if(lastdtmfcommand){
+ ast_free(lastdtmfcommand);
+ }
+ astman_append(s, "\r\n"); /* We're Done! */
+ return 0;
+ }
+ }
+ astman_send_error(s, m, "RptStatus unknown or missing node");
+ return -1;
+}
+
+
+
+/*
+ * Implement the RptStatus Manager Interface
+ */
+
+static int manager_rpt_status(struct mansession *s, const struct message *m)
+{
+ int i,res,len,index;
+ int uptime,hours,minutes;
+ time_t now;
+ const char *cmd = astman_get_header(m, "Command");
+ char *str;
+ enum {MGRCMD_RPTSTAT,MGRCMD_NODESTAT};
+ struct mgrcmdtbl{
+ const char *cmd;
+ int index;
+ };
+ static struct mgrcmdtbl mct[] = {
+ {"RptStat",MGRCMD_RPTSTAT},
+ {"NodeStat",MGRCMD_NODESTAT},
+ {NULL,0} /* NULL marks end of command table */
+ };
+
+ time(&now);
+
+ len = 1024; /* Allocate a working buffer */
+ if(!(str = ast_malloc(len)))
+ return -1;
+
+ /* Check for Command */
+ if(ast_strlen_zero(cmd)){
+ astman_send_error(s, m, "RptStatus missing command");
+ ast_free(str);
+ return 0;
+ }
+ /* Try to find the command in the table */
+ for(i = 0 ; mct[i].cmd ; i++){
+ if(!strcmp(mct[i].cmd, cmd))
+ break;
+ }
+
+ if(!mct[i].cmd){ /* Found or not found ? */
+ astman_send_error(s, m, "RptStatus unknown command");
+ ast_free(str);
+ return 0;
+ }
+ else
+ index = mct[i].index;
+
+ switch(index){ /* Use the index to go to the correct command */
+
+ case MGRCMD_RPTSTAT:
+ /* Return Nodes: and a comma separated list of nodes */
+ if((res = snprintf(str, len, "Nodes: ")) > -1)
+ len -= res;
+ else{
+ ast_free(str);
+ return 0;
+ }
+ for(i = 0; i < nrpts; i++){
+ if(i < nrpts - 1){
+ if((res = snprintf(str+strlen(str), len, "%s,",rpt_vars[i].name)) < 0){
+ ast_free(str);
+ return 0;
+ }
+ }
+ else{
+ if((res = snprintf(str+strlen(str), len, "%s",rpt_vars[i].name)) < 0){
+ ast_free(str);
+ return 0;
+ }
+ }
+ len -= res;
+ }
+
+ rpt_manager_success(s,m);
+
+ if(!nrpts)
+ astman_append(s, "<NONE>\r\n");
+ else
+ astman_append(s, "%s\r\n", str);
+
+ uptime = (int)(now - starttime);
+ hours = uptime/3600;
+ uptime %= 3600;
+ minutes = uptime/60;
+ uptime %= 60;
+
+ astman_append(s, "RptUptime: %02d:%02d:%02d\r\n",
+ hours, minutes, uptime);
+
+ astman_append(s, "\r\n");
+ break;
+
+ case MGRCMD_NODESTAT:
+ res = rpt_manager_do_stats(s,m,str);
+ ast_free(str);
+ return res;
+
+ default:
+ astman_send_error(s, m, "RptStatus invalid command");
+ break;
+ }
+ ast_free(str);
+ return 0;
+}
+
+#endif
+
+#ifdef OLD_ASTERISK
+int unload_module()
+#else
static int unload_module(void)
+#endif
{
- int i;
+ int i, res;
- for (i = 0; i < nrpts; i++) {
- if (!strcmp(rpt_vars[i].name, rpt_vars[i].p.nodes))
- continue;
- ast_mutex_destroy(&rpt_vars[i].lock);
+#ifdef OLD_ASTERISK
+ STANDARD_HANGUP_LOCALUSERS;
+#endif
+ for(i = 0; i < nrpts; i++) {
+ if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
+ ast_mutex_destroy(&rpt_vars[i].lock);
+ ast_mutex_destroy(&rpt_vars[i].remlock);
}
- i = ast_unregister_application(app);
+ res = ast_unregister_application(app);
+#ifdef NEW_ASTERISK
+ ast_cli_unregister_multiple(rpt_cli,sizeof(rpt_cli) /
+ sizeof(struct ast_cli_entry));
+#else
/* Unregister cli extensions */
- ast_cli_unregister_multiple(cli_rpt, sizeof(cli_rpt) / sizeof(struct ast_cli_entry));
-
- return i;
+ ast_cli_unregister(&cli_debug);
+ ast_cli_unregister(&cli_dump);
+ ast_cli_unregister(&cli_stats);
+ ast_cli_unregister(&cli_lstats);
+ ast_cli_unregister(&cli_nodes);
+ ast_cli_unregister(&cli_local_nodes);
+ ast_cli_unregister(&cli_reload);
+ ast_cli_unregister(&cli_restart);
+ ast_cli_unregister(&cli_fun);
+ ast_cli_unregister(&cli_fun1);
+ res |= ast_cli_unregister(&cli_cmd);
+#endif
+#ifndef OLD_ASTERISK
+ res |= ast_manager_unregister("RptLocalNodes");
+ res |= ast_manager_unregister("RptStatus");
+#endif
+ return res;
}
+#ifdef OLD_ASTERISK
+int load_module()
+#else
static int load_module(void)
+#endif
{
- struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
- struct ast_config *cfg = ast_config_load("rpt.conf", config_flags);
- if (!cfg) {
- ast_log(LOG_WARNING, "No such configuration file rpt.conf\n");
- return AST_MODULE_LOAD_DECLINE;
- }
- ast_pthread_create(&rpt_master_thread, NULL, rpt_master, cfg);
+ int res;
+ ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
+#ifdef NEW_ASTERISK
+ ast_cli_register_multiple(rpt_cli,sizeof(rpt_cli) /
+ sizeof(struct ast_cli_entry));
+ res = 0;
+#else
/* Register cli extensions */
- ast_cli_register_multiple(cli_rpt, sizeof(cli_rpt) / sizeof(struct ast_cli_entry));
+ ast_cli_register(&cli_debug);
+ ast_cli_register(&cli_dump);
+ ast_cli_register(&cli_stats);
+ ast_cli_register(&cli_lstats);
+ ast_cli_register(&cli_nodes);
+ ast_cli_register(&cli_local_nodes);
+ ast_cli_register(&cli_reload);
+ ast_cli_register(&cli_restart);
+ ast_cli_register(&cli_fun);
+ ast_cli_register(&cli_fun1);
+ res = ast_cli_register(&cli_cmd);
+#endif
+#ifndef OLD_ASTERISK
+ res |= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes, "List local node numbers");
+ res |= ast_manager_register("RptStatus", 0, manager_rpt_status, "Return Rpt Status for CGI");
+
+#endif
+ res |= ast_register_application(app, rpt_exec, synopsis, descrip);
+ return res;
+}
+
+#ifdef OLD_ASTERISK
+char *description()
+{
+ return tdesc;
+}
+int usecount(void)
+{
+ int res;
+ STANDARD_USECOUNT(res);
+ return res;
+}
- return ast_register_application(app, rpt_exec, synopsis, descrip);
+char *key()
+{
+ return ASTERISK_GPL_KEY;
}
+#endif
+#ifdef OLD_ASTERISK
+int reload()
+#else
static int reload(void)
+#endif
{
- int n;
+int n;
- for (n = 0; n < nrpts; n++)
- rpt_vars[n].reload = 1;
+ for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
return(0);
}
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater / Remote Base",
+
+#ifndef OLD_ASTERISK
+/* STD_MOD(MOD_1, reload, NULL, NULL); */
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
.load = load_module,
.unload = unload_module,
.reload = reload,
- );
+ );
+#endif
+
diff --git a/channels/Makefile b/channels/Makefile
index 34bd8e092..4ceec696d 100644
--- a/channels/Makefile
+++ b/channels/Makefile
@@ -101,3 +101,9 @@ misdn/isdn_lib.o: ASTCFLAGS+=-Wno-strict-aliasing
$(if $(filter chan_misdn,$(EMBEDDED_MODS)),modules.link,chan_misdn.so): misdn_config.o misdn/isdn_lib.o misdn/isdn_msg_parser.o
$(if $(filter chan_oss,$(EMBEDDED_MODS)),modules.link,chan_oss.so): console_video.o vgrabbers.o console_board.o
+
+chan_usbradio.o: ./xpmr/xpmr.c ./xpmr/xpmr.h ./xpmr/xpmr_coef.h
+
+chan_usbradio.so: LIBS+=-lusb -lasound
+
+
diff --git a/channels/chan_usbradio.c b/channels/chan_usbradio.c
index f7c05a670..f94ccd1da 100644
--- a/channels/chan_usbradio.c
+++ b/channels/chan_usbradio.c
@@ -1,8 +1,9 @@
+#define NEW_ASTERISK
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
- * Copyright (C) 2007, Jim Dixon
+ * Copyright (C) 2007 - 2008, Jim Dixon
*
* Jim Dixon, WB6NIL <jim@lambdatel.com>
* Steve Henke, W9SH <w9sh@arrl.net>
@@ -33,31 +34,47 @@
*/
/*** MODULEINFO
- <depend>asound</depend>
- <depend>usb</depend>
+ <depend>ossaudio</depend>
+ <depend>usb</depend>
<defaultenabled>no</defaultenabled>
+ <member name="RADIO_RTX" displayname="Build RTX/DTX Radio Programming">
+ <defaultenabled>no</defaultenabled>
+ </member>
+ <member name="RADIO_XPMRX" displayname="Build Experimental Radio Protocols">
+ <defaultenabled>no</defaultenabled>
+ </member>
***/
+// 20070918 1600 EDT sph@xelatec.com changing to rx driven streams
+
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include <stdio.h>
#include <ctype.h>
#include <math.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/io.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/time.h>
+#include <stdlib.h>
+#include <errno.h>
#include <usb.h>
#include <alsa/asoundlib.h>
-#define CHAN_USBRADIO 1
+//#define HAVE_XPMRX 1
+#ifdef RADIO_XPMRX
+#define HAVE_XPMRX 1
+#endif
+#define CHAN_USBRADIO 1
#define DEBUG_USBRADIO 0
#define DEBUG_CAPTURES 1
-
#define DEBUG_CAP_RX_OUT 0
#define DEBUG_CAP_TX_OUT 0
-
#define DEBUG_FILETEST 0
#define RX_CAP_RAW_FILE "/tmp/rx_cap_in.pcm"
@@ -76,18 +93,27 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define MIXER_PARAM_SPKR_PLAYBACK_SW "Speaker Playback Switch"
#define MIXER_PARAM_SPKR_PLAYBACK_VOL "Speaker Playback Volume"
+#define DELIMCHR ','
+#define QUOTECHR 34
+
+#define READERR_THRESHOLD 50
+
#include "./xpmr/xpmr.h"
+#ifdef HAVE_XPMRX
+#include "./xpmrx/xpmrx.h"
+#include "./xpmrx/bitweight.h"
+#endif
#if 0
-#define traceusb1(a, ...) ast_debug(4, a __VA_ARGS__)
+#define traceusb1(a) {printf a;}
#else
-#define traceusb1(a, ...)
+#define traceusb1(a)
#endif
#if 0
-#define traceusb2(a, ...) ast_debug(4, a __VA_ARGS__)
+#define traceusb2(a) {printf a;}
#else
-#define traceusb2(a, ...)
+#define traceusb2(a)
#endif
#ifdef __linux
@@ -100,9 +126,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/frame.h"
+#include "asterisk/logger.h"
#include "asterisk/callerid.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
+#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
@@ -114,6 +142,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
+#ifndef NEW_ASTERISK
+
+/* ringtones we use */
+#include "busy.h"
+#include "ringtone.h"
+#include "ring10.h"
+#include "answer.h"
+
+#endif
+
#define C108_VENDOR_ID 0x0d8c
#define C108_PRODUCT_ID 0x000c
#define C108_HID_INTERFACE 3
@@ -124,6 +162,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define HID_RT_INPUT 0x01
#define HID_RT_OUTPUT 0x02
+#define EEPROM_START_ADDR 6
+#define EEPROM_END_ADDR 63
+#define EEPROM_PHYSICAL_LEN 64
+#define EEPROM_TEST_ADDR EEPROM_END_ADDR
+#define EEPROM_MAGIC_ADDR 6
+#define EEPROM_MAGIC 34329
+#define EEPROM_CS_ADDR 62
+#define EEPROM_RXMIXERSET 8
+#define EEPROM_TXMIXASET 9
+#define EEPROM_TXMIXBSET 10
+#define EEPROM_RXVOICEADJ 11
+#define EEPROM_RXCTCSSADJ 13
+#define EEPROM_TXCTCSSADJ 15
+#define EEPROM_RXSQUELCHADJ 16
+
/*! Global jitterbuffer configuration - by default, jb is disabled */
static struct ast_jb_conf default_jbconf =
{
@@ -134,14 +187,15 @@ static struct ast_jb_conf default_jbconf =
};
static struct ast_jb_conf global_jbconf;
-/*!
+/*
* usbradio.conf parameters are
START_CONFIG
[general]
- ; General config options, with default values shown.
- ; You should use one section per device, with [general] being used
- ; for the device.
+ ; General config options which propigate to all devices, with
+ ; default values shown. You may have as many devices as the
+ ; system will allow. You must use one section per device, with
+ ; [usb] generally (although its up to you) being the first device.
;
;
; debug = 0x0 ; misc debug flags, default is 0
@@ -151,10 +205,11 @@ START_CONFIG
; Set hardware type here
; hdwtype=0 ; 0=limey, 1=sph
- ; rxboostset=0 ; no rx gain boost
+ ; rxboost=0 ; no rx gain boost
; rxctcssrelax=1 ; reduce talkoff from radios w/o CTCSS Tx HPF
- ; rxctcssfreq=100.0 ; rx ctcss freq in floating point. must be in table
- ; txctcssfreq=100.0 ; tx ctcss freq, any frequency permitted
+ ; rxctcssfreqs=100.0,123.0 ; list of rx ctcss freq in floating point. must be in table
+ ; txctcssfreqs=100.0,123.0 ; list tx ctcss freq, any frequency permitted
+ ; txctcssdefault=100.0 ; default tx ctcss freq, any frequency permitted
; carrierfrom=dsp ;no,usb,usbinvert,dsp,vox
; ctcssfrom=dsp ;no,usb,dsp
@@ -191,12 +246,47 @@ START_CONFIG
; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
;-----------------------------------------------------------------------------------
+[usb]
+
+; First channel unique config
+
+[usb1]
+
+; Second channel config
END_CONFIG
*/
-/*!
+/*
+ * Helper macros to parse config arguments. They will go in a common
+ * header file if their usage is globally accepted. In the meantime,
+ * we define them here. Typical usage is as below.
+ * Remember to open a block right before M_START (as it declares
+ * some variables) and use the M_* macros WITHOUT A SEMICOLON:
+ *
+ * {
+ * M_START(v->name, v->value)
+ *
+ * M_BOOL("dothis", x->flag1)
+ * M_STR("name", x->somestring)
+ * M_F("bar", some_c_code)
+ * M_END(some_final_statement)
+ * ... other code in the block
+ * }
+ *
+ * XXX NOTE these macros should NOT be replicated in other parts of asterisk.
+ * Likely we will come up with a better way of doing config file parsing.
+ */
+#define M_START(var, val) \
+ char *__s = var; char *__val = val;
+#define M_END(x) x;
+#define M_F(tag, f) if (!strcasecmp((__s), tag)) { f; } else
+#define M_BOOL(tag, dst) M_F(tag, (dst) = ast_true(__val) )
+#define M_UINT(tag, dst) M_F(tag, (dst) = strtoul(__val, NULL, 0) )
+#define M_STR(tag, dst) M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))
+
+/*
* The following parameters are used in the driver:
*
* FRAME_SIZE the size of an audio frame, in samples.
@@ -227,7 +317,7 @@ END_CONFIG
*/
#define FRAME_SIZE 160
-#define QUEUE_SIZE 20
+#define QUEUE_SIZE 2
#if defined(__FreeBSD__)
#define FRAGS 0x8
@@ -260,19 +350,22 @@ END_CONFIG
#endif
static char *config = "usbradio.conf"; /* default config file */
-static char *config1 = "usbradio_tune.conf"; /* tune config file */
+static char *config1 = "usbradio_tune_%s.conf"; /* tune config file */
static FILE *frxcapraw = NULL, *frxcaptrace = NULL, *frxoutraw = NULL;
static FILE *ftxcapraw = NULL, *ftxcaptrace = NULL, *ftxoutraw = NULL;
+static char *usb_device_list = NULL;
+static int usb_device_list_size = 0;
+
static int usbradio_debug;
-#if 0 /* maw asdf sph */
+#if 0 //maw asdf sph
static int usbradio_debug_level = 0;
#endif
enum {RX_AUDIO_NONE,RX_AUDIO_SPEAKER,RX_AUDIO_FLAT};
enum {CD_IGNORE,CD_XPMR_NOISE,CD_XPMR_VOX,CD_HID,CD_HID_INVERT};
-enum {SD_IGNORE,SD_HID,SD_HID_INVERT,SD_XPMR}; /* no,external,externalinvert,software */
+enum {SD_IGNORE,SD_HID,SD_HID_INVERT,SD_XPMR}; // no,external,externalinvert,software
enum {RX_KEY_CARRIER,RX_KEY_CARRIER_CODE};
enum {TX_OUT_OFF,TX_OUT_VOICE,TX_OUT_LSD,TX_OUT_COMPOSITE,TX_OUT_AUX};
enum {TOC_NONE,TOC_PHASE,TOC_NOTONE};
@@ -280,6 +373,34 @@ enum {TOC_NONE,TOC_PHASE,TOC_NOTONE};
/* DECLARE STRUCTURES */
/*
+ * Each sound is made of 'datalen' samples of sound, repeated as needed to
+ * generate 'samplen' samples of data, then followed by 'silencelen' samples
+ * of silence. The loop is repeated if 'repeat' is set.
+ */
+struct sound {
+ int ind;
+ char *desc;
+ short *data;
+ int datalen;
+ int samplen;
+ int silencelen;
+ int repeat;
+};
+
+#ifndef NEW_ASTERISK
+
+static struct sound sounds[] = {
+ { AST_CONTROL_RINGING, "RINGING", ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
+ { AST_CONTROL_BUSY, "BUSY", busy, sizeof(busy)/2, 4000, 4000, 1 },
+ { AST_CONTROL_CONGESTION, "CONGESTION", busy, sizeof(busy)/2, 2000, 2000, 1 },
+ { AST_CONTROL_RING, "RING10", ring10, sizeof(ring10)/2, 16000, 32000, 1 },
+ { AST_CONTROL_ANSWER, "ANSWER", answer, sizeof(answer)/2, 2200, 0, 0 },
+ { -1, NULL, 0, 0, 0, 0 }, /* end marker */
+};
+
+#endif
+
+/*
* descriptor for one of our channels.
* There is one used for 'default' values (from the [general] entry in
* the configuration file), and then one instance for each device
@@ -290,8 +411,22 @@ struct chan_usbradio_pvt {
struct chan_usbradio_pvt *next;
char *name;
+#ifndef NEW_ASTERISK
+ /*
+ * cursound indicates which in struct sound we play. -1 means nothing,
+ * any other value is a valid sound, in which case sampsent indicates
+ * the next sample to send in [0..samplen + silencelen]
+ * nosound is set to disable the audio data from the channel
+ * (so we can play the tones etc.).
+ */
+ int sndcmd[2]; /* Sound command pipe */
+ int cursound; /* index of sound to send */
+ int sampsent; /* # of sound samples sent */
+ int nosound; /* set to block audio from the PBX */
+#endif
- int total_blocks; /* total blocks in the output device */
+ int pttkick[2];
+ int total_blocks; /* total blocks in the output device */
int sounddev;
enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;
i16 cdMethod;
@@ -301,11 +436,11 @@ struct chan_usbradio_pvt {
unsigned int queuesize; /* max fragments in queue */
unsigned int frags; /* parameter for SETFRAGMENT */
- int warned; /* various flags used for warnings */
+ int warned; /* various flags used for warnings */
#define WARN_used_blocks 1
#define WARN_speed 2
#define WARN_frag 4
- int w_errors; /* overfull in the write path */
+ int w_errors; /* overfull in the write path */
struct timeval lastopen;
int overridecontext;
@@ -315,109 +450,178 @@ struct chan_usbradio_pvt {
* be representable in 16 bits to avoid overflows.
*/
#define BOOST_SCALE (1<<9)
-#define BOOST_MAX 40 /* slightly less than 7 bits */
- int boost; /* input boost, scaled by BOOST_SCALE */
+#define BOOST_MAX 40 /* slightly less than 7 bits */
+ int boost; /* input boost, scaled by BOOST_SCALE */
char devicenum;
+ char devstr[128];
int spkrmax;
int micmax;
+#ifndef NEW_ASTERISK
pthread_t sthread;
+#endif
pthread_t hidthread;
- int stophid;
+ int stophid;
+ FILE *hkickhid;
+
struct ast_channel *owner;
- char ext[AST_MAX_EXTENSION];
- char ctx[AST_MAX_CONTEXT];
- char language[MAX_LANGUAGE];
- char cid_name[256]; /* XXX */
- char cid_num[256]; /* XXX */
- char mohinterpret[MAX_MUSICCLASS];
+ char ext[AST_MAX_EXTENSION];
+ char ctx[AST_MAX_CONTEXT];
+ char language[MAX_LANGUAGE];
+ char cid_name[256]; /*XXX */
+ char cid_num[256]; /*XXX */
+ char mohinterpret[MAX_MUSICCLASS];
/* buffers used in usbradio_write, 2 per int by 2 channels by 6 times oversampling (48KS/s) */
- char usbradio_write_buf[FRAME_SIZE * 2 * 2 * 6];
- char usbradio_write_buf_1[FRAME_SIZE * 2 * 2 * 6];
+ char usbradio_write_buf[FRAME_SIZE * 2 * 2 * 6];
+ char usbradio_write_buf_1[FRAME_SIZE * 2 * 2* 6];
- int usbradio_write_dst;
+ int usbradio_write_dst;
/* buffers used in usbradio_read - AST_FRIENDLY_OFFSET space for headers
* plus enough room for a full frame
*/
- char usbradio_read_buf[FRAME_SIZE * (2 * 12) + AST_FRIENDLY_OFFSET];
- char usbradio_read_buf_8k[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
- int readpos; /* read position above */
- struct ast_frame read_f; /* returned by usbradio_read */
-
+ char usbradio_read_buf[FRAME_SIZE * (2 * 12) + AST_FRIENDLY_OFFSET];
+ char usbradio_read_buf_8k[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
+ int readpos; /* read position above */
+ struct ast_frame read_f; /* returned by usbradio_read */
+
+ char debuglevel;
+ char radioduplex; //
+ char wanteeprom;
+
+ int tracetype;
+ int tracelevel;
+ char area;
+ char rptnum;
+ int idleinterval;
+ int turnoffs;
+ int txsettletime;
+ char ukey[48];
+
+ char lastrx;
+ char rxhidsq;
+ char rxcarrierdetect; // status from pmr channel
+ char rxctcssdecode; // status from pmr channel
+
+ int rxdcsdecode;
+ int rxlsddecode;
+
+ char rxkeytype;
+ char rxkeyed; // indicates rx signal present
+
+ char lasttx;
+ char txkeyed; // tx key request from upper layers
+ char txchankey;
+ char txtestkey;
+
+ time_t lasthidtime;
+ struct ast_dsp *dsp;
- char debuglevel;
- char radioduplex;
+ t_pmr_chan *pmrChan;
- char lastrx;
- char rxhidsq;
- char rxcarrierdetect; /*!< status from pmr channel */
- char rxctcssdecode; /*!< status from pmr channel */
+ char rxcpusaver;
+ char txcpusaver;
- char rxkeytype;
- char rxkeyed; /*!< indicates rx signal present */
+ char rxdemod;
+ float rxgain;
+ char rxcdtype;
+ char rxsdtype;
+ int rxsquelchadj; /* this copy needs to be here for initialization */
+ int rxsqvoxadj;
+ char txtoctype;
- char lasttx;
- char txkeyed; /*! tx key request from upper layers */
- char txchankey;
- char txtestkey;
+ char txprelim;
+ float txctcssgain;
+ char txmixa;
+ char txmixb;
- time_t lasthidtime;
- struct ast_dsp *dsp;
+ char invertptt;
- t_pmr_chan *pmrChan;
+ char rxctcssrelax;
+ float rxctcssgain;
- char rxcpusaver;
- char txcpusaver;
+ char txctcssdefault[16]; // for repeater operation
+ char rxctcssfreqs[512]; // a string
+ char txctcssfreqs[512];
- char rxdemod;
- float rxgain;
- char rxcdtype;
- char rxsdtype;
- int rxsquelchadj; /*!< this copy needs to be here for initialization */
- char txtoctype;
+ char txctcssfreq[32]; // encode now
+ char rxctcssfreq[32]; // decode now
- char txprelim;
- float txctcssgain;
- char txmixa;
- char txmixb;
-
- char invertptt;
-
- char rxctcssrelax;
- float rxctcssgain;
- float rxctcssfreq;
- float txctcssfreq;
-
- int rxmixerset;
- int rxboostset;
- float rxvoiceadj;
- float rxctcssadj;
- int txmixaset;
- int txmixbset;
+ char numrxctcssfreqs; // how many
+ char numtxctcssfreqs;
+
+ char *rxctcss[CTCSS_NUM_CODES]; // pointers to strings
+ char *txctcss[CTCSS_NUM_CODES];
+
+ int txfreq; // in Hz
+ int rxfreq;
+
+ // start remote operation info
+ char set_txctcssdefault[16]; // for remote operation
+ char set_txctcssfreq[16]; // encode now
+ char set_rxctcssfreq[16]; // decode now
+
+ char set_numrxctcssfreqs; // how many
+ char set_numtxctcssfreqs;
+
+ char set_rxctcssfreqs[16]; // a string
+ char set_txctcssfreqs[16];
+
+ char *set_rxctcss; // pointers to strings
+ char *set_txctcss;
+
+ int set_txfreq; // in Hz
+ int set_rxfreq;
+ // end remote operation info
+
+ int rxmixerset;
+ int rxboostset;
+ float rxvoiceadj;
+ float rxctcssadj;
+ int txmixaset;
+ int txmixbset;
int txctcssadj;
int hdwtype;
- int hid_gpio_ctl;
- int hid_gpio_ctl_loc;
- int hid_io_cor;
- int hid_io_cor_loc;
- int hid_io_ctcss;
- int hid_io_ctcss_loc;
- int hid_io_ptt;
- int hid_gpio_loc;
+ int hid_gpio_ctl;
+ int hid_gpio_ctl_loc;
+ int hid_io_cor;
+ int hid_io_cor_loc;
+ int hid_io_ctcss;
+ int hid_io_ctcss_loc;
+ int hid_io_ptt;
+ int hid_gpio_loc;
struct {
- unsigned rxcapraw:1;
+ unsigned rxcapraw:1;
unsigned txcapraw:1;
unsigned txcap2:1;
unsigned rxcap2:1;
- } b;
+ unsigned rxplmon:1;
+ unsigned remoted:1;
+ unsigned txpolarity:1;
+ unsigned rxpolarity:1;
+ unsigned dcstxpolarity:1;
+ unsigned dcsrxpolarity:1;
+ unsigned lsdtxpolarity:1;
+ unsigned lsdrxpolarity:1;
+ unsigned loopback:1;
+ unsigned radioactive:1;
+ }b;
+ unsigned short eeprom[EEPROM_PHYSICAL_LEN];
+ char eepromctl;
+ ast_mutex_t eepromlock;
+
+ struct usb_dev_handle *usb_handle;
+ int readerrs;
};
-/* maw add additional defaults !!! */
+// maw add additional defaults !!!
static struct chan_usbradio_pvt usbradio_default = {
+#ifndef NEW_ASTERISK
+ .cursound = -1,
+#endif
.sounddev = -1,
.duplex = M_UNSET, /* XXX check this */
.autoanswer = 1,
@@ -429,26 +633,29 @@ static struct chan_usbradio_pvt usbradio_default = {
.readpos = AST_FRIENDLY_OFFSET, /* start here on reads */
.lastopen = { 0, 0 },
.boost = BOOST_SCALE,
+ .wanteeprom = 1,
+ .area = 0,
+ .rptnum = 0,
};
/* DECLARE FUNCTION PROTOTYPES */
-static void store_txtoctype(struct chan_usbradio_pvt *o, const char *s);
-static int hidhdwconfig(struct chan_usbradio_pvt *o);
-static int set_txctcss_level(struct chan_usbradio_pvt *o);
+static void store_txtoctype(struct chan_usbradio_pvt *o, char *s);
+static int hidhdwconfig(struct chan_usbradio_pvt *o);
+static int set_txctcss_level(struct chan_usbradio_pvt *o);
static void pmrdump(struct chan_usbradio_pvt *o);
static void mult_set(struct chan_usbradio_pvt *o);
static int mult_calc(int value);
static void mixer_write(struct chan_usbradio_pvt *o);
-static void tune_rxinput(struct chan_usbradio_pvt *o);
-static void tune_rxvoice(struct chan_usbradio_pvt *o);
-static void tune_rxctcss(struct chan_usbradio_pvt *o);
-static void tune_txoutput(struct chan_usbradio_pvt *o, int value);
+static void tune_rxinput(int fd, struct chan_usbradio_pvt *o);
+static void tune_rxvoice(int fd, struct chan_usbradio_pvt *o);
+static void tune_rxctcss(int fd, struct chan_usbradio_pvt *o);
+static void tune_txoutput(struct chan_usbradio_pvt *o, int value, int fd);
static void tune_write(struct chan_usbradio_pvt *o);
static char *usbradio_active; /* the active device */
-static int setformat(struct chan_usbradio_pvt *o, int mode);
+static int setformat(struct chan_usbradio_pvt *o, int mode);
static struct ast_channel *usbradio_request(const char *type, int format, void *data
, int *cause);
@@ -462,6 +669,7 @@ static int usbradio_call(struct ast_channel *c, char *dest, int timeout);
static int usbradio_write(struct ast_channel *chan, struct ast_frame *f);
static int usbradio_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);
static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+static int xpmr_config(struct chan_usbradio_pvt *o);
#if DEBUG_FILETEST == 1
static int RxTestIt(struct chan_usbradio_pvt *o);
@@ -494,36 +702,35 @@ Note: must add -lasound to end of linkage */
static int amixer_max(int devnum,char *param)
{
- int rv,type;
- char str[15];
- snd_hctl_t *hctl;
- snd_ctl_elem_id_t *id;
- snd_hctl_elem_t *elem;
- snd_ctl_elem_info_t *info;
-
- snprintf(str, sizeof(str), "hw:%d", devnum);
- if (snd_hctl_open(&hctl, str, 0))
- return -1;
+int rv,type;
+char str[100];
+snd_hctl_t *hctl;
+snd_ctl_elem_id_t *id;
+snd_hctl_elem_t *elem;
+snd_ctl_elem_info_t *info;
+
+ sprintf(str,"hw:%d",devnum);
+ if (snd_hctl_open(&hctl, str, 0)) return(-1);
snd_hctl_load(hctl);
- id = alloca(snd_ctl_elem_id_sizeof());
- memset(id, 0, snd_ctl_elem_id_sizeof());
+ snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
snd_ctl_elem_id_set_name(id, param);
elem = snd_hctl_find_elem(hctl, id);
- if (!elem) {
+ if (!elem)
+ {
snd_hctl_close(hctl);
- return -1;
+ return(-1);
}
- info = alloca(snd_ctl_elem_info_sizeof());
- memset(info, 0, snd_ctl_elem_info_sizeof());
+ snd_ctl_elem_info_alloca(&info);
snd_hctl_elem_info(elem,info);
type = snd_ctl_elem_info_get_type(info);
rv = 0;
- switch (type) {
- case SND_CTL_ELEM_TYPE_INTEGER:
+ switch(type)
+ {
+ case SND_CTL_ELEM_TYPE_INTEGER:
rv = snd_ctl_elem_info_get_max(info);
break;
- case SND_CTL_ELEM_TYPE_BOOLEAN:
+ case SND_CTL_ELEM_TYPE_BOOLEAN:
rv = 1;
break;
}
@@ -531,205 +738,515 @@ static int amixer_max(int devnum,char *param)
return(rv);
}
-/*! \brief Call with: devnum: alsa major device number, param: ascii Formal
+/* Call with: devnum: alsa major device number, param: ascii Formal
Parameter Name, val1, first or only value, val2 second value, or 0
if only 1 value. Values: 0-99 (percent) or 0-1 for baboon.
Note: must add -lasound to end of linkage */
-static int setamixer(int devnum, char *param, int v1, int v2)
+static int setamixer(int devnum,char *param, int v1, int v2)
{
- int type;
- char str[15];
- snd_hctl_t *hctl;
- snd_ctl_elem_id_t *id;
- snd_ctl_elem_value_t *control;
- snd_hctl_elem_t *elem;
- snd_ctl_elem_info_t *info;
-
- snprintf(str, sizeof(str), "hw:%d", devnum);
- if (snd_hctl_open(&hctl, str, 0))
- return -1;
+int type;
+char str[100];
+snd_hctl_t *hctl;
+snd_ctl_elem_id_t *id;
+snd_ctl_elem_value_t *control;
+snd_hctl_elem_t *elem;
+snd_ctl_elem_info_t *info;
+
+ sprintf(str,"hw:%d",devnum);
+ if (snd_hctl_open(&hctl, str, 0)) return(-1);
snd_hctl_load(hctl);
- id = alloca(snd_ctl_elem_id_sizeof());
- memset(id, 0, snd_ctl_elem_id_sizeof());
+ snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
snd_ctl_elem_id_set_name(id, param);
elem = snd_hctl_find_elem(hctl, id);
- if (!elem) {
+ if (!elem)
+ {
snd_hctl_close(hctl);
- return -1;
+ return(-1);
}
- info = alloca(snd_ctl_elem_info_sizeof());
- memset(info, 0, snd_ctl_elem_info_sizeof());
+ snd_ctl_elem_info_alloca(&info);
snd_hctl_elem_info(elem,info);
type = snd_ctl_elem_info_get_type(info);
- control = alloca(snd_ctl_elem_value_sizeof());
- memset(control, 0, snd_ctl_elem_value_sizeof());
+ snd_ctl_elem_value_alloca(&control);
snd_ctl_elem_value_set_id(control, id);
- switch (type) {
- case SND_CTL_ELEM_TYPE_INTEGER:
+ switch(type)
+ {
+ case SND_CTL_ELEM_TYPE_INTEGER:
snd_ctl_elem_value_set_integer(control, 0, v1);
if (v2 > 0) snd_ctl_elem_value_set_integer(control, 1, v2);
break;
- case SND_CTL_ELEM_TYPE_BOOLEAN:
+ case SND_CTL_ELEM_TYPE_BOOLEAN:
snd_ctl_elem_value_set_integer(control, 0, (v1 != 0));
break;
}
- if (snd_hctl_elem_write(elem, control)) {
+ if (snd_hctl_elem_write(elem, control))
+ {
snd_hctl_close(hctl);
return(-1);
}
snd_hctl_close(hctl);
- return 0;
+ return(0);
}
static void hid_set_outputs(struct usb_dev_handle *handle,
unsigned char *outputs)
{
+ usleep(1500);
usb_control_msg(handle,
- USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
- HID_REPORT_SET,
- 0 + (HID_RT_OUTPUT << 8),
- C108_HID_INTERFACE,
- (char *)outputs, 4, 5000);
+ USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
+ HID_REPORT_SET,
+ 0 + (HID_RT_OUTPUT << 8),
+ C108_HID_INTERFACE,
+ (char*)outputs, 4, 5000);
}
static void hid_get_inputs(struct usb_dev_handle *handle,
unsigned char *inputs)
{
+ usleep(1500);
usb_control_msg(handle,
- USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
- HID_REPORT_GET,
- 0 + (HID_RT_INPUT << 8),
- C108_HID_INTERFACE,
- (char *)inputs, 4, 5000);
+ USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
+ HID_REPORT_GET,
+ 0 + (HID_RT_INPUT << 8),
+ C108_HID_INTERFACE,
+ (char*)inputs, 4, 5000);
}
-static struct usb_device *hid_device_init(void)
+static unsigned short read_eeprom(struct usb_dev_handle *handle, int addr)
{
- struct usb_bus *usb_bus;
- struct usb_device *dev;
+ unsigned char buf[4];
- usb_init();
- usb_find_busses();
- usb_find_devices();
- for (usb_bus = usb_busses; usb_bus; usb_bus = usb_bus->next) {
- for (dev = usb_bus->devices; dev; dev = dev->next) {
- if ((dev->descriptor.idVendor == C108_VENDOR_ID) && (dev->descriptor.idProduct == C108_PRODUCT_ID))
- return dev;
- }
+ buf[0] = 0x80;
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0x80 | (addr & 0x3f);
+ hid_set_outputs(handle,buf);
+ memset(buf,0,sizeof(buf));
+ hid_get_inputs(handle,buf);
+ return(buf[1] + (buf[2] << 8));
+}
+
+static void write_eeprom(struct usb_dev_handle *handle, int addr,
+ unsigned short data)
+{
+
+ unsigned char buf[4];
+
+ buf[0] = 0x80;
+ buf[1] = data & 0xff;
+ buf[2] = data >> 8;
+ buf[3] = 0xc0 | (addr & 0x3f);
+ hid_set_outputs(handle,buf);
+}
+
+static unsigned short get_eeprom(struct usb_dev_handle *handle,
+ unsigned short *buf)
+{
+int i;
+unsigned short cs;
+
+ cs = 0xffff;
+ for(i = EEPROM_START_ADDR; i < EEPROM_END_ADDR; i++)
+ {
+ cs += buf[i] = read_eeprom(handle,i);
}
- return NULL;
+ return(cs);
}
-static int hidhdwconfig(struct chan_usbradio_pvt *o)
-{
- if (o->hdwtype == 1) { /*sphusb */
- o->hid_gpio_ctl = 0x08; /* set GPIO4 to output mode */
- o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
- o->hid_io_cor = 4; /* GPIO3 is COR */
- o->hid_io_cor_loc = 1; /* GPIO3 is COR */
- o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
- o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
- o->hid_io_ptt = 8; /* GPIO 4 is PTT */
- o->hid_gpio_loc = 1; /* For ALL GPIO */
- } else if (o->hdwtype == 0) { /* dudeusb */
- o->hid_gpio_ctl = 0x0c;/* set GPIO 3 & 4 to output mode */
- o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
- o->hid_io_cor = 2; /* VOLD DN is COR */
- o->hid_io_cor_loc = 0; /* VOL DN COR */
- o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
- o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
- o->hid_io_ptt = 4; /* GPIO 3 is PTT */
- o->hid_gpio_loc = 1; /* For ALL GPIO */
- } else if (o->hdwtype == 3) { /* custom version */
- o->hid_gpio_ctl = 0x0c; /* set GPIO 3 & 4 to output mode */
- o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
- o->hid_io_cor = 2; /* VOLD DN is COR */
- o->hid_io_cor_loc = 0; /* VOL DN COR */
- o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
- o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
- o->hid_io_ptt = 4; /* GPIO 3 is PTT */
- o->hid_gpio_loc = 1; /* For ALL GPIO */
+static void put_eeprom(struct usb_dev_handle *handle,unsigned short *buf)
+{
+int i;
+unsigned short cs;
+
+ cs = 0xffff;
+ buf[EEPROM_MAGIC_ADDR] = EEPROM_MAGIC;
+ for(i = EEPROM_START_ADDR; i < EEPROM_CS_ADDR; i++)
+ {
+ write_eeprom(handle,i,buf[i]);
+ cs += buf[i];
+ }
+ buf[EEPROM_CS_ADDR] = (65535 - cs) + 1;
+ write_eeprom(handle,i,buf[EEPROM_CS_ADDR]);
+}
+
+static struct usb_device *hid_device_init(char *desired_device)
+{
+ struct usb_bus *usb_bus;
+ struct usb_device *dev;
+ char devstr[200],str[200],desdev[200],*cp;
+ int i;
+ FILE *fp;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+ for (usb_bus = usb_busses;
+ usb_bus;
+ usb_bus = usb_bus->next) {
+ for (dev = usb_bus->devices;
+ dev;
+ dev = dev->next) {
+ if ((dev->descriptor.idVendor
+ == C108_VENDOR_ID) &&
+ (dev->descriptor.idProduct
+ == C108_PRODUCT_ID))
+ {
+ sprintf(devstr,"%s/%s", usb_bus->dirname,dev->filename);
+ for(i = 0; i < 32; i++)
+ {
+ sprintf(str,"/proc/asound/card%d/usbbus",i);
+ fp = fopen(str,"r");
+ if (!fp) continue;
+ if ((!fgets(desdev,sizeof(desdev) - 1,fp)) || (!desdev[0]))
+ {
+ fclose(fp);
+ continue;
+ }
+ fclose(fp);
+ if (desdev[strlen(desdev) - 1] == '\n')
+ desdev[strlen(desdev) -1 ] = 0;
+ if (strcasecmp(desdev,devstr)) continue;
+ if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
+ else strcpy(str,"/sys/class/sound/dsp/device");
+ memset(desdev,0,sizeof(desdev));
+ if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
+ {
+ sprintf(str,"/sys/class/sound/controlC%d/device",i);
+ memset(desdev,0,sizeof(desdev));
+ if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
+ }
+ cp = strrchr(desdev,'/');
+ if (cp) *cp = 0; else continue;
+ cp = strrchr(desdev,'/');
+ if (!cp) continue;
+ cp++;
+ break;
+ }
+ if (i >= 32) continue;
+ if (!strcmp(cp,desired_device)) return dev;
+ }
+
+ }
+ }
+ return NULL;
+}
+
+static int hid_device_mklist(void)
+{
+ struct usb_bus *usb_bus;
+ struct usb_device *dev;
+ char devstr[200],str[200],desdev[200],*cp;
+ int i;
+ FILE *fp;
+
+ usb_device_list = ast_malloc(2);
+ if (!usb_device_list) return -1;
+ memset(usb_device_list,0,2);
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+ for (usb_bus = usb_busses;
+ usb_bus;
+ usb_bus = usb_bus->next) {
+ for (dev = usb_bus->devices;
+ dev;
+ dev = dev->next) {
+ if ((dev->descriptor.idVendor
+ == C108_VENDOR_ID) &&
+ (dev->descriptor.idProduct
+ == C108_PRODUCT_ID))
+ {
+ sprintf(devstr,"%s/%s", usb_bus->dirname,dev->filename);
+ for(i = 0;i < 32; i++)
+ {
+ sprintf(str,"/proc/asound/card%d/usbbus",i);
+ fp = fopen(str,"r");
+ if (!fp) continue;
+ if ((!fgets(desdev,sizeof(desdev) - 1,fp)) || (!desdev[0]))
+ {
+ fclose(fp);
+ continue;
+ }
+ fclose(fp);
+ if (desdev[strlen(desdev) - 1] == '\n')
+ desdev[strlen(desdev) -1 ] = 0;
+ if (strcasecmp(desdev,devstr)) continue;
+ if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
+ else strcpy(str,"/sys/class/sound/dsp/device");
+ memset(desdev,0,sizeof(desdev));
+ if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
+ {
+ sprintf(str,"/sys/class/sound/controlC%d/device",i);
+ memset(desdev,0,sizeof(desdev));
+ if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
+ }
+ cp = strrchr(desdev,'/');
+ if (cp) *cp = 0; else continue;
+ cp = strrchr(desdev,'/');
+ if (!cp) continue;
+ cp++;
+ break;
+ }
+ if (i >= 32) return -1;
+ usb_device_list = ast_realloc(usb_device_list,
+ usb_device_list_size + 2 +
+ strlen(cp));
+ if (!usb_device_list) return -1;
+ usb_device_list_size += strlen(cp) + 2;
+ i = 0;
+ while(usb_device_list[i])
+ {
+ i += strlen(usb_device_list + i) + 1;
+ }
+ strcat(usb_device_list + i,cp);
+ usb_device_list[strlen(cp) + i + 1] = 0;
+ }
+
+ }
+ }
+ return 0;
+}
+
+/* returns internal formatted string from external one */
+static int usb_get_usbdev(char *devstr)
+{
+int i;
+char str[200],desdev[200],*cp;
+
+ for(i = 0;i < 32; i++)
+ {
+ if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
+ else strcpy(str,"/sys/class/sound/dsp/device");
+ memset(desdev,0,sizeof(desdev));
+ if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
+ {
+ sprintf(str,"/sys/class/sound/controlC%d/device",i);
+ memset(desdev,0,sizeof(desdev));
+ if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
+ }
+ cp = strrchr(desdev,'/');
+ if (cp) *cp = 0; else continue;
+ cp = strrchr(desdev,'/');
+ if (!cp) continue;
+ cp++;
+ if (!strcasecmp(cp,devstr)) break;
}
+ if (i >= 32) return -1;
+ return i;
- return 0;
}
+static int usb_list_check(char *devstr)
+{
+
+char *s = usb_device_list;
+ if (!s) return(0);
+ while(*s)
+ {
+ if (!strcasecmp(s,devstr)) return(1);
+ s += strlen(s) + 1;
+ }
+ return(0);
+}
+
+
+static int hidhdwconfig(struct chan_usbradio_pvt *o)
+{
+ if(o->hdwtype==1) //sphusb
+ {
+ o->hid_gpio_ctl = 0x08; /* set GPIO4 to output mode */
+ o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
+ o->hid_io_cor = 4; /* GPIO3 is COR */
+ o->hid_io_cor_loc = 1; /* GPIO3 is COR */
+ o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
+ o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
+ o->hid_io_ptt = 8; /* GPIO 4 is PTT */
+ o->hid_gpio_loc = 1; /* For ALL GPIO */
+ }
+ else if(o->hdwtype==0) //dudeusb
+ {
+ o->hid_gpio_ctl = 0x0c; /* set GPIO 3 & 4 to output mode */
+ o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
+ o->hid_io_cor = 2; /* VOLD DN is COR */
+ o->hid_io_cor_loc = 0; /* VOL DN COR */
+ o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
+ o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
+ o->hid_io_ptt = 4; /* GPIO 3 is PTT */
+ o->hid_gpio_loc = 1; /* For ALL GPIO */
+ }
+ else if(o->hdwtype==3) // custom version
+ {
+ o->hid_gpio_ctl = 0x0c; /* set GPIO 3 & 4 to output mode */
+ o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
+ o->hid_io_cor = 2; /* VOLD DN is COR */
+ o->hid_io_cor_loc = 0; /* VOL DN COR */
+ o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
+ o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
+ o->hid_io_ptt = 4; /* GPIO 3 is PTT */
+ o->hid_gpio_loc = 1; /* For ALL GPIO */
+ }
+
+ return 0;
+}
+/*
+*/
+static void kickptt(struct chan_usbradio_pvt *o)
+{
+ char c = 0;
+ //printf("kickptt %i %i %i\n",o->txkeyed,o->txchankey,o->txtestkey);
+ if (!o) return;
+ if (!o->pttkick) return;
+ write(o->pttkick[1],&c,1);
+}
+/*
+*/
static void *hidthread(void *arg)
{
- unsigned char buf[4], keyed;
+ unsigned char buf[4],bufsave[4],keyed;
char lastrx, txtmp;
+ int res;
struct usb_device *usb_dev;
struct usb_dev_handle *usb_handle;
- struct chan_usbradio_pvt *o = arg;
+ struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
+ struct timeval to;
+ fd_set rfds;
- usb_dev = hid_device_init();
+ usb_dev = hid_device_init(o->devstr);
if (usb_dev == NULL) {
- ast_log(LOG_ERROR, "USB HID device not found\n");
+ ast_log(LOG_ERROR,"USB HID device not found\n");
pthread_exit(NULL);
}
usb_handle = usb_open(usb_dev);
if (usb_handle == NULL) {
- ast_log(LOG_ERROR, "Not able to open USB device\n");
+ ast_log(LOG_ERROR,"Not able to open USB device\n");
pthread_exit(NULL);
}
- if (usb_claim_interface(usb_handle, C108_HID_INTERFACE) < 0) {
- if (usb_detach_kernel_driver_np(usb_handle, C108_HID_INTERFACE) < 0) {
- ast_log(LOG_ERROR, "Not able to detach the USB device\n");
+ if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0)
+ {
+ if (usb_detach_kernel_driver_np(usb_handle,C108_HID_INTERFACE) < 0) {
+ ast_log(LOG_ERROR,"Not able to detach the USB device\n");
pthread_exit(NULL);
}
- if (usb_claim_interface(usb_handle, C108_HID_INTERFACE) < 0) {
- ast_log(LOG_ERROR, "Not able to claim the USB device\n");
+ if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0) {
+ ast_log(LOG_ERROR,"Not able to claim the USB device\n");
pthread_exit(NULL);
}
}
- memset(buf, 0, sizeof(buf));
+ memset(buf,0,sizeof(buf));
buf[2] = o->hid_gpio_ctl;
buf[1] = 0;
- hid_set_outputs(usb_handle, buf);
- traceusb1("hidthread: Starting normally!!\n");
+ hid_set_outputs(usb_handle,buf);
+ memcpy(bufsave,buf,sizeof(buf));
+ if (pipe(o->pttkick) == -1)
+ {
+ ast_log(LOG_ERROR,"Not able to create pipe\n");
+ pthread_exit(NULL);
+ }
+ traceusb1(("hidthread: Starting normally on %s!!\n",o->name));
lastrx = 0;
- while (!o->stophid) {
+ // popen
+ while(!o->stophid)
+ {
+ to.tv_sec = 0;
+ to.tv_usec = 50000; // maw sph
+
+ FD_ZERO(&rfds);
+ FD_SET(o->pttkick[0],&rfds);
+ /* ast_select emulates linux behaviour in terms of timeout handling */
+ res = ast_select(o->pttkick[0] + 1, &rfds, NULL, NULL, &to);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
+ usleep(10000);
+ continue;
+ }
+ if (FD_ISSET(o->pttkick[0],&rfds))
+ {
+ char c;
+
+ read(o->pttkick[0],&c,1);
+ }
+ if(o->wanteeprom)
+ {
+ ast_mutex_lock(&o->eepromlock);
+ if (o->eepromctl == 1) /* to read */
+ {
+ /* if CS okay */
+ if (!get_eeprom(usb_handle,o->eeprom))
+ {
+ if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC)
+ {
+ ast_log(LOG_NOTICE,"UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n",o->name);
+ }
+ else
+ {
+ o->rxmixerset = o->eeprom[EEPROM_RXMIXERSET];
+ o->txmixaset = o->eeprom[EEPROM_TXMIXASET];
+ o->txmixbset = o->eeprom[EEPROM_TXMIXBSET];
+ memcpy(&o->rxvoiceadj,&o->eeprom[EEPROM_RXVOICEADJ],sizeof(float));
+ memcpy(&o->rxctcssadj,&o->eeprom[EEPROM_RXCTCSSADJ],sizeof(float));
+ o->txctcssadj = o->eeprom[EEPROM_TXCTCSSADJ];
+ o->rxsquelchadj = o->eeprom[EEPROM_RXSQUELCHADJ];
+ ast_log(LOG_NOTICE,"EEPROM Loaded on channel %s\n",o->name);
+ }
+ }
+ else
+ {
+ ast_log(LOG_NOTICE,"USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n",o->name);
+ }
+ hid_set_outputs(usb_handle,bufsave);
+ }
+ if (o->eepromctl == 2) /* to write */
+ {
+ put_eeprom(usb_handle,o->eeprom);
+ hid_set_outputs(usb_handle,bufsave);
+ ast_log(LOG_NOTICE,"USB Parameters written to EEPROM on %s\n",o->name);
+ }
+ o->eepromctl = 0;
+ ast_mutex_unlock(&o->eepromlock);
+ }
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
- hid_get_inputs(usb_handle, buf);
+ hid_get_inputs(usb_handle,buf);
keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor);
- if (keyed != o->rxhidsq) {
- if (o->debuglevel)
- ast_log(LOG_NOTICE, "chan_usbradio() hidthread: update rxhidsq = %d\n", keyed);
- o->rxhidsq = keyed;
+ if (keyed != o->rxhidsq)
+ {
+ if(o->debuglevel)printf("chan_usbradio() hidthread: update rxhidsq = %d\n",keyed);
+ o->rxhidsq=keyed;
}
- /* if change in tx stuff */
- txtmp = 0;
- if (o->txkeyed || o->txchankey || o->txtestkey || o->pmrChan->txPttOut)
- txtmp = 1;
-
- if (o->lasttx != txtmp) {
- o->lasttx = txtmp;
- if (o->debuglevel)
- ast_log(LOG_NOTICE, "hidthread: tx set to %d\n", txtmp);
+ /* if change in tx state as controlled by xpmr */
+ txtmp=o->pmrChan->txPttOut;
+
+ if (o->lasttx != txtmp)
+ {
+ o->pmrChan->txPttHid=o->lasttx = txtmp;
+ if(o->debuglevel)printf("hidthread: tx set to %d\n",txtmp);
buf[o->hid_gpio_loc] = 0;
- if (txtmp)
- buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ if (!o->invertptt)
+ {
+ if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ }
+ else
+ {
+ if (!txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ }
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
- hid_set_outputs(usb_handle, buf);
+ memcpy(bufsave,buf,sizeof(buf));
+ hid_set_outputs(usb_handle,buf);
}
-
time(&o->lasthidtime);
- usleep(50000);
}
buf[o->hid_gpio_loc] = 0;
- if (o->invertptt)
- buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ if (o->invertptt) buf[o->hid_gpio_loc] = o->hid_io_ptt;
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
- hid_set_outputs(usb_handle, buf);
+ hid_set_outputs(usb_handle,buf);
pthread_exit(0);
}
-/*! \brief
+/*
* returns a pointer to the descriptor with the given name
*/
static struct chan_usbradio_pvt *find_desc(char *dev)
@@ -740,14 +1257,28 @@ static struct chan_usbradio_pvt *find_desc(char *dev)
ast_log(LOG_WARNING, "null dev\n");
for (o = usbradio_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next);
-
if (!o)
+ {
ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--");
+ pthread_exit(0);
+ }
+
+ return o;
+}
+
+static struct chan_usbradio_pvt *find_desc_usb(char *devstr)
+{
+ struct chan_usbradio_pvt *o = NULL;
+
+ if (!devstr)
+ ast_log(LOG_WARNING, "null dev\n");
+
+ for (o = usbradio_default.next; o && devstr && strcmp(o->devstr, devstr) != 0; o = o->next);
return o;
}
-/*! \brief
+/*
* split a string in extension-context, returns pointers to malloc'ed
* strings.
* If we do not have 'overridecontext' then the last @ is considered as
@@ -783,7 +1314,7 @@ static char *ast_ext_ctx(const char *src, char **ext, char **ctx)
}
#endif
-/*! \brief
+/*
* Returns the number of blocks used in the audio output channel
*/
static int used_blocks(struct chan_usbradio_pvt *o)
@@ -799,14 +1330,15 @@ static int used_blocks(struct chan_usbradio_pvt *o)
}
if (o->total_blocks == 0) {
- ast_debug(4, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments);
+ if (0) /* debugging */
+ ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments);
o->total_blocks = info.fragments;
}
return o->total_blocks - info.fragments;
}
-/*! \brief Write an exactly FRAME_SIZE sized frame */
+/* Write an exactly FRAME_SIZE sized frame */
static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data)
{
int res;
@@ -815,6 +1347,13 @@ static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data)
setformat(o, O_RDWR);
if (o->sounddev < 0)
return 0; /* not fatal */
+ // maw maw sph !!! may or may not be a good thing
+ // drop the frame if not transmitting, this keeps from gradually
+ // filling the buffer when asterisk clock > usb sound clock
+ if(!o->pmrChan->txPttIn && !o->pmrChan->txPttOut)
+ {
+ //return 0;
+ }
/*
* Nothing complex to manage the audio device queue.
* If the buffer is full just drop the extra, otherwise write.
@@ -823,6 +1362,7 @@ static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data)
*/
res = used_blocks(o);
if (res > o->queuesize) { /* no room to write a block */
+ // ast_log(LOG_WARNING, "sound device write buffer overflow\n");
if (o->w_errors++ == 0 && (usbradio_debug & 0x4))
ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors);
return 0;
@@ -832,6 +1372,136 @@ static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data)
return write(o->sounddev, ((void *) data), FRAME_SIZE * 2 * 12);
}
+#ifndef NEW_ASTERISK
+
+/*
+ * Handler for 'sound writable' events from the sound thread.
+ * Builds a frame from the high level description of the sounds,
+ * and passes it to the audio device.
+ * The actual sound is made of 1 or more sequences of sound samples
+ * (s->datalen, repeated to make s->samplen samples) followed by
+ * s->silencelen samples of silence. The position in the sequence is stored
+ * in o->sampsent, which goes between 0 .. s->samplen+s->silencelen.
+ * In case we fail to write a frame, don't update o->sampsent.
+ */
+static void send_sound(struct chan_usbradio_pvt *o)
+{
+ short myframe[FRAME_SIZE];
+ int ofs, l, start;
+ int l_sampsent = o->sampsent;
+ struct sound *s;
+
+ if (o->cursound < 0) /* no sound to send */
+ return;
+
+ s = &sounds[o->cursound];
+
+ for (ofs = 0; ofs < FRAME_SIZE; ofs += l) {
+ l = s->samplen - l_sampsent; /* # of available samples */
+ if (l > 0) {
+ start = l_sampsent % s->datalen; /* source offset */
+ if (l > FRAME_SIZE - ofs) /* don't overflow the frame */
+ l = FRAME_SIZE - ofs;
+ if (l > s->datalen - start) /* don't overflow the source */
+ l = s->datalen - start;
+ bcopy(s->data + start, myframe + ofs, l * 2);
+ if (0)
+ ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n", l_sampsent, l, s->samplen, ofs);
+ l_sampsent += l;
+ } else { /* end of samples, maybe some silence */
+ static const short silence[FRAME_SIZE] = { 0, };
+
+ l += s->silencelen;
+ if (l > 0) {
+ if (l > FRAME_SIZE - ofs)
+ l = FRAME_SIZE - ofs;
+ bcopy(silence, myframe + ofs, l * 2);
+ l_sampsent += l;
+ } else { /* silence is over, restart sound if loop */
+ if (s->repeat == 0) { /* last block */
+ o->cursound = -1;
+ o->nosound = 0; /* allow audio data */
+ if (ofs < FRAME_SIZE) /* pad with silence */
+ bcopy(silence, myframe + ofs, (FRAME_SIZE - ofs) * 2);
+ }
+ l_sampsent = 0;
+ }
+ }
+ }
+ l = soundcard_writeframe(o, myframe);
+ if (l > 0)
+ o->sampsent = l_sampsent; /* update status */
+}
+
+static void *sound_thread(void *arg)
+{
+ char ign[4096];
+ struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
+
+ /*
+ * Just in case, kick the driver by trying to read from it.
+ * Ignore errors - this read is almost guaranteed to fail.
+ */
+ read(o->sounddev, ign, sizeof(ign));
+ for (;;) {
+ fd_set rfds, wfds;
+ int maxfd, res;
+
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_SET(o->sndcmd[0], &rfds);
+ maxfd = o->sndcmd[0]; /* pipe from the main process */
+ if (o->cursound > -1 && o->sounddev < 0)
+ setformat(o, O_RDWR); /* need the channel, try to reopen */
+ else if (o->cursound == -1 && o->owner == NULL)
+ {
+ setformat(o, O_CLOSE); /* can close */
+ }
+ if (o->sounddev > -1) {
+ if (!o->owner) { /* no one owns the audio, so we must drain it */
+ FD_SET(o->sounddev, &rfds);
+ maxfd = MAX(o->sounddev, maxfd);
+ }
+ if (o->cursound > -1) {
+ FD_SET(o->sounddev, &wfds);
+ maxfd = MAX(o->sounddev, maxfd);
+ }
+ }
+ /* ast_select emulates linux behaviour in terms of timeout handling */
+ res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL);
+ if (res < 1) {
+ ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
+ sleep(1);
+ continue;
+ }
+ if (FD_ISSET(o->sndcmd[0], &rfds)) {
+ /* read which sound to play from the pipe */
+ int i, what = -1;
+
+ read(o->sndcmd[0], &what, sizeof(what));
+ for (i = 0; sounds[i].ind != -1; i++) {
+ if (sounds[i].ind == what) {
+ o->cursound = i;
+ o->sampsent = 0;
+ o->nosound = 1; /* block audio from pbx */
+ break;
+ }
+ }
+ if (sounds[i].ind == -1)
+ ast_log(LOG_WARNING, "invalid sound index: %d\n", what);
+ }
+ if (o->sounddev > -1) {
+ if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */
+ read(o->sounddev, ign, sizeof(ign));
+ if (FD_ISSET(o->sounddev, &wfds))
+ send_sound(o);
+ }
+ }
+ return NULL; /* Never reached */
+}
+
+#endif
+
/*
* reset and close the device if opened,
* then open and initialize it in the desired mode,
@@ -840,7 +1510,7 @@ static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data)
static int setformat(struct chan_usbradio_pvt *o, int mode)
{
int fmt, desired, res, fd;
- char device[20];
+ char device[100];
if (o->sounddev >= 0) {
ioctl(o->sounddev, SNDCTL_DSP_RESET, 0);
@@ -850,12 +1520,10 @@ static int setformat(struct chan_usbradio_pvt *o, int mode)
}
if (mode == O_CLOSE) /* we are done */
return 0;
- if (ast_tvdiff_ms(ast_tvnow(), o->lastopen) < 1000)
- return -1; /* don't open too often */
o->lastopen = ast_tvnow();
- strcpy(device, "/dev/dsp");
+ strcpy(device,"/dev/dsp");
if (o->devicenum)
- snprintf(device + strlen("/dev/dsp"), sizeof(device) - strlen("/dev/dsp"), "%d", o->devicenum);
+ sprintf(device,"/dev/dsp%d",o->devicenum);
fd = o->sounddev = open(device, mode | O_NONBLOCK);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to re-open DSP device %d: %s\n", o->devicenum, strerror(errno));
@@ -880,7 +1548,8 @@ static int setformat(struct chan_usbradio_pvt *o, int mode)
/* Check to see if duplex set (FreeBSD Bug) */
res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
if (res == 0 && (fmt & DSP_CAP_DUPLEX)) {
- ast_verb(2, "Console is full duplex\n");
+ if (option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n");
o->duplex = M_FULL;
};
break;
@@ -946,18 +1615,74 @@ static int usbradio_digit_begin(struct ast_channel *c, char digit)
static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration)
{
/* no better use for received digits than print them */
- ast_verb(0, " << Console Received digit %c of duration %u ms >> \n",
+ ast_verbose(" << Console Received digit %c of duration %u ms >> \n",
digit, duration);
return 0;
}
-
+/*
+ SETFREQ - sets spi programmable xcvr
+ SETCHAN - sets binary parallel xcvr
+*/
static int usbradio_text(struct ast_channel *c, const char *text)
{
+ struct chan_usbradio_pvt *o = find_desc(usbradio_active);
+ double tx,rx;
+ char cnt,rxs[16],txs[16],txpl[16],rxpl[16];
+ char pwr,*cmd;
+
+ cmd = alloca(strlen(text) + 10);
+
/* print received messages */
- ast_verb(0, " << Console Received text %s >> \n", text);
+ if(o->debuglevel)ast_verbose(" << Console Received usbradio text %s >> \n", text);
+
+ cnt=sscanf(text,"%s %s %s %s %s %c",cmd,rxs,txs,rxpl,txpl,&pwr);
+
+ if (strcmp(cmd,"SETCHAN")==0)
+ {
+ u8 chan;
+ chan=strtod(rxs,NULL);
+ ppbinout(chan);
+ if(o->debuglevel)ast_log(LOG_NOTICE,"parse usbradio SETCHAN cmd: %s chan: %i\n",text,chan);
+ return 0;
+ }
+
+ if (cnt < 6)
+ {
+ ast_log(LOG_ERROR,"Cannot parse usbradio text: %s\n",text);
+ return 0;
+ }
+ else
+ {
+ if(o->debuglevel)ast_verbose(" << %s %s %s %s %s %c >> \n", cmd,rxs,txs,rxpl,txpl,pwr);
+ }
+
+ if (strcmp(cmd,"SETFREQ")==0)
+ {
+ if(o->debuglevel)ast_log(LOG_NOTICE,"parse usbradio SETFREQ cmd: %s\n",text);
+ tx=strtod(txs,NULL);
+ rx=strtod(rxs,NULL);
+ o->set_txfreq = round(tx * (double)1000000);
+ o->set_rxfreq = round(rx * (double)1000000);
+ o->pmrChan->txpower = (pwr == 'H');
+ strcpy(o->set_rxctcssfreqs,rxpl);
+ strcpy(o->set_txctcssfreqs,txpl);
+
+ o->b.remoted=1;
+ xpmr_config(o);
+ return 0;
+ }
+ ast_log(LOG_ERROR,"Cannot parse usbradio cmd: %s\n",text);
return 0;
}
+/* Play ringtone 'x' on device 'o' */
+static void ring(struct chan_usbradio_pvt *o, int x)
+{
+#ifndef NEW_ASTERISK
+ write(o->sndcmd[1], &x, sizeof(x));
+#endif
+}
+
/*
* handler for incoming calls. Either autoanswer, or start ringing
*/
@@ -965,6 +1690,7 @@ static int usbradio_call(struct ast_channel *c, char *dest, int timeout)
{
struct chan_usbradio_pvt *o = c->tech_pvt;
+ o->stophid = 0;
time(&o->lasthidtime);
ast_pthread_create_background(&o->hidthread, NULL, hidthread, o);
ast_setstate(c, AST_STATE_UP);
@@ -976,8 +1702,15 @@ static int usbradio_call(struct ast_channel *c, char *dest, int timeout)
*/
static int usbradio_answer(struct ast_channel *c)
{
- ast_setstate(c, AST_STATE_UP);
+#ifndef NEW_ASTERISK
+ struct chan_usbradio_pvt *o = c->tech_pvt;
+#endif
+ ast_setstate(c, AST_STATE_UP);
+#ifndef NEW_ASTERISK
+ o->cursound = -1;
+ o->nosound = 0;
+#endif
return 0;
}
@@ -985,6 +1718,11 @@ static int usbradio_hangup(struct ast_channel *c)
{
struct chan_usbradio_pvt *o = c->tech_pvt;
+ //ast_log(LOG_NOTICE, "usbradio_hangup()\n");
+#ifndef NEW_ASTERISK
+ o->cursound = -1;
+ o->nosound = 0;
+#endif
c->tech_pvt = NULL;
o->owner = NULL;
ast_module_unref(ast_module_info->self);
@@ -993,10 +1731,13 @@ static int usbradio_hangup(struct ast_channel *c)
/* Assume auto-hangup too */
o->hookstate = 0;
setformat(o, O_CLOSE);
+ } else {
+ /* Make congestion noise */
+ ring(o, AST_CONTROL_CONGESTION);
}
}
o->stophid = 1;
- pthread_join(o->hidthread, NULL);
+ pthread_join(o->hidthread,NULL);
return 0;
}
@@ -1004,11 +1745,17 @@ static int usbradio_hangup(struct ast_channel *c)
/* used for data coming from the network */
static int usbradio_write(struct ast_channel *c, struct ast_frame *f)
{
- int src,datalen;
struct chan_usbradio_pvt *o = c->tech_pvt;
- traceusb2("usbradio_write() o->nosound=%d\n", o->nosound); /*sph maw asdf */
+ traceusb2(("usbradio_write() o->nosound= %i\n",o->nosound));
+#ifndef NEW_ASTERISK
+ /* Immediately return if no sound is enabled */
+ if (o->nosound)
+ return 0;
+ /* Stop any currently playing sound */
+ o->cursound = -1;
+#endif
/*
* we could receive a block which is not a multiple of our
* FRAME_SIZE, so buffer it locally and write to the device
@@ -1016,93 +1763,70 @@ static int usbradio_write(struct ast_channel *c, struct ast_frame *f)
* Keep the residue stored for future use.
*/
- if (o->txkeyed || o->txtestkey)
- o->pmrChan->txPttIn = 1;
- else
- o->pmrChan->txPttIn = 0;
-
- #if DEBUG_CAPTURES == 1 /* to write input data to a file datalen=320 */
- if (ftxcapraw && o->b.txcapraw) {
+ #if DEBUG_CAPTURES == 1 // to write input data to a file datalen=320
+ if (ftxcapraw && o->b.txcapraw)
+ {
i16 i, tbuff[f->datalen];
- for (i = 0; i < f->datalen; i += 2) {
- tbuff[i] = ((i16 *)(f->data))[i / 2];
- tbuff[i + 1] = o->txkeyed * M_Q13;
+ for(i=0;i<f->datalen;i+=2)
+ {
+ tbuff[i]= ((i16*)(f->data))[i/2];
+ tbuff[i+1]= o->txkeyed*M_Q13;
}
- fwrite(tbuff, 2, f->datalen, ftxcapraw);
- /*fwrite(f->data,1,f->datalen,ftxcapraw); */
+ fwrite(tbuff,2,f->datalen,ftxcapraw);
+ //fwrite(f->data,1,f->datalen,ftxcapraw);
}
#endif
- PmrTx(o->pmrChan,(i16*)f->data,(i16*)o->usbradio_write_buf_1);
-
- #if 0 /* to write 48KS/s stereo data to a file */
- if (!ftxoutraw) ftxoutraw = fopen(TX_CAP_OUT_FILE,"w");
- if (ftxoutraw) fwrite(o->usbradio_write_buf_1,1,f->datalen * 2 * 6,ftxoutraw);
- #endif
-
- #if DEBUG_CAPTURES == 1
- if (o->b.txcap2 && ftxcaptrace)
- fwrite((o->pmrChan->ptxDebug), 1, FRAME_SIZE * 2 * 16, ftxcaptrace);
- #endif
-
- src = 0; /* read position into f->data */
- datalen = f->datalen * 12;
- while (src < datalen) {
- /* Compute spare room in the buffer */
- int l = sizeof(o->usbradio_write_buf) - o->usbradio_write_dst;
+ // maw just take the data from the network and save it for PmrRx processing
- if (datalen - src >= l) { /* enough to fill a frame */
- memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
- soundcard_writeframe(o, (short *) o->usbradio_write_buf);
- src += l;
- o->usbradio_write_dst = 0;
- } else { /* copy residue */
- l = datalen - src;
- memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
- src += l; /* but really, we are done */
- o->usbradio_write_dst += l;
- }
- }
+ PmrTx(o->pmrChan,(i16*)f->data);
+
return 0;
}
static struct ast_frame *usbradio_read(struct ast_channel *c)
{
- int res;
+ int res, src, datalen, oldpttout;
+ int cd,sd;
struct chan_usbradio_pvt *o = c->tech_pvt;
- struct ast_frame *f = &o->read_f, *f1;
+ struct ast_frame *f = &o->read_f,*f1;
struct ast_frame wf = { AST_FRAME_CONTROL };
time_t now;
- traceusb2("usbradio_read()\n"); /* sph maw asdf */
+ traceusb2(("usbradio_read()\n"));
- if (o->lasthidtime) {
+ if (o->lasthidtime)
+ {
time(&now);
- if ((now - o->lasthidtime) > 3) {
- ast_log(LOG_ERROR, "HID process has died or something!!\n");
+ if ((now - o->lasthidtime) > 3)
+ {
+ ast_log(LOG_ERROR,"HID process has died or something!!\n");
return NULL;
}
}
- if (o->lastrx && (!o->rxkeyed)) {
- o->lastrx = 0;
- wf.subclass = AST_CONTROL_RADIO_UNKEY;
- ast_queue_frame(o->owner, &wf);
- } else if ((!o->lastrx) && (o->rxkeyed)) {
- o->lastrx = 1;
- wf.subclass = AST_CONTROL_RADIO_KEY;
- ast_queue_frame(o->owner, &wf);
- }
/* XXX can be simplified returning &ast_null_frame */
/* prepare a NULL frame in case we don't have enough data to return */
- memset(f, 0, sizeof(struct ast_frame));
+ bzero(f, sizeof(struct ast_frame));
f->frametype = AST_FRAME_NULL;
f->src = usbradio_tech.type;
res = read(o->sounddev, o->usbradio_read_buf + o->readpos,
sizeof(o->usbradio_read_buf) - o->readpos);
if (res < 0) /* audio data not ready, return a NULL frame */
+ {
+ if (errno != EAGAIN) return NULL;
+ if (o->readerrs++ > READERR_THRESHOLD)
+ {
+ ast_log(LOG_ERROR,"Stuck USB read channel [%s], un-sticking it!\n",o->name);
+ o->readerrs = 0;
+ return NULL;
+ }
+ if (o->readerrs == 1)
+ ast_log(LOG_WARNING,"Possibly stuck USB read channel. [%s]\n",o->name);
return f;
-
+ }
+ if (o->readerrs) ast_log(LOG_WARNING,"Nope, USB read channel [%s] wasn't stuck after all.\n",o->name);
+ o->readerrs = 0;
o->readpos += res;
if (o->readpos < sizeof(o->usbradio_read_buf)) /* not enough samples */
return f;
@@ -1111,78 +1835,224 @@ static struct ast_frame *usbradio_read(struct ast_channel *c)
return f;
#if DEBUG_CAPTURES == 1
- if (o->b.rxcapraw && frxcapraw)
- fwrite((o->usbradio_read_buf + AST_FRIENDLY_OFFSET), 1, FRAME_SIZE * 2 * 2 * 6, frxcapraw);
+ if (o->b.rxcapraw && frxcapraw) fwrite((o->usbradio_read_buf + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2 * 2 * 6,frxcapraw);
#endif
#if 1
- PmrRx( o->pmrChan,
+ if(o->txkeyed||o->txtestkey)
+ {
+ if(!o->pmrChan->txPttIn)
+ {
+ o->pmrChan->txPttIn=1;
+ if(o->debuglevel) ast_log(LOG_NOTICE,"txPttIn = %i, chan %s\n",o->pmrChan->txPttIn,o->owner->name);
+ }
+ }
+ else if(o->pmrChan->txPttIn)
+ {
+ o->pmrChan->txPttIn=0;
+ if(o->debuglevel) ast_log(LOG_NOTICE,"txPttIn = %i, chan %s\n",o->pmrChan->txPttIn,o->owner->name);
+ }
+ oldpttout = o->pmrChan->txPttOut;
+
+ PmrRx( o->pmrChan,
(i16 *)(o->usbradio_read_buf + AST_FRIENDLY_OFFSET),
- (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
+ (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),
+ (i16 *)(o->usbradio_write_buf_1));
+
+ if (oldpttout != o->pmrChan->txPttOut)
+ {
+ if(o->debuglevel) ast_log(LOG_NOTICE,"txPttOut = %i, chan %s\n",o->pmrChan->txPttOut,o->owner->name);
+ kickptt(o);
+ }
+
+ #if 0 // to write 48KS/s stereo tx data to a file
+ if (!ftxoutraw) ftxoutraw = fopen(TX_CAP_OUT_FILE,"w");
+ if (ftxoutraw) fwrite(o->usbradio_write_buf_1,1,FRAME_SIZE * 2 * 6,ftxoutraw);
+ #endif
+ #if DEBUG_CAPTURES == 1 && XPMR_DEBUG0 == 1
+ if (o->b.txcap2 && ftxcaptrace) fwrite((o->pmrChan->ptxDebug),1,FRAME_SIZE * 2 * 16,ftxcaptrace);
+ #endif
+
+ // 160 samples * 2 bytes/sample * 2 chan * 6x oversampling to 48KS/s
+ datalen = FRAME_SIZE * 24;
+ src = 0; /* read position into f->data */
+ while (src < datalen)
+ {
+ /* Compute spare room in the buffer */
+ int l = sizeof(o->usbradio_write_buf) - o->usbradio_write_dst;
+
+ if (datalen - src >= l)
+ {
+ /* enough to fill a frame */
+ memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
+ soundcard_writeframe(o, (short *) o->usbradio_write_buf);
+ src += l;
+ o->usbradio_write_dst = 0;
+ }
+ else
+ {
+ /* copy residue */
+ l = datalen - src;
+ memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
+ src += l; /* but really, we are done */
+ o->usbradio_write_dst += l;
+ }
+ }
#else
static FILE *hInput;
- i16 iBuff[FRAME_SIZE * 2 * 6];
+ i16 iBuff[FRAME_SIZE*2*6];
- o->pmrChan->b.rxCapture = 1;
+ o->pmrChan->b.rxCapture=1;
- if(!hInput) {
- hInput = fopen("/usr/src/xpmr/testdata/rx_in.pcm", "r");
- if(!hInput) {
- ast_log(LOG_ERROR, " Input Data File Not Found.\n");
+ if(!hInput)
+ {
+ hInput = fopen("/usr/src/xpmr/testdata/rx_in.pcm","r");
+ if(!hInput)
+ {
+ printf(" Input Data File Not Found.\n");
return 0;
}
}
- if (0 == fread((void *)iBuff, 2, FRAME_SIZE * 2 * 6, hInput))
- exit;
+ if(0==fread((void *)iBuff,2,FRAME_SIZE*2*6,hInput))exit;
- PmrRx( o->pmrChan,
+ PmrRx( o->pmrChan,
(i16 *)iBuff,
(i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
#endif
#if 0
- if (!frxoutraw) frxoutraw = fopen(RX_CAP_OUT_FILE, "w");
- if (frxoutraw) fwrite((o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET), 1, FRAME_SIZE * 2, frxoutraw);
+ if (!frxoutraw) frxoutraw = fopen(RX_CAP_OUT_FILE,"w");
+ if (frxoutraw) fwrite((o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2,frxoutraw);
#endif
- #if DEBUG_CAPTURES == 1
- if (frxcaptrace && o->b.rxcap2) fwrite((o->pmrChan->prxDebug), 1, FRAME_SIZE * 2 * 16, frxcaptrace);
+ #if DEBUG_CAPTURES == 1 && XPMR_DEBUG0 == 1
+ if (frxcaptrace && o->b.rxcap2 && o->pmrChan->b.radioactive) fwrite((o->pmrChan->prxDebug),1,FRAME_SIZE * 2 * 16,frxcaptrace);
#endif
- if (o->rxcdtype == CD_HID && (o->pmrChan->rxExtCarrierDetect != o->rxhidsq))
- o->pmrChan->rxExtCarrierDetect = o->rxhidsq;
- if (o->rxcdtype == CD_HID_INVERT && (o->pmrChan->rxExtCarrierDetect == o->rxhidsq))
- o->pmrChan->rxExtCarrierDetect = !o->rxhidsq;
+ cd = 0;
+ if(o->rxcdtype==CD_HID && (o->pmrChan->rxExtCarrierDetect!=o->rxhidsq))
+ o->pmrChan->rxExtCarrierDetect=o->rxhidsq;
+
+ if(o->rxcdtype==CD_HID_INVERT && (o->pmrChan->rxExtCarrierDetect==o->rxhidsq))
+ o->pmrChan->rxExtCarrierDetect=!o->rxhidsq;
- if ( (o->rxcdtype == CD_HID && o->rxhidsq) ||
- (o->rxcdtype == CD_HID_INVERT && !o->rxhidsq) ||
- (o->rxcdtype == CD_XPMR_NOISE && o->pmrChan->rxCarrierDetect) ||
- (o->rxcdtype == CD_XPMR_VOX && o->pmrChan->rxCarrierDetect) )
- res = 1;
+ if( (o->rxcdtype==CD_HID && o->rxhidsq) ||
+ (o->rxcdtype==CD_HID_INVERT && !o->rxhidsq) ||
+ (o->rxcdtype==CD_XPMR_NOISE && o->pmrChan->rxCarrierDetect) ||
+ (o->rxcdtype==CD_XPMR_VOX && o->pmrChan->rxCarrierDetect)
+ )
+ {
+ if (!o->pmrChan->txPttOut || o->radioduplex)cd=1;
+ }
else
- res = 0;
+ {
+ cd=0;
+ }
- if (res != o->rxcarrierdetect) {
- o->rxcarrierdetect = res;
- if (o->debuglevel)
- ast_debug(4, "rxcarrierdetect = %d\n", res);
+ if(cd!=o->rxcarrierdetect)
+ {
+ o->rxcarrierdetect=cd;
+ if(o->debuglevel) ast_log(LOG_NOTICE,"rxcarrierdetect = %i, chan %s\n",cd,o->owner->name);
+ // printf("rxcarrierdetect = %i, chan %s\n",res,o->owner->name);
}
- if (o->pmrChan->rxCtcss->decode != o->rxctcssdecode) {
- if (o->debuglevel)
- ast_debug(4, "rxctcssdecode = %d\n", o->pmrChan->rxCtcss->decode);
- o->rxctcssdecode = o->pmrChan->rxCtcss->decode;
+ if(o->pmrChan->b.ctcssRxEnable && o->pmrChan->rxCtcss->decode!=o->rxctcssdecode)
+ {
+ if(o->debuglevel)ast_log(LOG_NOTICE,"rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
+ // printf("rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
+ o->rxctcssdecode=o->pmrChan->rxCtcss->decode;
+ strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
}
- if ( ( o->rxctcssfreq && (o->rxctcssdecode == o->pmrChan->rxCtcssIndex)) ||
- ( !o->rxctcssfreq && o->rxcarrierdetect) )
- o->rxkeyed = 1;
+ #ifndef HAVE_XPMRX
+ if( !o->pmrChan->b.ctcssRxEnable ||
+ ( o->pmrChan->b.ctcssRxEnable &&
+ o->pmrChan->rxCtcss->decode>CTCSS_NULL &&
+ o->pmrChan->smode==SMODE_CTCSS )
+ )
+ {
+ sd=1;
+ }
+ else
+ {
+ sd=0;
+ }
+ #else
+ if( (!o->pmrChan->b.ctcssRxEnable && !o->pmrChan->b.dcsRxEnable && !o->pmrChan->b.lmrRxEnable) ||
+ ( o->pmrChan->b.ctcssRxEnable &&
+ o->pmrChan->rxCtcss->decode>CTCSS_NULL &&
+ o->pmrChan->smode==SMODE_CTCSS ) ||
+ ( o->pmrChan->b.dcsRxEnable &&
+ o->pmrChan->decDcs->decode > 0 &&
+ o->pmrChan->smode==SMODE_DCS )
+ )
+ {
+ sd=1;
+ }
else
+ {
+ sd=0;
+ }
+
+ if(o->pmrChan->decDcs->decode!=o->rxdcsdecode)
+ {
+ if(o->debuglevel)ast_log(LOG_NOTICE,"rxdcsdecode = %s, chan %s\n",o->pmrChan->rxctcssfreq,o->owner->name);
+ // printf("rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
+ o->rxdcsdecode=o->pmrChan->decDcs->decode;
+ strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
+ }
+
+ if(o->pmrChan->rptnum && (o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed != o->rxlsddecode))
+ {
+ if(o->debuglevel)ast_log(LOG_NOTICE,"rxLSDecode = %s, chan %s\n",o->pmrChan->rxctcssfreq,o->owner->name);
+ o->rxlsddecode=o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed;
+ strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
+ }
+
+ if( (o->pmrChan->rptnum>0 && o->pmrChan->smode==SMODE_LSD && o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed)||
+ (o->pmrChan->smode==SMODE_DCS && o->pmrChan->decDcs->decode>0) )
+ {
+ sd=1;
+ }
+ #endif
+
+ if ( cd && sd )
+ {
+ //if(!o->rxkeyed)o->pmrChan->dd.b.doitnow=1;
+ if(!o->rxkeyed && o->debuglevel)ast_log(LOG_NOTICE,"o->rxkeyed = 1, chan %s\n", o->owner->name);
+ o->rxkeyed = 1;
+ }
+ else
+ {
+ //if(o->rxkeyed)o->pmrChan->dd.b.doitnow=1;
+ if(o->rxkeyed && o->debuglevel)ast_log(LOG_NOTICE,"o->rxkeyed = 0, chan %s\n",o->owner->name);
o->rxkeyed = 0;
+ }
+ // provide rx signal detect conditions
+ if (o->lastrx && (!o->rxkeyed))
+ {
+ o->lastrx = 0;
+ //printf("AST_CONTROL_RADIO_UNKEY\n");
+ wf.subclass = AST_CONTROL_RADIO_UNKEY;
+ ast_queue_frame(o->owner, &wf);
+ }
+ else if ((!o->lastrx) && (o->rxkeyed))
+ {
+ o->lastrx = 1;
+ //printf("AST_CONTROL_RADIO_KEY\n");
+ wf.subclass = AST_CONTROL_RADIO_KEY;
+ if(o->rxctcssdecode)
+ {
+ wf.data = o->rxctcssfreq;
+ wf.datalen = strlen(o->rxctcssfreq) + 1;
+ TRACEO(1,("AST_CONTROL_RADIO_KEY text=%s\n",o->rxctcssfreq));
+ }
+ ast_queue_frame(o->owner, &wf);
+ }
o->readpos = AST_FRIENDLY_OFFSET; /* reset read pointer for next frame */
if (c->_state != AST_STATE_UP) /* drop data if frame is not up */
@@ -1207,13 +2077,22 @@ static struct ast_frame *usbradio_read(struct ast_channel *c)
}
f->offset = AST_FRIENDLY_OFFSET;
- if (o->dsp) {
- f1 = ast_dsp_process(c, o->dsp, f);
- if ((f1->frametype == AST_FRAME_DTMF_END) || (f1->frametype == AST_FRAME_DTMF_BEGIN)) {
- if (f1->frametype == AST_FRAME_DTMF_END)
- ast_log(LOG_NOTICE,"Got DTMF char %c\n",f1->subclass);
- return f1;
+ if (o->dsp)
+ {
+ f1 = ast_dsp_process(c,o->dsp,f);
+ if ((f1->frametype == AST_FRAME_DTMF_END) ||
+ (f1->frametype == AST_FRAME_DTMF_BEGIN))
+ {
+ if ((f1->subclass == 'm') || (f1->subclass == 'u'))
+ {
+ f1->frametype = AST_FRAME_NULL;
+ f1->subclass = 0;
+ return(f1);
}
+ if (f1->frametype == AST_FRAME_DTMF_END)
+ ast_log(LOG_NOTICE,"Got DTMF char %c\n",f1->subclass);
+ return(f1);
+ }
}
return f;
}
@@ -1229,43 +2108,58 @@ static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newch
static int usbradio_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
{
struct chan_usbradio_pvt *o = c->tech_pvt;
- int res = 0;
+ int res = -1;
switch (cond) {
- case AST_CONTROL_BUSY:
- case AST_CONTROL_CONGESTION:
- case AST_CONTROL_RINGING:
- case -1:
- res = -1;
- break;
- case AST_CONTROL_PROGRESS:
- case AST_CONTROL_PROCEEDING:
- case AST_CONTROL_VIDUPDATE:
- break;
- case AST_CONTROL_HOLD:
- ast_verb(0, " << Console Has Been Placed on Hold >> \n");
- ast_moh_start(c, data, o->mohinterpret);
- break;
- case AST_CONTROL_UNHOLD:
- ast_verb(0, " << Console Has Been Retrieved from Hold >> \n");
- ast_moh_stop(c);
- break;
- case AST_CONTROL_RADIO_KEY:
- o->txkeyed = 1;
- if (o->debuglevel)
- ast_verb(0, " << Radio Transmit On. >> \n");
- break;
- case AST_CONTROL_RADIO_UNKEY:
- o->txkeyed = 0;
- if (o->debuglevel)
- ast_verb(0, " << Radio Transmit Off. >> \n");
- break;
- default:
- ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
- return -1;
+ case AST_CONTROL_BUSY:
+ case AST_CONTROL_CONGESTION:
+ case AST_CONTROL_RINGING:
+ res = cond;
+ break;
+
+ case -1:
+#ifndef NEW_ASTERISK
+ o->cursound = -1;
+ o->nosound = 0; /* when cursound is -1 nosound must be 0 */
+#endif
+ return 0;
+
+ case AST_CONTROL_VIDUPDATE:
+ res = -1;
+ break;
+ case AST_CONTROL_HOLD:
+ ast_verbose(" << Console Has Been Placed on Hold >> \n");
+ ast_moh_start(c, data, o->mohinterpret);
+ break;
+ case AST_CONTROL_UNHOLD:
+ ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
+ ast_moh_stop(c);
+ break;
+ case AST_CONTROL_PROCEEDING:
+ ast_verbose(" << Call Proceeding... >> \n");
+ ast_moh_stop(c);
+ break;
+ case AST_CONTROL_PROGRESS:
+ ast_verbose(" << Call Progress... >> \n");
+ ast_moh_stop(c);
+ break;
+ case AST_CONTROL_RADIO_KEY:
+ o->txkeyed = 1;
+ if(o->debuglevel)ast_verbose(" << AST_CONTROL_RADIO_KEY Radio Transmit On. >> \n");
+ break;
+ case AST_CONTROL_RADIO_UNKEY:
+ o->txkeyed = 0;
+ if(o->debuglevel)ast_verbose(" << AST_CONTROL_RADIO_UNKEY Radio Transmit Off. >> \n");
+ break;
+ default:
+ ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
+ return -1;
}
- return res;
+ if (res > -1)
+ ring(o, res);
+
+ return 0;
}
/*
@@ -1274,11 +2168,8 @@ static int usbradio_indicate(struct ast_channel *c, int cond, const void *data,
static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext, char *ctx, int state)
{
struct ast_channel *c;
- char device[15] = "dsp";
- if (o->devicenum)
- snprintf(device + 3, sizeof(device) - 3, "%d", o->devicenum);
- c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, 0, "usbRadio/%s", device);
+ c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, 0, "Radio/%s", o->name);
if (c == NULL)
return NULL;
c->tech = &usbradio_tech;
@@ -1315,13 +2206,19 @@ static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext,
return c;
}
-
+/*
+*/
static struct ast_channel *usbradio_request(const char *type, int format, void *data, int *cause)
{
struct ast_channel *c;
struct chan_usbradio_pvt *o = find_desc(data);
- ast_debug(4, "usbradio_request ty <%s> data 0x%p <%s>\n", type, data, (char *) data);
+ TRACEO(1,("usbradio_request()\n"));
+
+ if (0)
+ {
+ ast_log(LOG_WARNING, "usbradio_request type <%s> data 0x%p <%s>\n", type, data, (char *) data);
+ }
if (o == NULL) {
ast_log(LOG_NOTICE, "Device %s not found\n", (char *) data);
/* XXX we could default to 'dsp' perhaps ? */
@@ -1341,260 +2238,275 @@ static struct ast_channel *usbradio_request(const char *type, int format, void *
ast_log(LOG_WARNING, "Unable to create new usb channel\n");
return NULL;
}
+
+ o->b.remoted=0;
+ xpmr_config(o);
+
return c;
}
-
-static char *handle_cli_radio_key(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+/*
+*/
+static int console_key(int fd, int argc, char *argv[])
{
- struct chan_usbradio_pvt *o = NULL;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "radio key";
- e->usage =
- "Usage: radio key\n"
- " Simulates COR active.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 2)
- return CLI_SHOWUSAGE;
+ struct chan_usbradio_pvt *o = find_desc(usbradio_active);
- o = find_desc(usbradio_active);
+ if (argc != 2)
+ return RESULT_SHOWUSAGE;
o->txtestkey = 1;
-
- return CLI_SUCCESS;
+ return RESULT_SUCCESS;
}
-
-static char *handle_cli_radio_unkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+/*
+*/
+static int console_unkey(int fd, int argc, char *argv[])
{
- struct chan_usbradio_pvt *o = NULL;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "radio unkey";
- e->usage =
- "Usage: radio unkey\n"
- " Simulates COR un-active.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 2)
- return CLI_SHOWUSAGE;
+ struct chan_usbradio_pvt *o = find_desc(usbradio_active);
- o = find_desc(usbradio_active);
+ if (argc != 2)
+ return RESULT_SHOWUSAGE;
o->txtestkey = 0;
-
- return CLI_SUCCESS;
+ return RESULT_SUCCESS;
}
-static char *handle_cli_radio_tune(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static int radio_tune(int fd, int argc, char *argv[])
{
- struct chan_usbradio_pvt *o = NULL;
- int i = 0;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "radio tune [rxnoise|rxvoice|rxtone|rxsquelch|rxcap|rxtracecap|"
- "txvoice|txtone|txcap|txtracecap|auxvoice|nocap|dump|save]";
- /* radio tune 6 3000 measured tx value */
- e->usage =
- "Usage: radio tune <function>\n"
- " rxnoise\n"
- " rxvoice\n"
- " rxtone\n"
- " rxsquelch [newsetting]\n"
- " rxcap\n"
- " rxtracecap\n"
- " txvoice [newsetting]\n"
- " txtone [newsetting]\n"
- " txcap\n"
- " txtracecap\n"
- " auxvoice [newsetting]\n"
- " nocap\n"
- " dump\n"
- " save (settings to tuning file)\n"
- "\n"
- " All [newsetting]s are values 0-999\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if ((a->argc < 2) || (a->argc > 4))
- return CLI_SHOWUSAGE;
-
- if (a->argc == 2) { /* just show stuff */
- ast_cli(a->fd, "Output A is currently set to %s.\n",
- o->txmixa == TX_OUT_COMPOSITE ? "composite" :
- o->txmixa == TX_OUT_VOICE ? "voice" :
- o->txmixa == TX_OUT_LSD ? "tone" :
- o->txmixa == TX_OUT_AUX ? "auxvoice" :
- "off");
-
- ast_cli(a->fd, "Output B is currently set to %s.\n",
- o->txmixb == TX_OUT_COMPOSITE ? "composite" :
- o->txmixb == TX_OUT_VOICE ? "voice" :
- o->txmixb == TX_OUT_LSD ? "tone" :
- o->txmixb == TX_OUT_AUX ? "auxvoice" :
- "off");
-
- ast_cli(a->fd, "Tx Voice Level currently set to %d\n", o->txmixaset);
- ast_cli(a->fd, "Tx Tone Level currently set to %d\n", o->txctcssadj);
- ast_cli(a->fd, "Rx Squelch currently set to %d\n", o->rxsquelchadj);
- return CLI_SHOWUSAGE;
- }
-
- o = find_desc(usbradio_active);
-
- if (!strcasecmp(a->argv[2], "rxnoise"))
- tune_rxinput(o);
- else if (!strcasecmp(a->argv[2], "rxvoice"))
- tune_rxvoice(o);
- else if (!strcasecmp(a->argv[2], "rxtone"))
- tune_rxctcss(o);
- else if (!strcasecmp(a->argv[2], "rxsquelch")) {
- if (a->argc == 3) {
- ast_cli(a->fd, "Current Signal Strength is %d\n", ((32767 - o->pmrChan->rxRssi) * 1000 / 32767));
- ast_cli(a->fd, "Current Squelch setting is %d\n", o->rxsquelchadj);
-#if 0
- ast_cli(a->fd,"Current Raw RSSI is %d\n",o->pmrChan->rxRssi);
- ast_cli(a->fd,"Current (real) Squelch setting is %d\n",*(o->pmrChan->prxSquelchAdjust));
-#endif
+ struct chan_usbradio_pvt *o = find_desc(usbradio_active);
+ int i=0;
+
+ if ((argc < 2) || (argc > 4))
+ return RESULT_SHOWUSAGE;
+
+ if (argc == 2) /* just show stuff */
+ {
+ ast_cli(fd,"Active radio interface is [%s]\n",usbradio_active);
+ ast_cli(fd,"Output A is currently set to ");
+ if(o->txmixa==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
+ else if (o->txmixa==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
+ else if (o->txmixa==TX_OUT_LSD)ast_cli(fd,"tone.\n");
+ else if (o->txmixa==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n");
+ else ast_cli(fd,"off.\n");
+
+ ast_cli(fd,"Output B is currently set to ");
+ if(o->txmixb==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
+ else if (o->txmixb==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
+ else if (o->txmixb==TX_OUT_LSD)ast_cli(fd,"tone.\n");
+ else if (o->txmixb==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n");
+ else ast_cli(fd,"off.\n");
+
+ ast_cli(fd,"Tx Voice Level currently set to %d\n",o->txmixaset);
+ ast_cli(fd,"Tx Tone Level currently set to %d\n",o->txctcssadj);
+ ast_cli(fd,"Rx Squelch currently set to %d\n",o->rxsquelchadj);
+ ast_cli(fd,"Device String is %s\n",o->devstr);
+ return RESULT_SHOWUSAGE;
+ }
+
+ o->pmrChan->b.tuning=1;
+
+ if (!strcasecmp(argv[2],"rxnoise")) tune_rxinput(fd,o);
+ else if (!strcasecmp(argv[2],"rxvoice")) tune_rxvoice(fd,o);
+ else if (!strcasecmp(argv[2],"rxtone")) tune_rxctcss(fd,o);
+ else if (!strcasecmp(argv[2],"rxsquelch"))
+ {
+ if (argc == 3)
+ {
+ ast_cli(fd,"Current Signal Strength is %d\n",((32767-o->pmrChan->rxRssi)*1000/32767));
+ ast_cli(fd,"Current Squelch setting is %d\n",o->rxsquelchadj);
+ //ast_cli(fd,"Current Raw RSSI is %d\n",o->pmrChan->rxRssi);
+ //ast_cli(fd,"Current (real) Squelch setting is %d\n",*(o->pmrChan->prxSquelchAdjust));
} else {
- i = atoi(a->argv[3]);
- if ((i < 0) || (i > 999))
- return CLI_SHOWUSAGE;
- ast_cli(a->fd, "Changed Squelch setting to %d\n", i);
+ i = atoi(argv[3]);
+ if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
+ ast_cli(fd,"Changed Squelch setting to %d\n",i);
o->rxsquelchadj = i;
- *(o->pmrChan->prxSquelchAdjust) = ((999 - i) * 32767) / 1000;
+ *(o->pmrChan->prxSquelchAdjust)= ((999 - i) * 32767) / 1000;
}
- } else if (!strcasecmp(a->argv[2], "txvoice")) {
+ }
+ else if (!strcasecmp(argv[2],"txvoice")) {
i = 0;
- if ((o->txmixa != TX_OUT_VOICE) && (o->txmixb != TX_OUT_VOICE) &&
- (o->txmixa != TX_OUT_COMPOSITE) && (o->txmixb != TX_OUT_COMPOSITE)) {
- ast_log(LOG_ERROR, "No txvoice output configured.\n");
- } else if (a->argc == 3) {
- if ((o->txmixa == TX_OUT_VOICE) || (o->txmixa == TX_OUT_COMPOSITE))
- ast_cli(a->fd, "Current txvoice setting on Channel A is %d\n", o->txmixaset);
+ if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
+ (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
+ )
+ {
+ ast_log(LOG_ERROR,"No txvoice output configured.\n");
+ }
+ else if (argc == 3)
+ {
+ if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
+ ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset);
else
- ast_cli(a->fd, "Current txvoice setting on Channel B is %d\n", o->txmixbset);
- } else {
- i = atoi(a->argv[3]);
- if ((i < 0) || (i > 999))
- return CLI_SHOWUSAGE;
-
- if ((o->txmixa == TX_OUT_VOICE) || (o->txmixa == TX_OUT_COMPOSITE)) {
- o->txmixaset = i;
- ast_cli(a->fd, "Changed txvoice setting on Channel A to %d\n", o->txmixaset);
- } else {
- o->txmixbset = i;
- ast_cli(a->fd, "Changed txvoice setting on Channel B to %d\n", o->txmixbset);
+ ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset);
+ }
+ else
+ {
+ i = atoi(argv[3]);
+ if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
+
+ if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
+ {
+ o->txmixaset=i;
+ ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset);
+ }
+ else
+ {
+ o->txmixbset=i;
+ ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset);
}
mixer_write(o);
mult_set(o);
- ast_cli(a->fd, "Changed Tx Voice Output setting to %d\n", i);
+ ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i);
}
- tune_txoutput(o,i);
- } else if (!strcasecmp(a->argv[2], "auxvoice")) {
+ o->pmrChan->b.txCtcssInhibit=1;
+ tune_txoutput(o,i,fd);
+ o->pmrChan->b.txCtcssInhibit=0;
+ }
+ else if (!strcasecmp(argv[2],"txall")) {
i = 0;
- if ( (o->txmixa != TX_OUT_AUX) && (o->txmixb != TX_OUT_AUX))
- ast_log(LOG_WARNING, "No auxvoice output configured.\n");
- else if (a->argc == 3) {
- if (o->txmixa == TX_OUT_AUX)
- ast_cli(a->fd, "Current auxvoice setting on Channel A is %d\n", o->txmixaset);
+
+ if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
+ (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
+ )
+ {
+ ast_log(LOG_ERROR,"No txvoice output configured.\n");
+ }
+ else if (argc == 3)
+ {
+ if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
+ ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset);
else
- ast_cli(a->fd, "Current auxvoice setting on Channel B is %d\n", o->txmixbset);
- } else {
- i = atoi(a->argv[3]);
- if ((i < 0) || (i > 999))
- return CLI_SHOWUSAGE;
- if (o->txmixa == TX_OUT_AUX) {
- o->txmixbset = i;
- ast_cli(a->fd, "Changed auxvoice setting on Channel A to %d\n", o->txmixaset);
- } else {
- o->txmixbset = i;
- ast_cli(a->fd, "Changed auxvoice setting on Channel B to %d\n", o->txmixbset);
+ ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset);
+ }
+ else
+ {
+ i = atoi(argv[3]);
+ if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
+
+ if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
+ {
+ o->txmixaset=i;
+ ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset);
+ }
+ else
+ {
+ o->txmixbset=i;
+ ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset);
+ }
+ mixer_write(o);
+ mult_set(o);
+ ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i);
+ }
+ tune_txoutput(o,i,fd);
+ }
+ else if (!strcasecmp(argv[2],"auxvoice")) {
+ i = 0;
+ if( (o->txmixa!=TX_OUT_AUX) && (o->txmixb!=TX_OUT_AUX))
+ {
+ ast_log(LOG_WARNING,"No auxvoice output configured.\n");
+ }
+ else if (argc == 3)
+ {
+ if(o->txmixa==TX_OUT_AUX)
+ ast_cli(fd,"Current auxvoice setting on Channel A is %d\n",o->txmixaset);
+ else
+ ast_cli(fd,"Current auxvoice setting on Channel B is %d\n",o->txmixbset);
+ }
+ else
+ {
+ i = atoi(argv[3]);
+ if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
+ if(o->txmixa==TX_OUT_AUX)
+ {
+ o->txmixbset=i;
+ ast_cli(fd,"Changed auxvoice setting on Channel A to %d\n",o->txmixaset);
+ }
+ else
+ {
+ o->txmixbset=i;
+ ast_cli(fd,"Changed auxvoice setting on Channel B to %d\n",o->txmixbset);
}
mixer_write(o);
mult_set(o);
}
- /* tune_auxoutput(o,i); */
- } else if (!strcasecmp(a->argv[2], "txtone")) {
- if (a->argc == 3)
- ast_cli(a->fd, "Current Tx CTCSS modulation setting = %d\n", o->txctcssadj);
- else {
- i = atoi(a->argv[3]);
- if ((i < 0) || (i > 999))
- return CLI_SHOWUSAGE;
+ //tune_auxoutput(o,i);
+ }
+ else if (!strcasecmp(argv[2],"txtone"))
+ {
+ if (argc == 3)
+ ast_cli(fd,"Current Tx CTCSS modulation setting = %d\n",o->txctcssadj);
+ else
+ {
+ i = atoi(argv[3]);
+ if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
o->txctcssadj = i;
set_txctcss_level(o);
- ast_cli(a->fd, "Changed Tx CTCSS modulation setting to %i\n", i);
+ ast_cli(fd,"Changed Tx CTCSS modulation setting to %i\n",i);
}
- o->txtestkey = 1;
+ o->txtestkey=1;
usleep(5000000);
- o->txtestkey = 0;
- } else if (!strcasecmp(a->argv[2],"dump"))
- pmrdump(o);
- else if (!strcasecmp(a->argv[2],"nocap")) {
- ast_cli(a->fd, "File capture (trace) was rx=%d tx=%d and now off.\n", o->b.rxcap2, o->b.txcap2);
- ast_cli(a->fd, "File capture (raw) was rx=%d tx=%d and now off.\n", o->b.rxcapraw, o->b.txcapraw);
- o->b.rxcapraw = o->b.txcapraw = o->b.rxcap2 = o->b.txcap2 = o->pmrChan->b.rxCapture = o->pmrChan->b.txCapture = 0;
- if (frxcapraw) {
- fclose(frxcapraw);
- frxcapraw = NULL;
- }
- if (frxcaptrace) {
- fclose(frxcaptrace);
- frxcaptrace = NULL;
- }
- if (frxoutraw) {
- fclose(frxoutraw);
- frxoutraw = NULL;
- }
- if (ftxcapraw) {
- fclose(ftxcapraw);
- ftxcapraw = NULL;
- }
- if (ftxcaptrace) {
- fclose(ftxcaptrace);
- ftxcaptrace = NULL;
- }
- if (ftxoutraw) {
- fclose(ftxoutraw);
- ftxoutraw = NULL;
- }
- } else if (!strcasecmp(a->argv[2], "rxtracecap")) {
- if (!frxcaptrace)
- frxcaptrace = fopen(RX_CAP_TRACE_FILE, "w");
- ast_cli(a->fd, "Trace rx on.\n");
- o->b.rxcap2 = o->pmrChan->b.rxCapture = 1;
- } else if (!strcasecmp(a->argv[2], "txtracecap")) {
- if (!ftxcaptrace)
- ftxcaptrace = fopen(TX_CAP_TRACE_FILE, "w");
- ast_cli(a->fd, "Trace tx on.\n");
- o->b.txcap2 = o->pmrChan->b.txCapture = 1;
- } else if (!strcasecmp(a->argv[2], "rxcap")) {
- if (!frxcapraw)
- frxcapraw = fopen(RX_CAP_RAW_FILE, "w");
- ast_cli(a->fd, "cap rx raw on.\n");
- o->b.rxcapraw = 1;
- } else if (!strcasecmp(a->argv[2], "txcap")) {
- if (!ftxcapraw)
- ftxcapraw = fopen(TX_CAP_RAW_FILE, "w");
- ast_cli(a->fd, "cap tx raw on.\n");
- o->b.txcapraw = 1;
- } else if (!strcasecmp(a->argv[2], "save")) {
+ o->txtestkey=0;
+ }
+ else if (!strcasecmp(argv[2],"dump")) pmrdump(o);
+ else if (!strcasecmp(argv[2],"nocap"))
+ {
+ ast_cli(fd,"File capture (trace) was rx=%d tx=%d and now off.\n",o->b.rxcap2,o->b.txcap2);
+ ast_cli(fd,"File capture (raw) was rx=%d tx=%d and now off.\n",o->b.rxcapraw,o->b.txcapraw);
+ o->b.rxcapraw=o->b.txcapraw=o->b.rxcap2=o->b.txcap2=o->pmrChan->b.rxCapture=o->pmrChan->b.txCapture=0;
+ if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; }
+ if (frxcaptrace) { fclose(frxcaptrace); frxcaptrace = NULL; }
+ if (frxoutraw) { fclose(frxoutraw); frxoutraw = NULL; }
+ if (ftxcapraw) { fclose(ftxcapraw); ftxcapraw = NULL; }
+ if (ftxcaptrace) { fclose(ftxcaptrace); ftxcaptrace = NULL; }
+ if (ftxoutraw) { fclose(ftxoutraw); ftxoutraw = NULL; }
+ }
+ else if (!strcasecmp(argv[2],"rxtracecap"))
+ {
+ if (!frxcaptrace) frxcaptrace= fopen(RX_CAP_TRACE_FILE,"w");
+ ast_cli(fd,"Trace rx on.\n");
+ o->b.rxcap2=o->pmrChan->b.rxCapture=1;
+ }
+ else if (!strcasecmp(argv[2],"txtracecap"))
+ {
+ if (!ftxcaptrace) ftxcaptrace= fopen(TX_CAP_TRACE_FILE,"w");
+ ast_cli(fd,"Trace tx on.\n");
+ o->b.txcap2=o->pmrChan->b.txCapture=1;
+ }
+ else if (!strcasecmp(argv[2],"rxcap"))
+ {
+ if (!frxcapraw) frxcapraw = fopen(RX_CAP_RAW_FILE,"w");
+ ast_cli(fd,"cap rx raw on.\n");
+ o->b.rxcapraw=1;
+ }
+ else if (!strcasecmp(argv[2],"txcap"))
+ {
+ if (!ftxcapraw) ftxcapraw = fopen(TX_CAP_RAW_FILE,"w");
+ ast_cli(fd,"cap tx raw on.\n");
+ o->b.txcapraw=1;
+ }
+ else if (!strcasecmp(argv[2],"save"))
+ {
tune_write(o);
- ast_cli(a->fd, "Saved radio tuning settings to usbradio_tune.conf\n");
- } else
- return CLI_SHOWUSAGE;
- return CLI_SUCCESS;
+ ast_cli(fd,"Saved radio tuning settings to usbradio_tune_%s.conf\n",o->name);
+ }
+ else if (!strcasecmp(argv[2],"load"))
+ {
+ ast_mutex_lock(&o->eepromlock);
+ while(o->eepromctl)
+ {
+ ast_mutex_unlock(&o->eepromlock);
+ usleep(10000);
+ ast_mutex_lock(&o->eepromlock);
+ }
+ o->eepromctl = 1; /* request a load */
+ ast_mutex_unlock(&o->eepromlock);
+
+ ast_cli(fd,"Requesting loading of tuning settings from EEPROM for channel %s\n",o->name);
+ }
+ else
+ {
+ o->pmrChan->b.tuning=0;
+ return RESULT_SHOWUSAGE;
+ }
+ o->pmrChan->b.tuning=0;
+ return RESULT_SUCCESS;
}
/*
@@ -1604,491 +2516,599 @@ static char *handle_cli_radio_tune(struct ast_cli_entry *e, int cmd, struct ast_
*/
static int set_txctcss_level(struct chan_usbradio_pvt *o)
{
- if (o->txmixa == TX_OUT_LSD) {
- o->txmixaset = (151 * o->txctcssadj) / 1000;
+ if (o->txmixa == TX_OUT_LSD)
+ {
+// o->txmixaset=(151*o->txctcssadj) / 1000;
+ o->txmixaset=o->txctcssadj;
mixer_write(o);
mult_set(o);
- } else if (o->txmixb == TX_OUT_LSD) {
- o->txmixbset = (151 * o->txctcssadj) / 1000;
+ }
+ else if (o->txmixb == TX_OUT_LSD)
+ {
+// o->txmixbset=(151*o->txctcssadj) / 1000;
+ o->txmixbset=o->txctcssadj;
mixer_write(o);
mult_set(o);
- } else {
- *o->pmrChan->ptxCtcssAdjust = (o->txctcssadj * M_Q8) / 1000;
+ }
+ else
+ {
+ *o->pmrChan->ptxCtcssAdjust=(o->txctcssadj * M_Q8) / 1000;
}
return 0;
}
/*
CLI debugging on and off
*/
-static char *handle_cli_radio_set_debug_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static int radio_set_debug(int fd, int argc, char *argv[])
{
- struct chan_usbradio_pvt *o = NULL;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "radio set debug [off]";
- e->usage =
- "Usage: radio set debug [off]\n"
- " Enable/Disable radio debugging.\n";
- case CLI_GENERATE:
- return NULL;
- }
- if (a->argc < 3 || a->argc > 4)
- return CLI_SHOWUSAGE;
- if (a->argc == 4 && strncasecmp(a->argv[3], "off", 3))
- return CLI_SHOWUSAGE;
-
- o = find_desc(usbradio_active);
+ struct chan_usbradio_pvt *o = find_desc(usbradio_active);
- if (a->argc == 3)
- o->debuglevel = 1;
- else
- o->debuglevel = 0;
+ o->debuglevel=1;
+ ast_cli(fd,"usbradio debug on.\n");
+ return RESULT_SUCCESS;
+}
- ast_cli(a->fd, "USB Radio debugging %s.\n", o->debuglevel ? "enabled" : "disabled");
+static int radio_set_debug_off(int fd, int argc, char *argv[])
+{
+ struct chan_usbradio_pvt *o = find_desc(usbradio_active);
- return CLI_SUCCESS;
+ o->debuglevel=0;
+ ast_cli(fd,"usbradio debug off.\n");
+ return RESULT_SUCCESS;
}
-static char *handle_cli_radio_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static int radio_active(int fd, int argc, char *argv[])
{
- struct chan_usbradio_pvt *o = NULL;
+ if (argc == 2)
+ ast_cli(fd, "active (command) USB Radio device is [%s]\n", usbradio_active);
+ else if (argc != 3)
+ return RESULT_SHOWUSAGE;
+ else {
+ struct chan_usbradio_pvt *o;
+ if (strcmp(argv[2], "show") == 0) {
+ for (o = usbradio_default.next; o; o = o->next)
+ ast_cli(fd, "device [%s] exists\n", o->name);
+ return RESULT_SUCCESS;
+ }
+ o = find_desc(argv[2]);
+ if (o == NULL)
+ ast_cli(fd, "No device [%s] exists\n", argv[2]);
+ else
+ {
+ struct chan_usbradio_pvt *ao;
+ for (ao = usbradio_default.next; ao && ao->name ; ao = ao->next)ao->pmrChan->b.radioactive=0;
+ usbradio_active = o->name;
+ o->pmrChan->b.radioactive=1;
+ }
+ }
+ return RESULT_SUCCESS;
+}
+/*
+ CLI debugging on and off
+*/
+static int radio_set_xpmr_debug(int fd, int argc, char *argv[])
+{
+ struct chan_usbradio_pvt *o = find_desc(usbradio_active);
- switch (cmd) {
- case CLI_INIT:
- e->command = "radio set debug {on|off}";
- e->usage =
- "Usage: radio set debug {on|off}\n"
- " Enable/Disable radio debugging.\n";
- case CLI_GENERATE:
- return NULL;
- }
+ if (argc == 4)
+ {
+ int i;
+ i = atoi(argv[3]);
+ if ((i >= 0) && (i <= 100))
+ {
+ o->pmrChan->tracelevel=i;
+ }
+ }
+ // add ability to set it for a number of frames after which it reverts
+ ast_cli(fd,"usbradio xdebug on tracelevel %i\n",o->pmrChan->tracelevel);
- if (a->argc != e->args)
- return CLI_SHOWUSAGE;
+ return RESULT_SUCCESS;
+}
- o = find_desc(usbradio_active);
- if (!strncasecmp(a->argv[e->args - 1], "on", 2))
- o->debuglevel = 1;
- else if (!strncasecmp(a->argv[e->args - 1], "off", 3))
- o->debuglevel = 0;
- else
- return CLI_SHOWUSAGE;
+static char key_usage[] =
+ "Usage: radio key\n"
+ " Simulates COR active.\n";
- ast_cli(a->fd, "USB Radio debugging %s.\n", o->debuglevel ? "enabled" : "disabled");
+static char unkey_usage[] =
+ "Usage: radio unkey\n"
+ " Simulates COR un-active.\n";
- return CLI_SUCCESS;
-}
+static char active_usage[] =
+ "Usage: radio active [device-name]\n"
+ " If used without a parameter, displays which device is the current\n"
+ "one being commanded. If a device is specified, the commanded radio device is changed\n"
+ "to the device specified.\n";
+/*
+radio tune 6 3000 measured tx value
+*/
+static char radio_tune_usage[] =
+ "Usage: radio tune <function>\n"
+ " rxnoise\n"
+ " rxvoice\n"
+ " rxtone\n"
+ " rxsquelch [newsetting]\n"
+ " txvoice [newsetting]\n"
+ " txtone [newsetting]\n"
+ " auxvoice [newsetting]\n"
+ " save (settings to tuning file)\n"
+ " load (tuning settings from EEPROM)\n"
+ "\n All [newsetting]'s are values 0-999\n\n";
+
+#ifndef NEW_ASTERISK
-static struct ast_cli_entry cli_radio_set_debug_deprecated = AST_CLI_DEFINE(handle_cli_radio_set_debug_deprecated, "Enable/Disable Radio Debugging");
static struct ast_cli_entry cli_usbradio[] = {
- AST_CLI_DEFINE(handle_cli_radio_key, "Simulate Rx Signal Present"),
- AST_CLI_DEFINE(handle_cli_radio_unkey, "Simulate Rx Signal Lusb"),
- AST_CLI_DEFINE(handle_cli_radio_tune, "Radio Tune"),
- AST_CLI_DEFINE(handle_cli_radio_set_debug, "Enable/Disable Radio Debugging", .deprecate_cmd = &cli_radio_set_debug_deprecated),
+ { { "radio", "key", NULL },
+ console_key, "Simulate Rx Signal Present",
+ key_usage, NULL, NULL},
+
+ { { "radio", "unkey", NULL },
+ console_unkey, "Simulate Rx Signal Lusb",
+ unkey_usage, NULL, NULL },
+
+ { { "radio", "tune", NULL },
+ radio_tune, "Radio Tune",
+ radio_tune_usage, NULL, NULL },
+
+ { { "radio", "set", "debug", NULL },
+ radio_set_debug, "Radio Debug",
+ radio_tune_usage, NULL, NULL },
+
+ { { "radio", "set", "debug", "off", NULL },
+ radio_set_debug_off, "Radio Debug",
+ radio_tune_usage, NULL, NULL },
+
+ { { "radio", "active", NULL },
+ radio_active, "Change commanded device",
+ active_usage, NULL, NULL },
+
+ { { "radio", "set", "xdebug", NULL },
+ radio_set_xpmr_debug, "Radio set xpmr debug level",
+ active_usage, NULL, NULL },
+
};
+#endif
/*
* store the callerid components
*/
#if 0
-static void store_callerid(struct chan_usbradio_pvt *o, const char *s)
+static void store_callerid(struct chan_usbradio_pvt *o, char *s)
{
ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
}
#endif
-static void store_rxdemod(struct chan_usbradio_pvt *o, const char *s)
+static void store_rxdemod(struct chan_usbradio_pvt *o, char *s)
{
- if (!strcasecmp(s, "no")) {
+ if (!strcasecmp(s,"no")){
o->rxdemod = RX_AUDIO_NONE;
- } else if (!strcasecmp(s, "speaker")) {
+ }
+ else if (!strcasecmp(s,"speaker")){
o->rxdemod = RX_AUDIO_SPEAKER;
- } else if (!strcasecmp(s, "flat")) {
+ }
+ else if (!strcasecmp(s,"flat")){
o->rxdemod = RX_AUDIO_FLAT;
- } else {
- ast_log(LOG_WARNING, "Unrecognized rxdemod parameter: %s\n", s);
+ }
+ else {
+ ast_log(LOG_WARNING,"Unrecognized rxdemod parameter: %s\n",s);
}
- ast_debug(4, "set rxdemod = %s\n", s);
+ //ast_log(LOG_WARNING, "set rxdemod = %s\n", s);
}
-static void store_txmixa(struct chan_usbradio_pvt *o, const char *s)
+static void store_txmixa(struct chan_usbradio_pvt *o, char *s)
{
- if (!strcasecmp(s, "no"))
+ if (!strcasecmp(s,"no")){
o->txmixa = TX_OUT_OFF;
-
- else if (!strcasecmp(s, "voice"))
+ }
+ else if (!strcasecmp(s,"voice")){
o->txmixa = TX_OUT_VOICE;
- else if (!strcasecmp(s, "tone"))
+ }
+ else if (!strcasecmp(s,"tone")){
o->txmixa = TX_OUT_LSD;
- else if (!strcasecmp(s, "composite"))
+ }
+ else if (!strcasecmp(s,"composite")){
o->txmixa = TX_OUT_COMPOSITE;
- else if (!strcasecmp(s, "auxvoice"))
- o->txmixb = TX_OUT_AUX;
- else
- ast_log(LOG_WARNING, "Unrecognized txmixa parameter: %s\n", s);
+ }
+ else if (!strcasecmp(s,"auxvoice")){
+ o->txmixa = TX_OUT_AUX;
+ }
+ else {
+ ast_log(LOG_WARNING,"Unrecognized txmixa parameter: %s\n",s);
+ }
- ast_debug(4, "set txmixa = %s\n", s);
+ //ast_log(LOG_WARNING, "set txmixa = %s\n", s);
}
-static void store_txmixb(struct chan_usbradio_pvt *o, const char *s)
+static void store_txmixb(struct chan_usbradio_pvt *o, char *s)
{
- if (!strcasecmp(s, "no"))
+ if (!strcasecmp(s,"no")){
o->txmixb = TX_OUT_OFF;
- else if (!strcasecmp(s, "voice"))
+ }
+ else if (!strcasecmp(s,"voice")){
o->txmixb = TX_OUT_VOICE;
- else if (!strcasecmp(s, "tone"))
+ }
+ else if (!strcasecmp(s,"tone")){
o->txmixb = TX_OUT_LSD;
- else if (!strcasecmp(s, "composite"))
+ }
+ else if (!strcasecmp(s,"composite")){
o->txmixb = TX_OUT_COMPOSITE;
- else if (!strcasecmp(s, "auxvoice"))
+ }
+ else if (!strcasecmp(s,"auxvoice")){
o->txmixb = TX_OUT_AUX;
- else
- ast_log(LOG_WARNING, "Unrecognized txmixb parameter: %s\n", s);
+ }
+ else {
+ ast_log(LOG_WARNING,"Unrecognized txmixb parameter: %s\n",s);
+ }
- ast_debug(4, "set txmixb = %s\n", s);
+ //ast_log(LOG_WARNING, "set txmixb = %s\n", s);
}
-
-static void store_rxcdtype(struct chan_usbradio_pvt *o, const char *s)
+/*
+*/
+static void store_rxcdtype(struct chan_usbradio_pvt *o, char *s)
{
- if (!strcasecmp(s, "no"))
+ if (!strcasecmp(s,"no")){
o->rxcdtype = CD_IGNORE;
- else if (!strcasecmp(s, "usb"))
+ }
+ else if (!strcasecmp(s,"usb")){
o->rxcdtype = CD_HID;
- else if (!strcasecmp(s, "dsp"))
+ }
+ else if (!strcasecmp(s,"dsp")){
o->rxcdtype = CD_XPMR_NOISE;
- else if (!strcasecmp(s, "vox"))
+ }
+ else if (!strcasecmp(s,"vox")){
o->rxcdtype = CD_XPMR_VOX;
- else if (!strcasecmp(s, "usbinvert"))
+ }
+ else if (!strcasecmp(s,"usbinvert")){
o->rxcdtype = CD_HID_INVERT;
- else
- ast_log(LOG_WARNING, "Unrecognized rxcdtype parameter: %s\n", s);
+ }
+ else {
+ ast_log(LOG_WARNING,"Unrecognized rxcdtype parameter: %s\n",s);
+ }
- ast_debug(4, "set rxcdtype = %s\n", s);
+ //ast_log(LOG_WARNING, "set rxcdtype = %s\n", s);
}
-
-static void store_rxsdtype(struct chan_usbradio_pvt *o, const char *s)
+/*
+*/
+static void store_rxsdtype(struct chan_usbradio_pvt *o, char *s)
{
- if (!strcasecmp(s, "no") || !strcasecmp(s, "SD_IGNORE"))
+ if (!strcasecmp(s,"no") || !strcasecmp(s,"SD_IGNORE")){
o->rxsdtype = SD_IGNORE;
- else if (!strcasecmp(s, "usb") || !strcasecmp(s, "SD_HID"))
+ }
+ else if (!strcasecmp(s,"usb") || !strcasecmp(s,"SD_HID")){
o->rxsdtype = SD_HID;
- else if (!strcasecmp(s, "usbinvert") || !strcasecmp(s, "SD_HID_INVERT"))
+ }
+ else if (!strcasecmp(s,"usbinvert") || !strcasecmp(s,"SD_HID_INVERT")){
o->rxsdtype = SD_HID_INVERT;
- else if (!strcasecmp(s, "software") || !strcasecmp(s, "SD_XPMR"))
+ }
+ else if (!strcasecmp(s,"software") || !strcasecmp(s,"SD_XPMR")){
o->rxsdtype = SD_XPMR;
- else
- ast_log(LOG_WARNING, "Unrecognized rxsdtype parameter: %s\n", s);
+ }
+ else {
+ ast_log(LOG_WARNING,"Unrecognized rxsdtype parameter: %s\n",s);
+ }
- ast_debug(4, "set rxsdtype = %s\n", s);
+ //ast_log(LOG_WARNING, "set rxsdtype = %s\n", s);
}
-
-static void store_rxgain(struct chan_usbradio_pvt *o, const char *s)
+/*
+*/
+static void store_rxgain(struct chan_usbradio_pvt *o, char *s)
{
float f;
- if (sscanf(s, "%f", &f) == 1)
- o->rxgain = f;
- ast_debug(4, "set rxgain = %f\n", f);
+ sscanf(s,"%f",&f);
+ o->rxgain = f;
+ //ast_log(LOG_WARNING, "set rxgain = %f\n", f);
}
-
-static void store_rxvoiceadj(struct chan_usbradio_pvt *o, const char *s)
+/*
+*/
+static void store_rxvoiceadj(struct chan_usbradio_pvt *o, char *s)
{
float f;
- if (sscanf(s, "%f", &f) == 1)
- o->rxvoiceadj = f;
- ast_debug(4, "set rxvoiceadj = %f\n", f);
+ sscanf(s,"%f",&f);
+ o->rxvoiceadj = f;
+ //ast_log(LOG_WARNING, "set rxvoiceadj = %f\n", f);
}
-
-static void store_rxctcssadj(struct chan_usbradio_pvt *o, const char *s)
+/*
+*/
+static void store_rxctcssadj(struct chan_usbradio_pvt *o, char *s)
{
float f;
- if (sscanf(s, "%f", &f) == 1)
- o->rxctcssadj = f;
- ast_debug(4, "set rxctcssadj = %f\n", f);
+ sscanf(s,"%f",&f);
+ o->rxctcssadj = f;
+ //ast_log(LOG_WARNING, "set rxctcssadj = %f\n", f);
}
-
-static void store_txtoctype(struct chan_usbradio_pvt *o, const char *s)
+/*
+*/
+static void store_txtoctype(struct chan_usbradio_pvt *o, char *s)
{
- if (!strcasecmp(s, "no") || !strcasecmp(s, "TOC_NONE"))
+ if (!strcasecmp(s,"no") || !strcasecmp(s,"TOC_NONE")){
o->txtoctype = TOC_NONE;
- else if (!strcasecmp(s, "phase") || !strcasecmp(s, "TOC_PHASE"))
+ }
+ else if (!strcasecmp(s,"phase") || !strcasecmp(s,"TOC_PHASE")){
o->txtoctype = TOC_PHASE;
- else if (!strcasecmp(s, "notone") || !strcasecmp(s, "TOC_NOTONE"))
+ }
+ else if (!strcasecmp(s,"notone") || !strcasecmp(s,"TOC_NOTONE")){
o->txtoctype = TOC_NOTONE;
- else
- ast_log(LOG_WARNING, "Unrecognized txtoctype parameter: %s\n", s);
-
- ast_debug(4, "set txtoctype = %s\n", s);
-}
-
-static void store_rxctcssfreq(struct chan_usbradio_pvt *o, const char *s)
-{
- float f;
- if (sscanf(s, "%f", &f) == 1)
- o->rxctcssfreq = f;
- ast_debug(4, "set rxctcss = %f\n", f);
-}
-
-static void store_txctcssfreq(struct chan_usbradio_pvt *o, const char *s)
-{
- float f;
- if (sscanf(s, "%f", &f) == 1)
- o->txctcssfreq = f;
- ast_debug(4, "set txctcss = %f\n", f);
+ }
+ else {
+ ast_log(LOG_WARNING,"Unrecognized txtoctype parameter: %s\n",s);
+ }
}
-
-static void tune_txoutput(struct chan_usbradio_pvt *o, int value)
+/*
+*/
+static void tune_txoutput(struct chan_usbradio_pvt *o, int value, int fd)
{
- o->txtestkey = 1;
- o->pmrChan->txPttIn = 1;
-
-#if 0
- /* generate 1KHz tone at 7200 peak */
- o->pmrChan->spsSigGen1->freq = 10000;
- o->pmrChan->spsSigGen1->outputGain = (float)(0.22 * M_Q8);
- o->pmrChan->b.startSpecialTone = 1;
-#endif
-
- TxTestTone(o->pmrChan, 1);
-
+ o->txtestkey=1;
+ o->pmrChan->txPttIn=1;
+ TxTestTone(o->pmrChan, 1); // generate 1KHz tone at 7200 peak
+ if (fd > 0) ast_cli(fd,"Tone output starting on channel %s...\n",o->name);
usleep(5000000);
- /* o->pmrChan->b.stopSpecialTone = 1; */
- usleep(100000);
-
TxTestTone(o->pmrChan, 0);
-
- o->pmrChan->txPttIn = 0;
- o->txtestkey = 0;
+ if (fd > 0) ast_cli(fd,"Tone output ending on channel %s...\n",o->name);
+ o->pmrChan->txPttIn=0;
+ o->txtestkey=0;
}
-
-static void tune_rxinput(struct chan_usbradio_pvt *o)
+/*
+*/
+static void tune_rxinput(int fd, struct chan_usbradio_pvt *o)
{
- const int target = 23000;
- const int tolerance = 2000;
- const int settingmin = 1;
- const int settingstart = 2;
- const int maxtries = 12;
+ const int target=23000;
+ const int tolerance=2000;
+ const int settingmin=1;
+ const int settingstart=2;
+ const int maxtries=12;
float settingmax;
- int setting = 0, tries = 0, tmpdiscfactor, meas;
- int tunetype = 0;
+ int setting=0, tries=0, tmpdiscfactor, meas;
+ int tunetype=0;
settingmax = o->micmax;
- if (o->pmrChan->rxDemod)
- tunetype = 1;
+ if(o->pmrChan->rxDemod)tunetype=1;
+ o->pmrChan->b.tuning=1;
setting = settingstart;
- while (tries < maxtries) {
- setamixer(o->devicenum, MIXER_PARAM_MIC_CAPTURE_VOL, setting, 0);
- setamixer(o->devicenum, MIXER_PARAM_MIC_BOOST, o->rxboostset, 0);
+ ast_cli(fd,"tune rxnoise maxtries=%i, target=%i, tolerance=%i\n",maxtries,target,tolerance);
+
+ while(tries<maxtries)
+ {
+ setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,setting,0);
+ setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0);
+
usleep(100000);
- if (o->rxcdtype == CD_XPMR_VOX || o->rxdemod == RX_AUDIO_SPEAKER) {
- ast_debug(4, "Measure Direct Input\n");
+ if(o->rxcdtype!=CD_XPMR_NOISE || o->rxdemod==RX_AUDIO_SPEAKER)
+ {
+ // printf("Measure Direct Input\n");
o->pmrChan->spsMeasure->source = o->pmrChan->spsRx->source;
- o->pmrChan->spsMeasure->discfactor = 1000;
- o->pmrChan->spsMeasure->enabled = 1;
+ o->pmrChan->spsMeasure->discfactor=2000;
+ o->pmrChan->spsMeasure->enabled=1;
o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
usleep(400000);
- meas = o->pmrChan->spsMeasure->apeak;
- o->pmrChan->spsMeasure->enabled = 0;
- } else {
- ast_debug(4, "Measure HF Noise\n");
- tmpdiscfactor = o->pmrChan->spsRx->discfactor;
- o->pmrChan->spsRx->discfactor = (i16)1000;
- o->pmrChan->spsRx->discounteru = o->pmrChan->spsRx->discounterl = 0;
- o->pmrChan->spsRx->amax = o->pmrChan->spsRx->amin = 0;
+ meas=o->pmrChan->spsMeasure->apeak;
+ o->pmrChan->spsMeasure->enabled=0;
+ }
+ else
+ {
+ // printf("Measure HF Noise\n");
+ tmpdiscfactor=o->pmrChan->spsRx->discfactor;
+ o->pmrChan->spsRx->discfactor=(i16)2000;
+ o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0;
+ o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0;
usleep(200000);
- meas = o->pmrChan->rxRssi;
- o->pmrChan->spsRx->discfactor = tmpdiscfactor;
- o->pmrChan->spsRx->discounteru = o->pmrChan->spsRx->discounterl = 0;
- o->pmrChan->spsRx->amax = o->pmrChan->spsRx->amin = 0;
- }
- if (!meas)
- meas++;
- ast_log(LOG_NOTICE, "tries=%d, setting=%d, meas=%i\n", tries, setting, meas);
-
- if ( meas < (target - tolerance) || meas > (target + tolerance) || tries < 3)
- setting = setting * target / meas;
- else if (tries > 4 && meas > (target - tolerance) && meas < (target + tolerance) )
+ meas=o->pmrChan->rxRssi;
+ o->pmrChan->spsRx->discfactor=tmpdiscfactor;
+ o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0;
+ o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0;
+ }
+ if(!meas)meas++;
+ ast_cli(fd,"tries=%i, setting=%i, meas=%i\n",tries,setting,meas);
+
+ if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
+ setting=setting*target/meas;
+ }
+ else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
+ {
break;
+ }
- if (setting < settingmin)
- setting = settingmin;
- else if (setting > settingmax)
- setting = settingmax;
+ if(setting<settingmin)setting=settingmin;
+ else if(setting>settingmax)setting=settingmax;
tries++;
}
- ast_log(LOG_NOTICE, "DONE tries=%d, setting=%d, meas=%i\n", tries,
- (setting * 1000) / o->micmax, meas);
- if (meas < (target - tolerance) || meas > (target + tolerance))
- ast_log(LOG_NOTICE, "ERROR: RX INPUT ADJUST FAILED.\n");
- else {
- ast_log(LOG_NOTICE, "INFO: RX INPUT ADJUST SUCCESS.\n");
- o->rxmixerset = (setting * 1000) / o->micmax;
+ ast_cli(fd,"DONE tries=%i, setting=%i, meas=%i\n",tries,
+ (setting * 1000) / o->micmax,meas);
+ if( meas<(target-tolerance) || meas>(target+tolerance) ){
+ ast_cli(fd,"ERROR: RX INPUT ADJUST FAILED.\n");
+ }else{
+ ast_cli(fd,"INFO: RX INPUT ADJUST SUCCESS.\n");
+ o->rxmixerset=(setting * 1000) / o->micmax;
}
+ o->pmrChan->b.tuning=0;
}
/*
*/
-static void tune_rxvoice(struct chan_usbradio_pvt *o)
+static void tune_rxvoice(int fd, struct chan_usbradio_pvt *o)
{
- const int target = 7200; /* peak */
- const int tolerance = 360; /* peak to peak */
- const float settingmin = 0.1;
- const float settingmax = 4;
- const float settingstart = 1;
- const int maxtries = 12;
+ const int target=7200; // peak
+ const int tolerance=360; // peak to peak
+ const float settingmin=0.1;
+ const float settingmax=4;
+ const float settingstart=1;
+ const int maxtries=12;
float setting;
- int tries = 0, meas;
-
- ast_log(LOG_NOTICE, "INFO: RX VOICE ADJUST START.\n");
- ast_log(LOG_NOTICE, "target=%d tolerance=%d\n", target, tolerance);
+ int tries=0, meas;
- if (!o->pmrChan->spsMeasure)
- ast_log(LOG_ERROR, "NO MEASURE BLOCK.\n");
+ ast_cli(fd,"INFO: RX VOICE ADJUST START.\n");
+ ast_cli(fd,"target=%i tolerance=%i \n",target,tolerance);
- if (!o->pmrChan->spsMeasure->source || !o->pmrChan->prxVoiceAdjust )
- ast_log(LOG_ERROR, "NO SOURCE OR MEASURE SETTING.\n");
+ o->pmrChan->b.tuning=1;
+ if(!o->pmrChan->spsMeasure)
+ ast_cli(fd,"ERROR: NO MEASURE BLOCK.\n");
- o->pmrChan->spsMeasure->source = o->pmrChan->spsRxOut->sink;
- o->pmrChan->spsMeasure->enabled = 1;
- o->pmrChan->spsMeasure->discfactor = 1000;
+ if(!o->pmrChan->spsMeasure->source || !o->pmrChan->prxVoiceAdjust )
+ ast_cli(fd,"ERROR: NO SOURCE OR MEASURE SETTING.\n");
+ o->pmrChan->spsMeasure->source=o->pmrChan->spsRxOut->sink;
+ o->pmrChan->spsMeasure->enabled=1;
+ o->pmrChan->spsMeasure->discfactor=1000;
+
setting=settingstart;
- ast_debug(4, "ERROR: NO MEASURE BLOCK.\n");
+ // ast_cli(fd,"ERROR: NO MEASURE BLOCK.\n");
- while (tries < maxtries) {
- *(o->pmrChan->prxVoiceAdjust) = setting * M_Q8;
+ while(tries<maxtries)
+ {
+ *(o->pmrChan->prxVoiceAdjust)=setting*M_Q8;
usleep(10000);
o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
usleep(1000000);
meas = o->pmrChan->spsMeasure->apeak;
- ast_log(LOG_NOTICE, "tries=%d, setting=%f, meas=%i\n", tries, setting, meas);
+ ast_cli(fd,"tries=%i, setting=%f, meas=%i\n",tries,setting,meas);
- if (meas < (target - tolerance) || meas > (target + tolerance) || tries < 3)
- setting = setting * target / meas;
- else if (tries > 4 && meas > (target - tolerance) && meas < (target + tolerance))
+ if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
+ setting=setting*target/meas;
+ }
+ else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
+ {
break;
- if (setting < settingmin)
- setting = settingmin;
- else if (setting > settingmax)
- setting = settingmax;
+ }
+ if(setting<settingmin)setting=settingmin;
+ else if(setting>settingmax)setting=settingmax;
tries++;
}
- o->pmrChan->spsMeasure->enabled = 0;
+ o->pmrChan->spsMeasure->enabled=0;
- ast_log(LOG_NOTICE, "DONE tries=%d, setting=%f, meas=%f\n", tries, setting, (float)meas);
- if (meas < (target - tolerance) || meas > (target + tolerance))
- ast_log(LOG_ERROR, "RX VOICE GAIN ADJUST FAILED.\n");
- else {
- ast_log(LOG_NOTICE, "RX VOICE GAIN ADJUST SUCCESS.\n");
- o->rxvoiceadj = setting;
+ ast_cli(fd,"DONE tries=%i, setting=%f, meas=%f\n",tries,setting,(float)meas);
+ if( meas<(target-tolerance) || meas>(target+tolerance) ){
+ ast_cli(fd,"ERROR: RX VOICE GAIN ADJUST FAILED.\n");
+ }else{
+ ast_cli(fd,"INFO: RX VOICE GAIN ADJUST SUCCESS.\n");
+ o->rxvoiceadj=setting;
}
+ o->pmrChan->b.tuning=0;
}
-
-static void tune_rxctcss(struct chan_usbradio_pvt *o)
+/*
+*/
+static void tune_rxctcss(int fd, struct chan_usbradio_pvt *o)
{
- const int target = 4096;
- const int tolerance = 100;
- const float settingmin = 0.1;
- const float settingmax = 4;
- const float settingstart = 1;
- const int maxtries = 12;
+ const int target=2400; // was 4096 pre 20080205
+ const int tolerance=100;
+ const float settingmin=0.1;
+ const float settingmax=8;
+ const float settingstart=1;
+ const int maxtries=12;
float setting;
- int tries = 0, meas;
+ int tries=0, meas;
- ast_log(LOG_NOTICE, "RX CTCSS ADJUST START.\n");
- ast_log(LOG_NOTICE, "target=%d tolerance=%d \n", target, tolerance);
+ ast_cli(fd,"INFO: RX CTCSS ADJUST START.\n");
+ ast_cli(fd,"target=%i tolerance=%i \n",target,tolerance);
- o->pmrChan->spsMeasure->source = o->pmrChan->prxCtcssMeasure;
- o->pmrChan->spsMeasure->discfactor = 400;
- o->pmrChan->spsMeasure->enabled = 1;
+ o->pmrChan->b.tuning=1;
+ o->pmrChan->spsMeasure->source=o->pmrChan->prxCtcssMeasure;
+ o->pmrChan->spsMeasure->discfactor=400;
+ o->pmrChan->spsMeasure->enabled=1;
- setting = settingstart;
+ setting=settingstart;
- while (tries < maxtries) {
- *(o->pmrChan->prxCtcssAdjust) = setting * M_Q8;
+ while(tries<maxtries)
+ {
+ *(o->pmrChan->prxCtcssAdjust)=setting*M_Q8;
usleep(10000);
o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
usleep(500000);
meas = o->pmrChan->spsMeasure->apeak;
- ast_debug(4, "tries=%d, setting=%f, meas=%i\n", tries, setting, meas);
+ ast_cli(fd,"tries=%i, setting=%f, meas=%i\n",tries,setting,meas);
- if (meas < (target - tolerance) || meas > (target + tolerance) || tries < 3)
- setting = setting * target / meas;
- else if (tries > 4 && meas > (target - tolerance) && meas < (target + tolerance))
+ if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
+ setting=setting*target/meas;
+ }
+ else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
+ {
break;
- if (setting < settingmin)
- setting = settingmin;
- else if (setting > settingmax)
- setting = settingmax;
+ }
+ if(setting<settingmin)setting=settingmin;
+ else if(setting>settingmax)setting=settingmax;
tries++;
}
- o->pmrChan->spsMeasure->enabled = 0;
- ast_debug(4, "DONE tries=%d, setting=%f, meas=%f\n", tries, setting, (float)meas);
- if (meas < (target - tolerance) || meas > (target + tolerance))
- ast_log(LOG_ERROR, "RX CTCSS GAIN ADJUST FAILED.\n");
- else {
- ast_log(LOG_NOTICE, "RX CTCSS GAIN ADJUST SUCCESS.\n");
- o->rxctcssadj = setting;
+ o->pmrChan->spsMeasure->enabled=0;
+ ast_cli(fd,"DONE tries=%i, setting=%f, meas=%f\n",tries,setting,(float)meas);
+ if( meas<(target-tolerance) || meas>(target+tolerance) ){
+ ast_cli(fd,"ERROR: RX CTCSS GAIN ADJUST FAILED.\n");
+ }else{
+ ast_cli(fd,"INFO: RX CTCSS GAIN ADJUST SUCCESS.\n");
+ o->rxctcssadj=setting;
}
+ o->pmrChan->b.tuning=0;
}
/*
- this file then is included in chan_usbradio.conf
- #include /etc/asterisk/usbradio_tune.conf
+ after radio tune is performed data is serialized here
*/
static void tune_write(struct chan_usbradio_pvt *o)
{
FILE *fp;
-
- fp = fopen("/etc/asterisk/usbradio_tune.conf", "w");
-
- if (!strcmp(o->name, "dsp"))
- fprintf(fp, "[general]\n");
- else
- fprintf(fp, "[%s]\n", o->name);
-
- fprintf(fp, "; name=%s\n", o->name);
- fprintf(fp, "; devicenum=%d\n", o->devicenum);
-
- fprintf(fp, "rxmixerset=%d\n", o->rxmixerset);
- fprintf(fp, "rxboostset=%d\n", o->rxboostset);
- fprintf(fp, "txmixaset=%d\n", o->txmixaset);
- fprintf(fp, "txmixbset=%d\n", o->txmixbset);
-
- fprintf(fp, "rxvoiceadj=%f\n", o->rxvoiceadj);
- fprintf(fp, "rxctcssadj=%f\n", o->rxctcssadj);
- fprintf(fp, "txctcssadj=%d\n", o->txctcssadj);
-
- fprintf(fp, "rxsquelchadj=%d\n", o->rxsquelchadj);
+ char fname[200];
+
+ snprintf(fname,sizeof(fname) - 1,"/etc/asterisk/usbradio_tune_%s.conf",o->name);
+ fp = fopen(fname,"w");
+
+ fprintf(fp,"[%s]\n",o->name);
+
+ fprintf(fp,"; name=%s\n",o->name);
+ fprintf(fp,"; devicenum=%i\n",o->devicenum);
+ fprintf(fp,"devstr=%s\n",o->devstr);
+ fprintf(fp,"rxmixerset=%i\n",o->rxmixerset);
+ fprintf(fp,"txmixaset=%i\n",o->txmixaset);
+ fprintf(fp,"txmixbset=%i\n",o->txmixbset);
+ fprintf(fp,"rxvoiceadj=%f\n",o->rxvoiceadj);
+ fprintf(fp,"rxctcssadj=%f\n",o->rxctcssadj);
+ fprintf(fp,"txctcssadj=%i\n",o->txctcssadj);
+ fprintf(fp,"rxsquelchadj=%i\n",o->rxsquelchadj);
fclose(fp);
-}
+ if(o->wanteeprom)
+ {
+ ast_mutex_lock(&o->eepromlock);
+ while(o->eepromctl)
+ {
+ ast_mutex_unlock(&o->eepromlock);
+ usleep(10000);
+ ast_mutex_lock(&o->eepromlock);
+ }
+ o->eeprom[EEPROM_RXMIXERSET] = o->rxmixerset;
+ o->eeprom[EEPROM_TXMIXASET] = o->txmixaset;
+ o->eeprom[EEPROM_TXMIXBSET] = o->txmixbset;
+ memcpy(&o->eeprom[EEPROM_RXVOICEADJ],&o->rxvoiceadj,sizeof(float));
+ memcpy(&o->eeprom[EEPROM_RXCTCSSADJ],&o->rxctcssadj,sizeof(float));
+ o->eeprom[EEPROM_TXCTCSSADJ] = o->txctcssadj;
+ o->eeprom[EEPROM_RXSQUELCHADJ] = o->rxsquelchadj;
+ o->eepromctl = 2; /* request a write */
+ ast_mutex_unlock(&o->eepromlock);
+ }
+}
+//
static void mixer_write(struct chan_usbradio_pvt *o)
{
- setamixer(o->devicenum, MIXER_PARAM_MIC_PLAYBACK_SW, 0, 0);
- setamixer(o->devicenum, MIXER_PARAM_MIC_PLAYBACK_VOL, 0, 0);
- setamixer(o->devicenum, MIXER_PARAM_SPKR_PLAYBACK_SW, 1, 0);
- setamixer(o->devicenum, MIXER_PARAM_SPKR_PLAYBACK_VOL,
+ setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_SW,0,0);
+ setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_VOL,0,0);
+ setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_SW,1,0);
+ setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL,
o->txmixaset * o->spkrmax / 1000,
o->txmixbset * o->spkrmax / 1000);
- setamixer(o->devicenum, MIXER_PARAM_MIC_CAPTURE_VOL,
- o->rxmixerset * o->micmax / 1000, 0);
- setamixer(o->devicenum, MIXER_PARAM_MIC_BOOST, o->rxboostset, 0);
- setamixer(o->devicenum, MIXER_PARAM_MIC_CAPTURE_SW, 1, 0);
+ setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,
+ o->rxmixerset * o->micmax / 1000,0);
+ setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0);
+ setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_SW,1,0);
}
/*
adjust dsp multiplier to add resolution to tx level adjustment
@@ -2096,43 +3116,121 @@ static void mixer_write(struct chan_usbradio_pvt *o)
static void mult_set(struct chan_usbradio_pvt *o)
{
- if (o->pmrChan->spsTxOutA) {
+ if(o->pmrChan->spsTxOutA) {
o->pmrChan->spsTxOutA->outputGain =
mult_calc((o->txmixaset * 152) / 1000);
}
- if (o->pmrChan->spsTxOutB) {
+ if(o->pmrChan->spsTxOutB){
o->pmrChan->spsTxOutB->outputGain =
mult_calc((o->txmixbset * 152) / 1000);
}
}
-/*
- * input 0 - 151 outputs are pot and multiplier
- */
+//
+// input 0 - 151 outputs are pot and multiplier
+//
static int mult_calc(int value)
{
- const int multx = M_Q8;
- int pot, mult;
+ const int multx=M_Q8;
+ int pot,mult;
- pot= ((int)(value / 4) * 4) + 2;
- mult = multx - ((multx * (3 - (value % 4))) / (pot + 2));
- return mult;
+ pot=((int)(value/4)*4)+2;
+ mult = multx-( ( multx * (3-(value%4)) ) / (pot+2) );
+ return(mult);
}
-#define pd(x) ast_debug(4, #x" = %d\n", x)
-#define pp(x) ast_debug(4, #x" = %p\n", x)
-#define ps(x) ast_debug(4, #x" = %s\n", x)
-#define pf(x) ast_debug(4, #x" = %f\n", x)
+#define pd(x) {printf(#x" = %d\n",x);}
+#define pp(x) {printf(#x" = %p\n",x);}
+#define ps(x) {printf(#x" = %s\n",x);}
+#define pf(x) {printf(#x" = %f\n",x);}
+
+
+#if 0
+/*
+ do hid output if only requirement is ptt out
+ this give fastest performance with least overhead
+ where gpio inputs are not required.
+*/
+
+static int usbhider(struct chan_usbradio_pvt *o, int opt)
+{
+ unsigned char buf[4];
+ char lastrx, txtmp;
+
+ if(opt)
+ {
+ struct usb_device *usb_dev;
+
+ usb_dev = hid_device_init(o->devstr);
+ if (usb_dev == NULL) {
+ ast_log(LOG_ERROR,"USB HID device not found\n");
+ return -1;
+ }
+ o->usb_handle = usb_open(usb_dev);
+ if (o->usb_handle == NULL) {
+ ast_log(LOG_ERROR,"Not able to open USB device\n");
+ return -1;
+ }
+ if (usb_claim_interface(o->usb_handle,C108_HID_INTERFACE) < 0)
+ {
+ if (usb_detach_kernel_driver_np(o->usb_handle,C108_HID_INTERFACE) < 0) {
+ ast_log(LOG_ERROR,"Not able to detach the USB device\n");
+ return -1;
+ }
+ if (usb_claim_interface(o->usb_handle,C108_HID_INTERFACE) < 0) {
+ ast_log(LOG_ERROR,"Not able to claim the USB device\n");
+ return -1;
+ }
+ }
+
+ memset(buf,0,sizeof(buf));
+ buf[2] = o->hid_gpio_ctl;
+ buf[1] = 0;
+ hid_set_outputs(o->usb_handle,buf);
+ memcpy(bufsave,buf,sizeof(buf));
+
+ buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
+ o->lasttx=0;
+ }
+
+ /* if change in tx state as controlled by xpmr */
+ txtmp=o->pmrChan->txPttOut;
+
+ if (o->lasttx != txtmp)
+ {
+ o->pmrChan->txPttHid=o->lasttx = txtmp;
+ if(o->debuglevel)printf("usbhid: tx set to %d\n",txtmp);
+ buf[o->hid_gpio_loc] = 0;
+ if (!o->invertptt)
+ {
+ if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ }
+ else
+ {
+ if (!txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ }
+ buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
+ hid_set_outputs(o->usb_handle,buf);
+ }
+
+ return(0);
+}
+#endif
/*
*/
static void pmrdump(struct chan_usbradio_pvt *o)
{
t_pmr_chan *p;
+ int i;
- p = o->pmrChan;
+ p=o->pmrChan;
- ast_debug(4, "odump()\n");
+ printf("\nodump()\n");
pd(o->devicenum);
+ ps(o->devstr);
+
+ pd(o->micmax);
+ pd(o->spkrmax);
pd(o->rxdemod);
pd(o->rxcdtype);
@@ -2140,10 +3238,27 @@ static void pmrdump(struct chan_usbradio_pvt *o)
pd(o->txtoctype);
pd(o->rxmixerset);
+ pd(o->rxboostset);
+
pf(o->rxvoiceadj);
pf(o->rxctcssadj);
pd(o->rxsquelchadj);
-
+
+ ps(o->txctcssdefault);
+ ps(o->txctcssfreq);
+
+ pd(o->numrxctcssfreqs);
+ if(o->numrxctcssfreqs>0)
+ {
+ for(i=0;i<o->numrxctcssfreqs;i++)
+ {
+ printf(" %i = %s %s\n",i,o->rxctcss[i],o->txctcss[i]);
+ }
+ }
+
+ pd(o->b.rxpolarity);
+ pd(o->b.txpolarity);
+
pd(o->txprelim);
pd(o->txmixa);
pd(o->txmixb);
@@ -2151,17 +3266,50 @@ static void pmrdump(struct chan_usbradio_pvt *o)
pd(o->txmixaset);
pd(o->txmixbset);
- ast_debug(4, "pmrdump()\n");
+ printf("\npmrdump()\n");
- ast_debug(4, "prxSquelchAdjust=%d\n", *(o->pmrChan->prxSquelchAdjust));
+ pd(p->devicenum);
+
+ printf("prxSquelchAdjust=%i\n",*(o->pmrChan->prxSquelchAdjust));
pd(p->rxCarrierPoint);
pd(p->rxCarrierHyst);
+ pd(*p->prxVoiceAdjust);
+ pd(*p->prxCtcssAdjust);
+
+ pd(p->rxfreq);
+ pd(p->txfreq);
+
pd(p->rxCtcss->relax);
- pf(p->rxCtcssFreq);
- pd(p->rxCtcssIndex);
- pf(p->txCtcssFreq);
+ //pf(p->rxCtcssFreq);
+ pd(p->numrxcodes);
+ if(o->pmrChan->numrxcodes>0)
+ {
+ for(i=0;i<o->pmrChan->numrxcodes;i++)
+ {
+ printf(" %i = %s\n",i,o->pmrChan->pRxCode[i]);
+ }
+ }
+
+ pd(p->txTocType);
+ ps(p->pTxCodeDefault);
+ pd(p->txcodedefaultsmode);
+ pd(p->numtxcodes);
+ if(o->pmrChan->numtxcodes>0)
+ {
+ for(i=0;i<o->pmrChan->numtxcodes;i++)
+ {
+ printf(" %i = %s\n",i,o->pmrChan->pTxCode[i]);
+ }
+ }
+
+ pd(p->b.rxpolarity);
+ pd(p->b.txpolarity);
+ pd(p->b.dcsrxpolarity);
+ pd(p->b.dcstxpolarity);
+ pd(p->b.lsdrxpolarity);
+ pd(p->b.lsdtxpolarity);
pd(p->txMixA);
pd(p->txMixB);
@@ -2170,21 +3318,73 @@ static void pmrdump(struct chan_usbradio_pvt *o)
pd(p->rxCenterSlicerEnable);
pd(p->rxCtcssDecodeEnable);
pd(p->rxDcsDecodeEnable);
+ pd(p->b.ctcssRxEnable);
+ pd(p->b.dcsRxEnable);
+ pd(p->b.lmrRxEnable);
+ pd(p->b.dstRxEnable);
+ pd(p->smode);
pd(p->txHpfEnable);
pd(p->txLimiterEnable);
pd(p->txPreEmpEnable);
pd(p->txLpfEnable);
- if (p->spsTxOutA)
- pd(p->spsTxOutA->outputGain);
- if (p->spsTxOutB)
- pd(p->spsTxOutB->outputGain);
+ if(p->spsTxOutA)pd(p->spsTxOutA->outputGain);
+ if(p->spsTxOutB)pd(p->spsTxOutB->outputGain);
+ pd(p->txPttIn);
+ pd(p->txPttOut);
+
+ pd(p->tracetype);
return;
}
+/*
+ takes data from a chan_usbradio_pvt struct (e.g. o->)
+ and configures the xpmr radio layer
+*/
+static int xpmr_config(struct chan_usbradio_pvt *o)
+{
+ //ast_log(LOG_NOTICE,"xpmr_config()\n");
+
+ TRACEO(1,("xpmr_config()\n"));
+
+ if(o->pmrChan==NULL)
+ {
+ ast_log(LOG_ERROR,"pmr channel structure NULL\n");
+ return 1;
+ }
+
+ o->pmrChan->rxCtcss->relax = o->rxctcssrelax;
+ o->pmrChan->txpower=0;
+ if(o->b.remoted)
+ {
+ o->pmrChan->pTxCodeDefault = o->set_txctcssdefault;
+ o->pmrChan->pRxCodeSrc=o->set_rxctcssfreqs;
+ o->pmrChan->pTxCodeSrc=o->set_txctcssfreqs;
+ o->pmrChan->rxfreq=o->set_rxfreq;
+ o->pmrChan->txfreq=o->set_txfreq;
+ /* printf(" remoted %s %s --> %s \n",o->pmrChan->txctcssdefault,
+ o->pmrChan->txctcssfreq,o->pmrChan->rxctcssfreq); */
+ }
+ else
+ {
+ // set xpmr pointers to source strings
+
+ o->pmrChan->pTxCodeDefault = o->txctcssdefault;
+ o->pmrChan->pRxCodeSrc = o->rxctcssfreqs;
+ o->pmrChan->pTxCodeSrc = o->txctcssfreqs;
+
+ o->pmrChan->rxfreq = o->rxfreq;
+ o->pmrChan->txfreq = o->txfreq;
+ }
+
+ code_string_parse(o->pmrChan);
+ if(o->pmrChan->rxfreq) o->pmrChan->b.reprog=1;
+
+ return 0;
+}
/*
* grab fields from the config file, init the descriptor and open the device.
*/
@@ -2193,175 +3393,318 @@ static struct chan_usbradio_pvt *store_config(struct ast_config *cfg, char *ctg)
struct ast_variable *v;
struct chan_usbradio_pvt *o;
struct ast_config *cfg1;
- struct ast_flags config_flags = { 0 };
-
+ int i;
+ char fname[200];
+#ifdef NEW_ASTERISK
+ struct ast_flags zeroflag = {0};
+#endif
if (ctg == NULL) {
- traceusb1(" store_config() ctg == NULL\n");
+ traceusb1((" store_config() ctg == NULL\n"));
o = &usbradio_default;
ctg = "general";
} else {
- if (!(o = ast_calloc(1, sizeof(*o)))){
- return NULL;
- }
- *o = usbradio_default;
/* "general" is also the default thing */
if (strcmp(ctg, "general") == 0) {
- o->name = ast_strdup("dsp");
- usbradio_active = o->name;
- } else
+ o = &usbradio_default;
+ } else {
+ // ast_log(LOG_NOTICE,"ast_calloc for chan_usbradio_pvt of %s\n",ctg);
+ if (!(o = ast_calloc(1, sizeof(*o))))
+ return NULL;
+ *o = usbradio_default;
o->name = ast_strdup(ctg);
+ if (!usbradio_active)
+ usbradio_active = o->name;
+ }
}
-
+ ast_mutex_init(&o->eepromlock);
strcpy(o->mohinterpret, "default");
- o->micmax = amixer_max(o->devicenum, MIXER_PARAM_MIC_CAPTURE_VOL);
- o->spkrmax = amixer_max(o->devicenum, MIXER_PARAM_SPKR_PLAYBACK_VOL);
/* fill other fields from configuration */
for (v = ast_variable_browse(cfg, ctg); v; v = v->next) {
+ M_START((char *)v->name, (char *)v->value);
/* handle jb conf */
if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
continue;
- CV_START(v->name, v->value);
-
- CV_UINT("frags", o->frags);
- CV_UINT("queuesize", o->queuesize);
- CV_UINT("devicenum", o->devicenum);
- CV_UINT("debug", usbradio_debug);
- CV_BOOL("rxcpusaver", o->rxcpusaver);
- CV_BOOL("txcpusaver", o->txcpusaver);
- CV_BOOL("invertptt", o->invertptt);
- CV_F("rxdemod", store_rxdemod(o, v->value));
- CV_BOOL("txprelim", o->txprelim);;
- CV_F("txmixa", store_txmixa(o, v->value));
- CV_F("txmixb", store_txmixb(o, v->value));
- CV_F("carrierfrom", store_rxcdtype(o, v->value));
- CV_F("rxsdtype", store_rxsdtype(o, v->value));
- CV_F("rxctcssfreq", store_rxctcssfreq(o, v->value));
- CV_F("txctcssfreq", store_txctcssfreq(o, v->value));
- CV_F("rxgain", store_rxgain(o, v->value));
- CV_BOOL("rxboostset", o->rxboostset);
- CV_UINT("rxctcssrelax", o->rxctcssrelax);
- CV_F("txtoctype", store_txtoctype(o, v->value));
- CV_UINT("hdwtype", o->hdwtype);
- CV_UINT("duplex", o->radioduplex);
-
- CV_END;
- }
-
- cfg1 = ast_config_load(config1, config_flags);
- if (!cfg1) {
- o->rxmixerset = 500;
- o->txmixaset = 500;
- o->txmixbset = 500;
- o->rxvoiceadj = 0.5;
- o->rxctcssadj = 0.5;
- o->txctcssadj = 200;
- o->rxsquelchadj = 500;
- ast_log(LOG_WARNING, "File %s not found, using default parameters.\n", config1);
- } else {
- for (v = ast_variable_browse(cfg1, ctg); v; v = v->next) {
+
+#if 0
+ M_BOOL("autoanswer", o->autoanswer)
+ M_BOOL("autohangup", o->autohangup)
+ M_BOOL("overridecontext", o->overridecontext)
+ M_STR("context", o->ctx)
+ M_STR("language", o->language)
+ M_STR("mohinterpret", o->mohinterpret)
+ M_STR("extension", o->ext)
+ M_F("callerid", store_callerid(o, v->value))
+#endif
+ M_UINT("frags", o->frags)
+ M_UINT("queuesize",o->queuesize)
+#if 0
+ M_UINT("devicenum",o->devicenum)
+#endif
+ M_UINT("debug", usbradio_debug)
+ M_BOOL("rxcpusaver",o->rxcpusaver)
+ M_BOOL("txcpusaver",o->txcpusaver)
+ M_BOOL("invertptt",o->invertptt)
+ M_F("rxdemod",store_rxdemod(o,(char *)v->value))
+ M_BOOL("txprelim",o->txprelim);
+ M_F("txmixa",store_txmixa(o,(char *)v->value))
+ M_F("txmixb",store_txmixb(o,(char *)v->value))
+ M_F("carrierfrom",store_rxcdtype(o,(char *)v->value))
+ M_F("rxsdtype",store_rxsdtype(o,(char *)v->value))
+ M_UINT("rxsqvox",o->rxsqvoxadj)
+ M_STR("txctcssdefault",o->txctcssdefault)
+ M_STR("rxctcssfreqs",o->rxctcssfreqs)
+ M_STR("txctcssfreqs",o->txctcssfreqs)
+ M_UINT("rxfreq",o->rxfreq)
+ M_UINT("txfreq",o->txfreq)
+ M_F("rxgain",store_rxgain(o,(char *)v->value))
+ M_BOOL("rxboost",o->rxboostset)
+ M_UINT("rxctcssrelax",o->rxctcssrelax)
+ M_F("txtoctype",store_txtoctype(o,(char *)v->value))
+ M_UINT("hdwtype",o->hdwtype)
+ M_UINT("eeprom",o->wanteeprom)
+ M_UINT("duplex",o->radioduplex)
+ M_UINT("txsettletime",o->txsettletime)
+ M_BOOL("rxpolarity",o->b.rxpolarity)
+ M_BOOL("txpolarity",o->b.txpolarity)
+ M_BOOL("dcsrxpolarity",o->b.dcsrxpolarity)
+ M_BOOL("dcstxpolarity",o->b.dcstxpolarity)
+ M_BOOL("lsdrxpolarity",o->b.lsdrxpolarity)
+ M_BOOL("lsdtxpolarity",o->b.lsdtxpolarity)
+ M_BOOL("loopback",o->b.loopback)
+ M_BOOL("radioactive",o->b.radioactive)
+ M_UINT("rptnum",o->rptnum)
+ M_UINT("idleinterval",o->idleinterval)
+ M_UINT("turnoffs",o->turnoffs)
+ M_UINT("tracetype",o->tracetype)
+ M_UINT("tracelevel",o->tracelevel)
+ M_UINT("area",o->area)
+ M_STR("ukey",o->ukey)
+ M_END(;
+ );
+ }
+
+ o->debuglevel=0;
+
+ if (o == &usbradio_default) /* we are done with the default */
+ return NULL;
+
+ snprintf(fname,sizeof(fname) - 1,config1,o->name);
+#ifdef NEW_ASTERISK
+ cfg1 = ast_config_load(fname,zeroflag);
+#else
+ cfg1 = ast_config_load(fname);
+#endif
+ o->rxmixerset = 500;
+ o->txmixaset = 500;
+ o->txmixbset = 500;
+ o->rxvoiceadj = 0.5;
+ o->rxctcssadj = 0.5;
+ o->txctcssadj = 200;
+ o->rxsquelchadj = 500;
+ o->devstr[0] = 0;
+ if (cfg1) {
+ for (v = ast_variable_browse(cfg1, o->name); v; v = v->next) {
- CV_START(v->name, v->value);
- CV_UINT("rxmixerset", o->rxmixerset);
- CV_UINT("txmixaset", o->txmixaset);
- CV_UINT("txmixbset", o->txmixbset);
- CV_F("rxvoiceadj", store_rxvoiceadj(o, v->value));
- CV_F("rxctcssadj", store_rxctcssadj(o, v->value));
- CV_UINT("txctcssadj", o->txctcssadj);
- CV_UINT("rxsquelchadj", o->rxsquelchadj);
- CV_END;
+ M_START((char *)v->name, (char *)v->value);
+ M_UINT("rxmixerset", o->rxmixerset)
+ M_UINT("txmixaset", o->txmixaset)
+ M_UINT("txmixbset", o->txmixbset)
+ M_F("rxvoiceadj",store_rxvoiceadj(o,(char *)v->value))
+ M_F("rxctcssadj",store_rxctcssadj(o,(char *)v->value))
+ M_UINT("txctcssadj",o->txctcssadj);
+ M_UINT("rxsquelchadj", o->rxsquelchadj)
+ M_STR("devstr", o->devstr)
+ M_END(;
+ );
}
ast_config_destroy(cfg1);
+ } else ast_log(LOG_WARNING,"File %s not found, using default parameters.\n",fname);
+
+ if(o->wanteeprom)
+ {
+ ast_mutex_lock(&o->eepromlock);
+ while(o->eepromctl)
+ {
+ ast_mutex_unlock(&o->eepromlock);
+ usleep(10000);
+ ast_mutex_lock(&o->eepromlock);
+ }
+ o->eepromctl = 1; /* request a load */
+ ast_mutex_unlock(&o->eepromlock);
}
+ /* if our specified one exists in the list */
+ if ((!usb_list_check(o->devstr)) || find_desc_usb(o->devstr))
+ {
+ char *s;
- o->debuglevel = 0;
+ for(s = usb_device_list; *s; s += strlen(s) + 1)
+ {
+ if (!find_desc_usb(s)) break;
+ }
+ if (!*s)
+ {
+ ast_log(LOG_WARNING,"Unable to assign USB device for channel %s\n",o->name);
+ goto error;
+ }
+ ast_log(LOG_NOTICE,"Assigned USB device %s to usbradio channel %s\n",s,o->name);
+ strcpy(o->devstr,s);
+ }
- if (o == &usbradio_default) /* we are done with the default */
- return NULL;
+ i = usb_get_usbdev(o->devstr);
+ if (i < 0)
+ {
+ ast_log(LOG_ERROR,"Not able to find alsa USB device\n");
+ goto error;
+ }
+ o->devicenum = i;
+ o->micmax = amixer_max(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL);
+ o->spkrmax = amixer_max(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL);
o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */
o->dsp = ast_dsp_new();
- if (o->dsp) {
- ast_dsp_set_features(o->dsp, DSP_FEATURE_DIGIT_DETECT);
- ast_dsp_set_digitmode(o->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
+ if (o->dsp)
+ {
+#ifdef NEW_ASTERISK
+ ast_dsp_set_features(o->dsp,DSP_FEATURE_DIGIT_DETECT);
+ ast_dsp_set_digitmode(o->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
+#else
+ ast_dsp_set_features(o->dsp,DSP_FEATURE_DTMF_DETECT);
+ ast_dsp_digitmode(o->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
+#endif
}
- if (o->rxctcssfreq != 0 && o->rxdemod == RX_AUDIO_SPEAKER)
- ast_log(LOG_ERROR, "Incompatable Options o->rxctcssfreq=%f and o->rxdemod=speaker\n", o->rxctcssfreq);
-
- if (o->pmrChan == NULL) {
+ if(o->pmrChan==NULL)
+ {
t_pmr_chan tChan;
- memset(&tChan, 0, sizeof(tChan));
+ // ast_log(LOG_NOTICE,"createPmrChannel() %s\n",o->name);
+ memset(&tChan,0,sizeof(t_pmr_chan));
+
+ tChan.pTxCodeDefault = o->txctcssdefault;
+ tChan.pRxCodeSrc = o->rxctcssfreqs;
+ tChan.pTxCodeSrc = o->txctcssfreqs;
- tChan.rxDemod = o->rxdemod;
- tChan.rxCdType = o->rxcdtype;
+ tChan.rxDemod=o->rxdemod;
+ tChan.rxCdType=o->rxcdtype;
+ tChan.rxSqVoxAdj=o->rxsqvoxadj;
- tChan.txMod = o->txprelim;
+ if (o->txprelim)
+ tChan.txMod = 2;
tChan.txMixA = o->txmixa;
tChan.txMixB = o->txmixb;
- tChan.rxCpuSaver = o->rxcpusaver;
- tChan.txCpuSaver = o->txcpusaver;
+ tChan.rxCpuSaver=o->rxcpusaver;
+ tChan.txCpuSaver=o->txcpusaver;
- tChan.rxCtcssFreq = o->rxctcssfreq;
- tChan.txCtcssFreq = o->txctcssfreq;
+ tChan.b.rxpolarity=o->b.rxpolarity;
+ tChan.b.txpolarity=o->b.txpolarity;
- o->pmrChan = createPmrChannel(&tChan, FRAME_SIZE);
+ tChan.b.dcsrxpolarity=o->b.dcsrxpolarity;
+ tChan.b.dcstxpolarity=o->b.dcstxpolarity;
- o->pmrChan->radioDuplex = o->radioduplex;
+ tChan.b.lsdrxpolarity=o->b.lsdrxpolarity;
+ tChan.b.lsdtxpolarity=o->b.lsdtxpolarity;
- o->pmrChan->rxCpuSaver = o->rxcpusaver;
- o->pmrChan->txCpuSaver = o->txcpusaver;
+ tChan.tracetype=o->tracetype;
+ tChan.tracelevel=o->tracelevel;
+ tChan.rptnum=o->rptnum;
+ tChan.idleinterval=o->idleinterval;
+ tChan.turnoffs=o->turnoffs;
+ tChan.area=o->area;
+ tChan.ukey=o->ukey;
+ tChan.name=o->name;
+
+ o->pmrChan=createPmrChannel(&tChan,FRAME_SIZE);
+
+ o->pmrChan->radioDuplex=o->radioduplex;
+ o->pmrChan->b.loopback=0;
+ o->pmrChan->txsettletime=o->txsettletime;
+ o->pmrChan->rxCpuSaver=o->rxcpusaver;
+ o->pmrChan->txCpuSaver=o->txcpusaver;
*(o->pmrChan->prxSquelchAdjust) =
((999 - o->rxsquelchadj) * 32767) / 1000;
- o->pmrChan->spsRx->outputGain = o->rxvoiceadj*M_Q8;
-
+ *(o->pmrChan->prxVoiceAdjust)=o->rxvoiceadj*M_Q8;
+ *(o->pmrChan->prxCtcssAdjust)=o->rxctcssadj*M_Q8;
+ o->pmrChan->rxCtcss->relax=o->rxctcssrelax;
o->pmrChan->txTocType = o->txtoctype;
- if ((o->txmixa == TX_OUT_LSD) ||
- (o->txmixa == TX_OUT_COMPOSITE) ||
- (o->txmixb == TX_OUT_LSD) ||
- (o->txmixb == TX_OUT_COMPOSITE)) {
- *(o->pmrChan->prxCtcssAdjust) = o->rxctcssadj * M_Q8;
- set_txctcss_level(o);
+ if ( (o->txmixa == TX_OUT_LSD) ||
+ (o->txmixa == TX_OUT_COMPOSITE) ||
+ (o->txmixb == TX_OUT_LSD) ||
+ (o->txmixb == TX_OUT_COMPOSITE))
+ {
+ set_txctcss_level(o);
+ }
+
+ if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
+ (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
+ )
+ {
+ ast_log(LOG_ERROR,"No txvoice output configured.\n");
+ }
+
+ if( o->txctcssfreq[0] &&
+ o->txmixa!=TX_OUT_LSD && o->txmixa!=TX_OUT_COMPOSITE &&
+ o->txmixb!=TX_OUT_LSD && o->txmixb!=TX_OUT_COMPOSITE
+ )
+ {
+ ast_log(LOG_ERROR,"No txtone output configured.\n");
+ }
+
+ if(o->b.radioactive)
+ {
+ // 20080328 sphenke asdf maw !!!
+ // this diagnostic option was working but now appears broken
+ // it's not required for operation so I'll fix it later.
+ //struct chan_usbradio_pvt *ao;
+ //for (ao = usbradio_default.next; ao && ao->name ; ao = ao->next)ao->pmrChan->b.radioactive=0;
+ usbradio_active = o->name;
+ // o->pmrChan->b.radioactive=1;
+ //o->b.radioactive=0;
+ //o->pmrChan->b.radioactive=0;
+ ast_log(LOG_NOTICE,"radio active set to [%s]\n",o->name);
}
-
- o->pmrChan->rxCtcss->relax = o->rxctcssrelax;
-
}
- if ((o->txmixa != TX_OUT_VOICE) && (o->txmixb != TX_OUT_VOICE) &&
- (o->txmixa != TX_OUT_COMPOSITE) && (o->txmixb != TX_OUT_COMPOSITE))
- ast_log(LOG_ERROR, "No txvoice output configured.\n");
-
- if (o->txctcssfreq &&
- o->txmixa != TX_OUT_LSD && o->txmixa != TX_OUT_COMPOSITE &&
- o->txmixb != TX_OUT_LSD && o->txmixb != TX_OUT_COMPOSITE)
- ast_log(LOG_ERROR, "No txtone output configured.\n");
-
- if (o->rxctcssfreq && o->pmrChan->rxCtcssIndex < 0)
- ast_log(LOG_ERROR, "Invalid CTCSS Frequency.\n");
-
- /* RxTestIt(o); */
+ xpmr_config(o);
+ TRACEO(1,("store_config() 120\n"));
mixer_write(o);
+ TRACEO(1,("store_config() 130\n"));
mult_set(o);
+ TRACEO(1,("store_config() 140\n"));
hidhdwconfig(o);
- /* pmrdump(o); */
+ TRACEO(1,("store_config() 200\n"));
+
+#ifndef NEW_ASTERISK
+ if (pipe(o->sndcmd) != 0) {
+ ast_log(LOG_ERROR, "Unable to create pipe\n");
+ goto error;
+ }
+
+ ast_pthread_create_background(&o->sthread, NULL, sound_thread, o);
+#endif
/* link into list of devices */
if (o != &usbradio_default) {
o->next = usbradio_default.next;
usbradio_default.next = o;
}
+ TRACEO(1,("store_config() complete\n"));
return o;
+
+ error:
+ if (o != &usbradio_default)
+ free(o);
+ return NULL;
}
+
#if DEBUG_FILETEST == 1
/*
Test It on a File
@@ -2371,86 +3714,231 @@ int RxTestIt(struct chan_usbradio_pvt *o)
const int numSamples = SAMPLES_PER_BLOCK;
const int numChannels = 16;
- i16 sample, i, ii;
+ i16 sample,i,ii;
i32 txHangTime;
i16 txEnable;
- t_pmr_chan tChan;
+ t_pmr_chan tChan;
t_pmr_chan *pChan;
- FILE *hInput = NULL, *hOutput = NULL, *hOutputTx = NULL;
+ FILE *hInput=NULL, *hOutput=NULL, *hOutputTx=NULL;
- i16 iBuff[numSamples * 2 * 6], oBuff[numSamples];
-
- ast_debug(4, "RxTestIt()\n");
+ i16 iBuff[numSamples*2*6], oBuff[numSamples];
+
+ printf("RxTestIt()\n");
- pChan = o->pmrChan;
- pChan->b.txCapture = 1;
- pChan->b.rxCapture = 1;
+ pChan=o->pmrChan;
+ pChan->b.txCapture=1;
+ pChan->b.rxCapture=1;
txEnable = 0;
- hInput = fopen("/usr/src/xpmr/testdata/rx_in.pcm", "r");
- if (!hInput){
- ast_debug(4, " RxTestIt() File Not Found.\n");
+ hInput = fopen("/usr/src/xpmr/testdata/rx_in.pcm","r");
+ if(!hInput){
+ printf(" RxTestIt() File Not Found.\n");
return 0;
}
- hOutput = fopen("/usr/src/xpmr/testdata/rx_debug.pcm", "w");
+ hOutput = fopen("/usr/src/xpmr/testdata/rx_debug.pcm","w");
- ast_debug(4, " RxTestIt() Working...\n");
+ printf(" RxTestIt() Working...\n");
- while (!feof(hInput)) {
- fread((void *)iBuff, 2, numSamples * 2 * 6, hInput);
+ while(!feof(hInput))
+ {
+ fread((void *)iBuff,2,numSamples*2*6,hInput);
- if (txHangTime)
- txHangTime -= numSamples;
- if (txHangTime < 0)
- txHangTime = 0;
+ if(txHangTime)txHangTime-=numSamples;
+ if(txHangTime<0)txHangTime=0;
- if (pChan->rxCtcss->decode)
- txHangTime = (8000 / 1000 * 2000);
+ if(pChan->rxCtcss->decode)txHangTime=(8000/1000*2000);
- if (pChan->rxCtcss->decode && !txEnable) {
- txEnable = 1;
- /* pChan->inputBlanking = (8000 / 1000 * 200); */
- } else if (!pChan->rxCtcss->decode && txEnable) {
- txEnable = 0;
+ if(pChan->rxCtcss->decode && !txEnable)
+ {
+ txEnable=1;
+ //pChan->inputBlanking=(8000/1000*200);
+ }
+ else if(!pChan->rxCtcss->decode && txEnable)
+ {
+ txEnable=0;
}
- PmrRx(pChan, iBuff, oBuff);
+ PmrRx(pChan,iBuff,oBuff);
- fwrite((void *)pChan->prxDebug, 2, numSamples * numChannels, hOutput);
+ fwrite((void *)pChan->prxDebug,2,numSamples*numChannels,hOutput);
}
- pChan->b.txCapture = 0;
- pChan->b.rxCapture = 0;
+ pChan->b.txCapture=0;
+ pChan->b.rxCapture=0;
- if (hInput)
- fclose(hInput);
- if (hOutput)
- fclose(hOutput);
+ if(hInput)fclose(hInput);
+ if(hOutput)fclose(hOutput);
- ast_debug(4, " RxTestIt() Complete.\n");
+ printf(" RxTestIt() Complete.\n");
return 0;
}
#endif
+#ifdef NEW_ASTERISK
+
+static char *res2cli(int r)
+
+{
+ switch (r)
+ {
+ case RESULT_SUCCESS:
+ return(CLI_SUCCESS);
+ case RESULT_SHOWUSAGE:
+ return(CLI_SHOWUSAGE);
+ default:
+ return(CLI_FAILURE);
+ }
+}
+
+static char *handle_console_key(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "radio key";
+ e->usage = key_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(console_key(a->fd,a->argc,a->argv));
+}
+
+static char *handle_console_unkey(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "radio unkey";
+ e->usage = unkey_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(console_unkey(a->fd,a->argc,a->argv));
+}
+
+static char *handle_radio_tune(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "radio tune";
+ e->usage = radio_tune_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(radio_tune(a->fd,a->argc,a->argv));
+}
+
+static char *handle_radio_debug(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "radio debug";
+ e->usage = radio_tune_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(radio_set_debug(a->fd,a->argc,a->argv));
+}
+
+static char *handle_radio_debug_off(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "radio debug off";
+ e->usage = radio_tune_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(radio_set_debug_off(a->fd,a->argc,a->argv));
+}
+
+static char *handle_radio_active(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "radio active";
+ e->usage = active_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(radio_active(a->fd,a->argc,a->argv));
+}
+
+static char *handle_set_xdebug(struct ast_cli_entry *e,
+ int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "radio set xdebug";
+ e->usage = active_usage;
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+ return res2cli(radio_set_xpmr_debug(a->fd,a->argc,a->argv));
+}
+
+
+static struct ast_cli_entry cli_usbradio[] = {
+ AST_CLI_DEFINE(handle_console_key,"Simulate Rx Signal Present"),
+ AST_CLI_DEFINE(handle_console_unkey,"Simulate Rx Signal Loss"),
+ AST_CLI_DEFINE(handle_radio_tune,"Radio Tune"),
+ AST_CLI_DEFINE(handle_radio_debug,"Radio Debug On"),
+ AST_CLI_DEFINE(handle_radio_debug_off,"Radio Debug Off"),
+ AST_CLI_DEFINE(handle_radio_active,"Change commanded device"),
+ AST_CLI_DEFINE(handle_set_xdebug,"Radio set xpmr debug level")
+};
+
+#endif
+
#include "./xpmr/xpmr.c"
+#ifdef HAVE_XPMRX
+#include "./xpmrx/xpmrx.c"
+#endif
+
/*
*/
static int load_module(void)
{
struct ast_config *cfg = NULL;
char *ctg = NULL;
- struct ast_flags config_flags = { 0 };
+#ifdef NEW_ASTERISK
+ struct ast_flags zeroflag = {0};
+#endif
+
+ if (hid_device_mklist()) {
+ ast_log(LOG_NOTICE, "Unable to make hid list\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ usb_list_check("");
+
+ usbradio_active = NULL;
/* Copy the default jb config over global_jbconf */
memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
/* load config file */
- if (!(cfg = ast_config_load(config, config_flags))) {
+#ifdef NEW_ASTERISK
+ if (!(cfg = ast_config_load(config,zeroflag))) {
+#else
+ if (!(cfg = ast_config_load(config))) {
+#endif
ast_log(LOG_NOTICE, "Unable to load config %s\n", config);
return AST_MODULE_LOAD_DECLINE;
}
@@ -2462,7 +3950,7 @@ static int load_module(void)
ast_config_destroy(cfg);
if (find_desc(usbradio_active) == NULL) {
- ast_log(LOG_NOTICE, "Device %s not found\n", usbradio_active);
+ ast_log(LOG_NOTICE, "radio active device %s not found\n", usbradio_active);
/* XXX we could default to 'dsp' perhaps ? */
/* XXX should cleanup allocated memory etc. */
return AST_MODULE_LOAD_FAILURE;
@@ -2491,8 +3979,7 @@ static int unload_module(void)
for (o = usbradio_default.next; o; o = o->next) {
ast_log(LOG_WARNING, "destroyPmrChannel() called\n");
- if (o->pmrChan)
- destroyPmrChannel(o->pmrChan);
+ if(o->pmrChan)destroyPmrChannel(o->pmrChan);
#if DEBUG_CAPTURES == 1
if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; }
@@ -2504,8 +3991,13 @@ static int unload_module(void)
#endif
close(o->sounddev);
- if (o->dsp)
- ast_dsp_free(o->dsp);
+#ifndef NEW_ASTERISK
+ if (o->sndcmd[0] > 0) {
+ close(o->sndcmd[0]);
+ close(o->sndcmd[1]);
+ }
+#endif
+ if (o->dsp) ast_dsp_free(o->dsp);
if (o->owner)
ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD);
if (o->owner) /* XXX how ??? */
diff --git a/channels/xpmr/sinetabx.h b/channels/xpmr/sinetabx.h
index 4c4574850..14d8f9f4c 100755
--- a/channels/xpmr/sinetabx.h
+++ b/channels/xpmr/sinetabx.h
@@ -4,16 +4,26 @@
* All Rights Reserved. Copyright (C)2007, Xelatec, LLC
*
* 20070808 1235 Steven Henke, W9SH, sph@xelatec.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This version may be optionally licenced under the GNU LGPL licence.
*
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
+ * A license has been granted to Digium (via disclaimer) for the use of
+ * this code.
*
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
*/
/*! \file
@@ -24,11 +34,11 @@
*/
#ifndef XPMR_SINETABX_H
-#define XPMR_SINETABX_H 1
+#define XPMR_SINETABX_H 1
#define SAMPLES_PER_SINE 256
-const i16 sinetablex[]={
+static const i16 sinetablex[]={
0, // 0
804, // 1
1608, // 2
diff --git a/channels/xpmr/xpmr.c b/channels/xpmr/xpmr.c
index a799ca9d3..5e1b0f59d 100755
--- a/channels/xpmr/xpmr.c
+++ b/channels/xpmr/xpmr.c
@@ -1,19 +1,30 @@
/*
* xpmr.c - Xelatec Private Mobile Radio Processes
- *
+ *
* All Rights Reserved. Copyright (C)2007, Xelatec, LLC
- *
+ *
* 20070808 1235 Steven Henke, W9SH, sph@xelatec.com
*
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This version may be optionally licenced under the GNU LGPL licence.
+ *
+ * A license has been granted to Digium (via disclaimer) for the use of
+ * this code.
*
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
+ * 20080118 0800 sph@xelatec.com major fixes and features
*/
/*! \file
@@ -36,29 +47,419 @@
FIR = Finite Impulse Response (Filter)
IIR = Infinite Impulse Response (Filter)
*/
+
+// XPMR_FILE_VERSION(__FILE__, "$Revision$")
+
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
+#include <sys/io.h>
#include <fcntl.h>
#include <sys/time.h>
#include <stdlib.h>
#include <errno.h>
-
+
#include "xpmr.h"
#include "xpmr_coef.h"
#include "sinetabx.h"
static i16 pmrChanIndex=0; // count of created pmr instances
+//static i16 pmrSpsIndex=0;
+
+#if (DTX_PROG == 1) || XPMR_PPTP == 1
+static int ppdrvdev=0;
+#endif
+
+/*
+ Trace Routines
+*/
+void strace(i16 point, t_sdbg *sdbg, i16 index, i16 value)
+{
+ // make dbg_trace buffer in structure
+ if(!sdbg->mode || sdbg->point[point]<0){
+ return;
+ } else {
+ sdbg->buffer[(index*XPMR_DEBUG_CHANS) + sdbg->point[point]] = value;
+ }
+}
+/*
+
+*/
+void strace2(t_sdbg *sdbg)
+{
+ int i;
+ for(i=0;i<XPMR_DEBUG_CHANS;i++)
+ {
+ if(sdbg->source[i])
+ {
+ int ii;
+ for(ii=0;ii<SAMPLES_PER_BLOCK;ii++)
+ {
+ sdbg->buffer[ii*XPMR_DEBUG_CHANS + i] = sdbg->source[i][ii];
+ }
+ }
+ }
+}
+#if XPMR_PPTP == 1
+/*
+ Hardware Trace Signals via the PC Parallel Port
+*/
+void pptp_init (void)
+{
+ if (ppdrvdev == 0)
+ ppdrvdev = open("/dev/ppdrv_device", 0);
+
+ if (ppdrvdev < 0)
+ {
+ ast_log(LOG_ERROR, "open /dev/ppdrv_ppdrvdev returned %i\n",ppdrvdev);
+ exit(0);
+ }
+ ioctl(ppdrvdev, PPDRV_IOC_PINMODE_OUT, DTX_CLK | DTX_DATA | DTX_ENABLE | DTX_TXPWR | DTX_TX | DTX_TP1 | DTX_TP2);
+ ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_CLK | DTX_DATA | DTX_ENABLE | DTX_TXPWR | DTX_TX | DTX_TP1 | DTX_TP2);
+}
+/*
+*/
+void pptp_write(i16 bit, i16 state)
+{
+ if(bit==0)
+ {
+ if(state)ioctl(ppdrvdev,PPDRV_IOC_PINSET,DTX_TP1);
+ else ioctl(ppdrvdev,PPDRV_IOC_PINCLEAR,DTX_TP1);
+ }
+ else
+ {
+ if(state)ioctl(ppdrvdev,PPDRV_IOC_PINSET,DTX_TP2);
+ else ioctl(ppdrvdev,PPDRV_IOC_PINCLEAR,DTX_TP2);
+ }
+}
+#endif
+/*
+ take source string allocate and copy
+ copy is modified, delimiters are replaced with zeros to mark
+ end of string
+ count set pointers
+ string_parse( char *src, char *dest, char **sub)
+*/
+i16 string_parse(char *src, char **dest, char ***ptrs)
+{
+ char *p,*pd;
+ char *ptstr[1000];
+ i16 i, slen, numsub;
+
+ TRACEJ(2,("string_parse(%s)\n",src));
+
+ slen=strlen(src);
+ TRACEJ(2,(" source len = %i\n",slen));
+
+ pd=*dest;
+ if(pd) free(pd);
+ pd=calloc(slen+1,1);
+ memcpy(pd,src,slen);
+ *dest=pd;
+
+ p=0;
+ numsub=0;
+ for(i=0;i<slen+1;i++)
+ {
+ TRACEJ(5,(" pd[%i] = %c\n",i,pd[i]));
+
+ if( p==0 && pd[i]!=',' && pd[i]!=' ' )
+ {
+ p=&(pd[i]);
+ }
+ else if(pd[i]==',' || pd[i]==0 )
+ {
+ ptstr[numsub]=p;
+ pd[i]=0;
+ p=0;
+ numsub++;
+ }
+ }
+
+ for(i=0;i<numsub;i++)
+ {
+ TRACEJ(5,(" ptstr[%i] = %p %s\n",i,ptstr[i],ptstr[i]));
+ }
+
+ if(*ptrs)free(*ptrs);
+ *ptrs=calloc(numsub,4);
+ for(i=0;i<numsub;i++)
+ {
+ (*ptrs)[i]=ptstr[i];
+ TRACEJ(5,(" %i = %s\n",i,(*ptrs)[i]));
+ }
+ TRACEJ(5,("string_parse()=%i\n\n",numsub));
+
+ return numsub;
+}
+/*
+ the parent program defines
+ pRxCodeSrc and pTxCodeSrc string pointers to the list of codes
+ pTxCodeDefault the default Tx Code.
+
+*/
+i16 code_string_parse(t_pmr_chan *pChan)
+{
+ i16 i, ii, hit, ti;
+ char *p;
+ float f, maxctcsstxfreq;
+
+ t_pmr_sps *pSps;
+ i16 maxctcssindex;
+
+ TRACEF(1,("code_string_parse(%i)\n",0));
+ TRACEF(1,("pChan->pRxCodeSrc %s \n",pChan->pRxCodeSrc));
+ TRACEF(1,("pChan->pTxCodeSrc %s \n",pChan->pTxCodeSrc));
+ TRACEF(1,("pChan->pTxCodeDefault %s \n",pChan->pTxCodeDefault));
+
+ //printf("code_string_parse() %s / %s / %s / %s \n",pChan->name, pChan->pTxCodeDefault,pChan->pTxCodeSrc,pChan->pRxCodeSrc);
+
+ maxctcssindex=CTCSS_NULL;
+ maxctcsstxfreq=CTCSS_NULL;
+ pChan->txctcssdefault_index=CTCSS_NULL;
+ pChan->txctcssdefault_value=CTCSS_NULL;
+
+ pChan->b.ctcssRxEnable=pChan->b.ctcssTxEnable=0;
+ pChan->b.dcsRxEnable=pChan->b.dcsTxEnable=0;
+ pChan->b.lmrRxEnable=pChan->b.lmrTxEnable=0;
+ pChan->b.mdcRxEnable=pChan->b.mdcTxEnable=0;
+ pChan->b.dstRxEnable=pChan->b.dstTxEnable=0;
+ pChan->b.p25RxEnable=pChan->b.p25TxEnable=0;
+
+ if(pChan->spsLsdGen){
+ pChan->spsLsdGen->enabled=0;
+ pChan->spsLsdGen->state=0;
+ }
+
+ TRACEF(1,("code_string_parse(%i) 05\n",0));
+
+ pChan->numrxcodes = string_parse( pChan->pRxCodeSrc, &(pChan->pRxCodeStr), &(pChan->pRxCode));
+ pChan->numtxcodes = string_parse( pChan->pTxCodeSrc, &(pChan->pTxCodeStr), &(pChan->pTxCode));
+
+ if(pChan->numrxcodes!=pChan->numtxcodes)printf("ERROR: numrxcodes != numtxcodes \n");
+
+ pChan->rxCtcss->enabled=0;
+ pChan->rxCtcss->gain=1*M_Q8;
+ pChan->rxCtcss->limit=8192;
+ pChan->rxCtcss->input=pChan->pRxLsdLimit;
+ pChan->rxCtcss->decode=CTCSS_NULL;
+
+ pChan->rxCtcss->testIndex=0;
+ if(!pChan->rxCtcss->testIndex)pChan->rxCtcss->testIndex=3;
+
+ pChan->rxctcssfreq[0]=0; // decode now CTCSS_RXONLY
+
+ for(i=0;i<CTCSS_NUM_CODES;i++)
+ {
+ pChan->rxctcss[i]=0;
+ pChan->txctcss[i]=0;
+ pChan->rxCtcssMap[i]=CTCSS_NULL;
+ }
+
+ TRACEF(1,("code_string_parse(%i) 10\n",0));
+
+ #ifdef XPMRX_H
+ xpmrx(pChan,XXO_LSDCODEPARSE);
+ #endif
+
+ // Do Receive Codes String
+ for(i=0;i<pChan->numrxcodes;i++)
+ {
+ i16 ii,ri,ti;
+ float f;
+
+ p=pChan->pStr=pChan->pRxCode[i];
+
+ #ifdef HAVE_XPMRX
+ if(!xpmrx(pChan,XXO_LSDCODEPARSE_1))
+ #endif
+ {
+ sscanf(p,"%f",&f);
+ ri=CtcssFreqIndex(f);
+ if(ri>maxctcssindex)maxctcssindex=ri;
+
+ sscanf(pChan->pTxCode[i],"%f",&f);
+ ti=CtcssFreqIndex(f);
+ if(f>maxctcsstxfreq)maxctcsstxfreq=f;
+
+ if(ri>CTCSS_NULL && ti>CTCSS_NULL)
+ {
+ pChan->b.ctcssRxEnable=pChan->b.ctcssTxEnable=1;
+ pChan->rxCtcssMap[ri]=ti;
+ pChan->numrxctcssfreqs++;
+ TRACEF(1,("pChan->rxctcss[%i]=%s pChan->rxCtcssMap[%i]=%i\n",i,pChan->rxctcss[i],ri,ti));
+ }
+ else if(ri>CTCSS_NULL && f==0)
+ {
+ pChan->b.ctcssRxEnable=1;
+ pChan->rxCtcssMap[ri]=CTCSS_RXONLY;
+ pChan->numrxctcssfreqs++;
+ TRACEF(1,("pChan->rxctcss[%i]=%s pChan->rxCtcssMap[%i]=%i RXONLY\n",i,pChan->rxctcss[i],ri,ti));
+ }
+ else
+ {
+ pChan->numrxctcssfreqs=0;
+ for(ii=0;ii<CTCSS_NUM_CODES;ii++) pChan->rxCtcssMap[ii]=CTCSS_NULL;
+ TRACEF(1,("WARNING: Invalid Channel code detected and ignored. %i %s %s \n",i,pChan->pRxCode[i],pChan->pTxCode[i]));
+ }
+ }
+ }
+
+ TRACEF(1,("code_string_parse() CTCSS Init Struct %i %i\n",pChan->b.ctcssRxEnable,pChan->b.ctcssTxEnable));
+ if(pChan->b.ctcssRxEnable)
+ {
+ pChan->rxHpfEnable=1;
+ pChan->spsRxLsdNrz->enabled=pChan->rxCenterSlicerEnable=1;
+ pChan->rxCtcssDecodeEnable=1;
+ pChan->rxCtcss->enabled=1;
+ }
+ else
+ {
+ pChan->rxHpfEnable=1;
+ pChan->spsRxLsdNrz->enabled=pChan->rxCenterSlicerEnable=0;
+ pChan->rxCtcssDecodeEnable=0;
+ pChan->rxCtcss->enabled=0;
+ }
+
+ TRACEF(1,("code_string_parse() CTCSS Init Decoders \n"));
+ for(i=0;i<CTCSS_NUM_CODES;i++)
+ {
+ t_tdet *ptdet;
+ ptdet=&(pChan->rxCtcss->tdet[i]);
+ ptdet->counterFactor=coef_ctcss_div[i];
+ ptdet->state=1;
+ ptdet->setpt=(M_Q15*0.041); // 0.069
+ ptdet->hyst =(M_Q15*0.0130);
+ ptdet->binFactor=(M_Q15*0.135); // was 0.140
+ ptdet->fudgeFactor=8;
+ }
+
+
+ // DEFAULT TX CODE
+ TRACEF(1,("code_string_parse() Default Tx Code %s \n",pChan->pTxCodeDefault));
+ pChan->txcodedefaultsmode=SMODE_NULL;
+ p=pChan->pStr=pChan->pTxCodeDefault;
+
+ #ifdef HAVE_XPMRX
+ if(!lsd_code_parse(pChan,3))
+ #endif
+ {
+ sscanf(p,"%f",&f);
+ ti=CtcssFreqIndex(f);
+ if(f>maxctcsstxfreq)maxctcsstxfreq=f;
+
+ if(ti>CTCSS_NULL)
+ {
+ pChan->b.ctcssTxEnable=1;
+ pChan->txctcssdefault_index=ti;
+ pChan->txctcssdefault_value=f;
+ pChan->spsSigGen0->freq=f*10;
+ pChan->txcodedefaultsmode=SMODE_CTCSS;
+ TRACEF(1,("code_string_parse() Tx Default CTCSS = %s %i %f\n",p,ti,f));
+ }
+ }
+
+
+ // set x for maximum length and just change pointers
+ TRACEF(1,("code_string_parse() Filter Config \n"));
+ pSps=pChan->spsTxLsdLpf;
+ if(pSps->x)free(pSps->x);
+ if(maxctcsstxfreq>203.5)
+ {
+ pSps->ncoef=taps_fir_lpf_250_9_66;
+ pSps->size_coef=2;
+ pSps->coef=(void*)coef_fir_lpf_250_9_66;
+ pSps->nx=taps_fir_lpf_250_9_66;
+ pSps->size_x=2;
+ pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
+ pSps->calcAdjust=gain_fir_lpf_250_9_66;
+ TRACEF(1,("code_string_parse() Tx Filter Freq High\n"));
+ }
+ else
+ {
+ pSps->ncoef=taps_fir_lpf_215_9_88;
+ pSps->size_coef=2;
+ pSps->coef=(void*)coef_fir_lpf_215_9_88;
+ pSps->nx=taps_fir_lpf_215_9_88;
+ pSps->size_x=2;
+ pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
+ pSps->calcAdjust=gain_fir_lpf_215_9_88;
+ TRACEF(1,("code_string_parse() Tx Filter Freq Low\n"));
+ }
+
+ // CTCSS Rx Decoder Low Pass Filter
+ hit=0;
+ ii= CtcssFreqIndex(203.5);
+ for(i=ii;i<CTCSS_NUM_CODES;i++)
+ {
+ if(pChan->rxCtcssMap[i]>CTCSS_NULL)hit=1;
+ }
+
+ pSps=pChan->spsRxLsd;
+ if(pSps->x)free(pSps->x);
+ if(hit)
+ {
+ pSps->ncoef=taps_fir_lpf_250_9_66;
+ pSps->size_coef=2;
+ pSps->coef=(void*)coef_fir_lpf_250_9_66;
+ pSps->nx=taps_fir_lpf_250_9_66;
+ pSps->size_x=2;
+ pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
+ pSps->calcAdjust=gain_fir_lpf_250_9_66;
+ TRACEF(1,("code_string_parse() Rx Filter Freq High\n"));
+ }
+ else
+ {
+ pSps->ncoef=taps_fir_lpf_215_9_88;
+ pSps->size_coef=2;
+ pSps->coef=(void*)coef_fir_lpf_215_9_88;
+ pSps->nx=taps_fir_lpf_215_9_88;
+ pSps->size_x=2;
+ pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
+ pSps->calcAdjust=gain_fir_lpf_215_9_88;
+ TRACEF(1,("code_string_parse() Rx Filter Freq Low\n"));
+ }
+
+ if(pChan->b.ctcssRxEnable || pChan->b.dcsRxEnable || pChan->b.lmrRxEnable)
+ {
+ pChan->rxCenterSlicerEnable=1;
+ pSps->enabled=1;
+ }
+ else
+ {
+ pChan->rxCenterSlicerEnable=0;
+ pSps->enabled=0;
+ }
+
+ #if XPMR_DEBUG0 == 1
+ TRACEF(2,("code_string_parse() ctcssRxEnable = %i \n",pChan->b.ctcssRxEnable));
+ TRACEF(2,(" ctcssTxEnable = %i \n",pChan->b.ctcssTxEnable));
+ TRACEF(2,(" dcsRxEnable = %i \n",pChan->b.dcsRxEnable));
+ TRACEF(2,(" lmrRxEnable = %i \n",pChan->b.lmrRxEnable));
+ TRACEF(2,(" txcodedefaultsmode = %i \n",pChan->txcodedefaultsmode));
+ for(i=0;i<CTCSS_NUM_CODES;i++)
+ {
+ TRACEF(2,("rxCtcssMap[%i] = %i \n",i,pChan->rxCtcssMap[i]));
+ }
+ #endif
+
+ #ifdef HAVE_XPMRX
+ lsd_code_parse(pChan,5);
+ #endif
+ TRACEF(1,("code_string_parse(%i) end\n",0));
+
+ return 0;
+}
/*
Convert a Frequency in Hz to a zero based CTCSS Table index
*/
i16 CtcssFreqIndex(float freq)
{
- i16 i,hit=-1;
+ i16 i,hit=CTCSS_NULL;
for(i=0;i<CTCSS_NUM_CODES;i++){
if(freq==freq_ctcss[i])hit=i;
@@ -66,15 +467,15 @@ i16 CtcssFreqIndex(float freq)
return hit;
}
/*
- pmr_rx_frontend
+ pmr_rx_frontend
Takes a block of data and low pass filters it.
Determines the amplitude of high frequency noise for carrier detect.
Decimates input data to change the rate.
*/
-i16 pmr_rx_frontend(t_pmr_sps *mySps)
+i16 pmr_rx_frontend(t_pmr_sps *mySps)
{
#define DCgainBpfNoise 65536
-
+
i16 samples,iOutput, *input, *output, *noutput;
i16 *x, *coef, *coef2;
i32 i, naccum, outputGain, calcAdjust;
@@ -83,7 +484,7 @@ i16 pmr_rx_frontend(t_pmr_sps *mySps)
i16 amax, amin, apeak, discounteru, discounterl, discfactor;
i16 decimator, decimate, doNoise;
- TRACEX(("pmr_rx_frontend()\n"));
+ TRACEJ(5,("pmr_rx_frontend()\n"));
if(!mySps->enabled)return(1);
@@ -112,12 +513,12 @@ i16 pmr_rx_frontend(t_pmr_sps *mySps)
compOut=mySps->compOut;
samples=mySps->nSamples*decimate;
- x=mySps->x;
+ x=mySps->x;
iOutput=0;
if(mySps->parentChan->rxCdType!=CD_XPMR_VOX)doNoise=1;
else doNoise=0;
-
+
for(i=0;i<samples;i++)
{
i16 n;
@@ -127,14 +528,14 @@ i16 pmr_rx_frontend(t_pmr_sps *mySps)
x[n] = x[n-1];
x[0] = input[i*2];
-
+
--decimator;
if(decimator<=0)
{
decimator=decimate;
-
- y=0;
+
+ y=0;
for(n=0; n<nx; n++)
y += coef[n] * x[n];
@@ -153,9 +554,9 @@ i16 pmr_rx_frontend(t_pmr_sps *mySps)
naccum=0;
for(n=0; n<nx; n++)
naccum += coef_fir_bpf_noise_1[n] * x[n];
-
+
naccum /= DCgainBpfNoise;
-
+
if(naccum>amax)
{
amax=naccum;
@@ -177,33 +578,33 @@ i16 pmr_rx_frontend(t_pmr_sps *mySps)
discounterl=discfactor;
amin=(i32)((amin*32700)/32768);
}
-
+
apeak=(amax-amin)/2;
-
+
} // if doNoise
}
if(doNoise)
{
((t_pmr_chan *)(mySps->parentChan))->rxRssi=apeak;
-
+
if(apeak>setpt || (compOut&&(apeak>(setpt-hyst)))) compOut=1;
else compOut=0;
mySps->compOut=compOut;
mySps->amax=amax;
- mySps->amin=amin;
+ mySps->amin=amin;
mySps->apeak=apeak;
mySps->discounteru=discounteru;
- mySps->discounterl=discounterl;
+ mySps->discounterl=discounterl;
}
return 0;
}
-/*
+/*
pmr general purpose fir
works on a block of samples
*/
-i16 pmr_gp_fir(t_pmr_sps *mySps)
+i16 pmr_gp_fir(t_pmr_sps *mySps)
{
i32 nsamples,inputGain,outputGain,calcAdjust;
i16 *input, *output;
@@ -214,7 +615,7 @@ i16 pmr_gp_fir(t_pmr_sps *mySps)
i16 decimator, decimate, interpolate;
i16 numChanOut, selChanOut, mixOut, monoOut;
- TRACEX(("pmr_gp_fir() %i\n",mySps->enabled));
+ TRACEJ(5,("pmr_gp_fir() %i %i\n",mySps->index, mySps->enabled));
if(!mySps->enabled)return(1);
@@ -227,7 +628,7 @@ i16 pmr_gp_fir(t_pmr_sps *mySps)
x = mySps->x;
nx = mySps->nx;
coef = mySps->coef;
-
+
decimator = mySps->decimator;
decimate = mySps->decimate;
interpolate = mySps->interpolate;
@@ -243,11 +644,11 @@ i16 pmr_gp_fir(t_pmr_sps *mySps)
monoOut = mySps->monoOut;
amax=mySps->amax;
- amin=mySps->amin;
+ amin=mySps->amin;
discfactor=mySps->discfactor;
- hyst=mySps->hyst;
- setpt=mySps->setpt;
+ hyst=mySps->hyst;
+ setpt=mySps->setpt;
nsamples=mySps->nSamples;
if(mySps->option==3)
@@ -270,21 +671,21 @@ i16 pmr_gp_fir(t_pmr_sps *mySps)
int ix;
int64_t y=0;
-
+
if(decimate<0)
{
- decimator=decimate;
+ decimator=decimate;
}
for(ix=0;ix<interpolate;ix++)
{
- i16 n;
+ i16 n;
y=0;
-
+
for(n=nx-1; n>0; n--)
x[n] = x[n-1];
x[0] = (input[i]*inputGain)/M_Q8;
-
+
#if 0
--decimator;
if(decimator<=0)
@@ -292,7 +693,7 @@ i16 pmr_gp_fir(t_pmr_sps *mySps)
decimator=decimate;
for(n=0; n<nx; n++)
y += coef[n] * x[n];
- y /= (outputGain*3);
+ y /= (outputGain*3);
output[ii++]=y;
}
#else
@@ -300,13 +701,13 @@ i16 pmr_gp_fir(t_pmr_sps *mySps)
y += coef[n] * x[n];
y=((y/calcAdjust)*outputGain)/M_Q8;
-
+
if(mixOut){
if(monoOut){
output[(ii*2)]=output[(ii*2)+1]+=y;
}
else{
- output[(ii*numChanOut)+selChanOut]+=y;
+ output[(ii*numChanOut)+selChanOut]+=y;
}
}
else{
@@ -336,7 +737,7 @@ i16 pmr_gp_fir(t_pmr_sps *mySps)
discounteru=discfactor;
amax=(i32)((amax*32700)/32768);
}
-
+
if(accum<amin)
{
amin=accum;
@@ -347,9 +748,9 @@ i16 pmr_gp_fir(t_pmr_sps *mySps)
discounterl=discfactor;
amin=(i32)((amin*32700)/32768);
}
-
+
apeak = (i32)(amax-amin)/2;
-
+
if(apeak>setpt)compOut=1;
else if(compOut&&(apeak<(setpt-hyst)))compOut=0;
}
@@ -358,13 +759,13 @@ i16 pmr_gp_fir(t_pmr_sps *mySps)
mySps->decimator = decimator;
mySps->amax=amax;
- mySps->amin=amin;
- mySps->apeak=apeak;
+ mySps->amin=amin;
+ mySps->apeak=apeak;
mySps->discounteru=discounteru;
- mySps->discounterl=discounterl;
-
+ mySps->discounterl=discounterl;
+
mySps->compOut=compOut;
-
+
return 0;
}
/*
@@ -382,7 +783,7 @@ i16 gp_inte_00(t_pmr_sps *mySps)
i32 state00;
i16 coeff00, coeff01;
- TRACEX(("gp_inte_00() %i\n",mySps->enabled));
+ TRACEJ(5,("gp_inte_00() %i\n",mySps->enabled));
if(!mySps->enabled)return(1);
input = mySps->source;
@@ -447,7 +848,7 @@ i16 gp_diff(t_pmr_sps *mySps)
x0=x[0];
- TRACEX(("gp_diff()\n"));
+ TRACEJ(5,("gp_diff()\n"));
for (i=0;i<npoints;i++)
{
@@ -455,7 +856,11 @@ i16 gp_diff(t_pmr_sps *mySps)
x0 = input[i];
temp1 = input[i] * a0;
y0 = (temp0 + temp1)/calcAdjust;
- output[i]=(y0*outputGain)/M_Q8;
+ y0 =(y0*outputGain)/M_Q8;
+
+ if(y0>32766)y0=32766;
+ else if(y0<-32766)y0=-32766;
+ output[i]=y0;
}
x[0]=x0;
@@ -484,10 +889,11 @@ i16 CenterSlicer(t_pmr_sps *mySps)
i32 discounterl; // amplitude detector integrator discharge counter lower
i32 discfactor; // amplitude detector integrator discharge factor
- TRACEX(("CenterSlicer() %i\n",mySps->enabled));
+ TRACEJ(5,("CenterSlicer() %i\n",mySps->enabled));
+ if(!mySps->enabled)return(1);
input = mySps->source;
- output = mySps->sink;
+ output = mySps->sink; // limited output
buff = mySps->buff;
npoints=mySps->nSamples;
@@ -532,27 +938,34 @@ i16 CenterSlicer(t_pmr_sps *mySps)
uhit=1;
}
}
-
- if(--discounteru<=0 && amax>0)
+ #if 0
+ if((discounteru-=1)<=0 && amax>amin)
{
- amax--;
+ if((amax-=10)<amin)amax=amin;
uhit=1;
}
-
- if(--discounterl<=0 && amin<0)
+
+ if((discounterl-=1)<=0 && amin<amax)
{
- amin++;
+ if((amin+=10)>amax)amin=amax;
lhit=1;
}
-
- if(uhit)discounteru=discfactor;
- if(lhit)discounterl=discfactor;
-
+ if(uhit)discounteru=discfactor;
+ if(lhit)discounterl=discfactor;
+
+ #else
+
+ if((amax-=discfactor)<amin)amax=amin;
+ if((amin+=discfactor)>amax)amin=amax;
+
+ #endif
+
apeak = (amax-amin)/2;
center = (amax+amin)/2;
accum = accum - center;
- output[i]=accum;
-
+
+ output[i]=accum; // sink output unlimited/centered.
+
// do limiter function
if(accum>inputGainB)accum=inputGainB;
else if(accum<-inputGainB)accum=-inputGainB;
@@ -560,7 +973,13 @@ i16 CenterSlicer(t_pmr_sps *mySps)
#if XPMR_DEBUG0 == 1
#if 0
- mySps->debugBuff0[i]=center;
+ mySps->parentChan->pRxLsdCen[i]=center; // trace center ref
+ #else
+ static i32 tfx=0;
+ if((tfx++/8)&1) // trace min/max levels
+ mySps->parentChan->pRxLsdCen[i]=amax;
+ else
+ mySps->parentChan->pRxLsdCen[i]=amin;
#endif
#if 0
if(mySps->parentChan->frameCountRx&0x01) mySps->parentChan->prxDebug1[i]=amax;
@@ -599,7 +1018,7 @@ i16 MeasureBlock(t_pmr_sps *mySps)
i32 discounterl; // amplitude detector integrator discharge counter lower
i32 discfactor; // amplitude detector integrator discharge factor
- TRACEX(("MeasureBlock() %i\n",mySps->enabled));
+ TRACEJ(5,("MeasureBlock() %i\n",mySps->enabled));
if(!mySps->enabled)return 1;
@@ -657,7 +1076,7 @@ i16 MeasureBlock(t_pmr_sps *mySps)
apeak = (i32)(amax-amin)/2;
if(output)output[i]=apeak;
}
-
+
mySps->amax=amax;
mySps->amin=amin;
mySps->apeak=apeak;
@@ -665,7 +1084,7 @@ i16 MeasureBlock(t_pmr_sps *mySps)
mySps->discounterl=discounterl;
if(apeak>=setpt) mySps->compOut=1;
else mySps->compOut=0;
-
+
//TRACEX((" -MeasureBlock()=%i\n",mySps->apeak));
return 0;
}
@@ -701,7 +1120,7 @@ i16 SoftLimiter(t_pmr_sps *mySps)
amax=(setpt*124)/128;
amin=-amax;
- TRACEX(("SoftLimiter() %i %i %i) \n",amin, amax,setpt));
+ TRACEJ(5,("SoftLimiter() %i %i %i) \n",amin, amax,setpt));
for(i=0;i<npoints;i++)
{
@@ -745,15 +1164,17 @@ i16 SigGen(t_pmr_sps *mySps)
i32 ph;
i16 i,outputgain,waveform,numChanOut,selChanOut;
- i32 accum;
-
- TRACEX(("SigGen(%i) \n",mySps->option));
+ i32 accum;
+
+ t_pmr_chan *pChan;
+ pChan=mySps->parentChan;
+ TRACEC(5,("SigGen(%i %i %i)\n",mySps->option,mySps->enabled,mySps->state));
if(!mySps->freq ||!mySps->enabled)return 0;
outputgain=mySps->outputGain;
waveform=0;
- numChanOut=mySps->numChanOut;
+ numChanOut=mySps->numChanOut;
selChanOut=mySps->selChanOut;
if(mySps->option==1)
@@ -762,8 +1183,8 @@ i16 SigGen(t_pmr_sps *mySps)
mySps->state=1;
mySps->discfactor=
(SAMPLES_PER_SINE*mySps->freq*PH_FRACT_FACT)/mySps->sampleRate/10;
-
- TRACEX((" SigGen() discfactor = %i\n",mySps->discfactor));
+
+ TRACEF(5,(" SigGen() discfactor = %i\n",mySps->discfactor));
if(mySps->discounterl)mySps->state=2;
}
else if(mySps->option==2)
@@ -772,7 +1193,7 @@ i16 SigGen(t_pmr_sps *mySps)
// phase shift request
mySps->option=0;
mySps->state=2;
- mySps->discounterl=CTCSS_TURN_OFF_TIME-(2*MS_PER_FRAME); //
+ mySps->discounterl=CTCSS_TURN_OFF_TIME-(2*MS_PER_FRAME); //
mySps->discounteru = \
(mySps->discounteru + (((SAMPLES_PER_SINE*shiftfactor)/360)*PH_FRACT_FACT)) % (SAMPLES_PER_SINE*PH_FRACT_FACT);
@@ -838,7 +1259,7 @@ i16 SigGen(t_pmr_sps *mySps)
/*
adder/mixer
takes existing buffer and adds source buffer to destination buffer
- sink buffer = (sink buffer * gain) + source buffer
+ sink buffer = (sink buffer * gain) + source buffer
*/
i16 pmrMixer(t_pmr_sps *mySps)
{
@@ -849,7 +1270,9 @@ i16 pmrMixer(t_pmr_sps *mySps)
i16 discounteru,discounterl,amax,amin,setpt,discfactor;
i16 npoints,uhit,lhit,apeak,measPeak;
- TRACEX(("pmrMixer()\n"));
+ t_pmr_chan *pChan;
+ pChan=mySps->parentChan;
+ TRACEF(5,("pmrMixer()\n"));
input = mySps->source;
inputB = mySps->sourceB;
@@ -858,7 +1281,7 @@ i16 pmrMixer(t_pmr_sps *mySps)
inputGain=mySps->inputGain;
inputGainB=mySps->inputGainB;
outputGain=mySps->outputGain;
-
+
amax=mySps->amax;
amin=mySps->amin;
setpt=mySps->setpt;
@@ -871,7 +1294,7 @@ i16 pmrMixer(t_pmr_sps *mySps)
for(i=0;i<npoints;i++)
{
- accum = ((input[i]*inputGain)/M_Q8) +
+ accum = ((input[i]*inputGain)/M_Q8) +
((inputB[i]*inputGainB)/M_Q8);
accum=(accum*outputGain)/M_Q8;
@@ -879,7 +1302,7 @@ i16 pmrMixer(t_pmr_sps *mySps)
if(measPeak){
lhit=uhit=0;
-
+
if(accum>amax){
amax=accum;
uhit=1;
@@ -896,20 +1319,20 @@ i16 pmrMixer(t_pmr_sps *mySps)
uhit=1;
}
}
-
+
if(--discounteru<=0 && amax>0){
amax--;
uhit=1;
}
-
+
if(--discounterl<=0 && amin<0){
amin++;
lhit=1;
}
-
- if(uhit)discounteru=discfactor;
+
+ if(uhit)discounteru=discfactor;
if(lhit)discounterl=discfactor;
- }
+ }
}
if(measPeak){
@@ -920,19 +1343,21 @@ i16 pmrMixer(t_pmr_sps *mySps)
mySps->discounteru=discounteru;
mySps->discounterl=discounterl;
}
-
+
return 0;
}
/*
- DelayLine
+ DelayLine
*/
i16 DelayLine(t_pmr_sps *mySps)
{
i16 *input, *output, *buff;
i16 i, npoints,buffsize,inindex,outindex;
- TRACEX((" DelayLine() %i\n",mySps->enabled));
-
+ t_pmr_chan *pChan;
+ pChan=mySps->parentChan;
+ TRACEF(5,(" DelayLine() %i\n",mySps->enabled));
+
input = mySps->source;
output = mySps->sink;
buff = (i16*)(mySps->buff);
@@ -946,7 +1371,7 @@ i16 DelayLine(t_pmr_sps *mySps)
{
inindex %= buffsize;
outindex %= buffsize;
-
+
buff[inindex]=input[i];
output[i]=buff[outindex];
inindex++;
@@ -959,25 +1384,27 @@ i16 DelayLine(t_pmr_sps *mySps)
/*
Continuous Tone Coded Squelch (CTCSS) Detector
*/
-i16 ctcss_detect(t_pmr_chan *pmrChan)
+i16 ctcss_detect(t_pmr_chan *pChan)
{
- i16 i,points2do, points=0, *pInput, hit, thit,relax;
- i16 tnum, tmp, indexWas=0, indexNow, gain, peakwas=0, diffpeak;
+ i16 i,points2do,*pInput,hit,thit,relax;
+ i16 tnum, tmp,indexNow,gain,diffpeak;
i16 difftrig;
- i16 lasttv0=0, lasttv1=0, lasttv2=0, tv0, tv1, tv2, indexDebug;
+ i16 tv0,tv1,tv2,tv3,indexDebug;
+ i16 points=0;
+ i16 indexWas=0;
- TRACEX(("ctcss_detect(%p) %i %i %i %i\n",pmrChan,
- pmrChan->rxCtcss->enabled,
- pmrChan->rxCtcssIndex,
- pmrChan->rxCtcss->testIndex,
- pmrChan->rxCtcss->decode));
+ TRACEF(5,("ctcss_detect(%p) %i %i %i %i\n",pChan,
+ pChan->rxCtcss->enabled,
+ 0,
+ pChan->rxCtcss->testIndex,
+ pChan->rxCtcss->decode));
- if(!pmrChan->rxCtcss->enabled)return(1);
+ if(!pChan->rxCtcss->enabled)return(1);
+
+ relax = pChan->rxCtcss->relax;
+ pInput = pChan->rxCtcss->input;
+ gain = pChan->rxCtcss->gain;
- relax = pmrChan->rxCtcss->relax;
- pInput = pmrChan->rxCtcss->input;
- gain = pmrChan->rxCtcss->gain;
-
if(relax) difftrig=(-0.1*M_Q15);
else difftrig=(-0.05*M_Q15);
@@ -992,35 +1419,32 @@ i16 ctcss_detect(t_pmr_chan *pmrChan)
i16 fudgeFactor;
i16 binFactor;
- //TRACEX((" ctcss_detect() tnum=%i %i\n",tnum,pmrChan->rxCtcssMap[tnum]));
+ TRACEF(6,(" ctcss_detect() tnum=%i %i\n",tnum,pChan->rxCtcssMap[tnum]));
+ //if(tnum==14)printf("ctcss_detect() %i %i %i\n",tnum,pChan->rxCtcssMap[tnum], pChan->rxCtcss->decode );
- if( (pmrChan->rxCtcssMap[tnum] < 0) ||
- (pmrChan->rxCtcss->decode>=0 && (tnum!= pmrChan->rxCtcss->decode)) ||
- (!pmrChan->rxCtcss->multiFreq && (tnum!= pmrChan->rxCtcssIndex))
+ if( (pChan->rxCtcssMap[tnum]==CTCSS_NULL) ||
+ (pChan->rxCtcss->decode>CTCSS_NULL && (tnum!= pChan->rxCtcss->decode))
)
continue;
- //TRACEX((" ctcss_detect() tnum=%i\n",tnum));
+ TRACEF(6,(" ctcss_detect() tnum=%i\n",tnum));
- ptdet=&(pmrChan->rxCtcss->tdet[tnum]);
+ ptdet=&(pChan->rxCtcss->tdet[tnum]);
indexDebug=0;
- points=points2do=pmrChan->nSamplesRx;
+ points=points2do=pChan->nSamplesRx;
fudgeFactor=ptdet->fudgeFactor;
binFactor=ptdet->binFactor;
while(ptdet->counter < (points2do*CTCSS_SCOUNT_MUL))
{
- //TRACEX((" ctcss_detect() - inner loop\n"));
tmp=(ptdet->counter/CTCSS_SCOUNT_MUL)+1;
ptdet->counter-=(tmp*CTCSS_SCOUNT_MUL);
points2do-=tmp;
indexNow=points-points2do;
-
- ptdet->counter += ptdet->counterFactor;
- accum = pInput[indexNow-1]; // dude's major bug fix!
+ ptdet->counter += ptdet->counterFactor;
- peakwas=ptdet->peak;
+ accum = pInput[indexNow-1]; // duuuude's major bug fix!
ptdet->z[ptdet->zIndex]+=
(((accum - ptdet->z[ptdet->zIndex])*binFactor)/M_Q15);
@@ -1037,7 +1461,7 @@ i16 ctcss_detect(t_pmr_chan *pmrChan)
static const i16 a1=-13723;
i32 temp0,temp1;
i16 x0;
-
+
//differentiate
x0=ptdet->zd;
temp0 = x0 * a1;
@@ -1053,7 +1477,7 @@ i16 ctcss_detect(t_pmr_chan *pmrChan)
else if(ptdet->dvu)ptdet->dvu--;
tmp=ptdet->setpt;
- if(pmrChan->rxCtcss->decode==tnum)
+ if(pChan->rxCtcss->decode==tnum)
{
if(relax)tmp=(tmp*55)/100;
else tmp=(tmp*80)/100;
@@ -1063,54 +1487,67 @@ i16 ctcss_detect(t_pmr_chan *pmrChan)
{
if(ptdet->decode<(fudgeFactor*32))ptdet->decode++;
}
- else if(pmrChan->rxCtcss->decode==tnum)
+ else if(pChan->rxCtcss->decode==tnum)
{
if(ptdet->peak > ptdet->hyst)ptdet->decode--;
- else if(relax) ptdet->decode--;
- else ptdet->decode-=4;
+ else if(relax) ptdet->decode--;
+ else ptdet->decode-=4;
}
else
{
ptdet->decode=0;
}
- if((pmrChan->rxCtcss->decode==tnum) && !relax && (ptdet->dvu > (0.00075*M_Q15)))
+ if((pChan->rxCtcss->decode==tnum) && !relax && (ptdet->dvu > (0.00075*M_Q15)))
{
ptdet->decode=0;
ptdet->z[0]=ptdet->z[1]=ptdet->z[2]=ptdet->z[3]=ptdet->dvu=0;
- //printf("ctcss_detect() turnoff code!\n");
+ TRACEF(4,("ctcss_detect() turnoff detected by dvdt for tnum = %i.\n",tnum));
}
- if(ptdet->decode<0 || !pmrChan->rxCarrierDetect)ptdet->decode=0;
-
- if(ptdet->decode>=fudgeFactor)thit=tnum;
+ if(ptdet->decode<0 || !pChan->rxCarrierDetect)ptdet->decode=0;
- #if XPMR_DEBUG0 == 1
- //if(thit>=0 && thit==tnum)
- // printf(" ctcss_detect() %i %i %i %i \n",tnum,ptdet->peak,ptdet->setpt,ptdet->hyst);
-
- // tv0=accum;
- tv0=ptdet->peak;
- tv1=diffpeak;
- tv2=ptdet->dvu;
-
- //tv1=ptdet->zi*100;
- while(indexDebug<indexNow)
+ if(ptdet->decode>=fudgeFactor)
{
- if(indexDebug==0)lasttv0=ptdet->pDebug0[points-1];
- if(ptdet->pDebug0)ptdet->pDebug0[indexDebug]=lasttv0;
+ thit=tnum;
+ if(pChan->rxCtcss->decode!=tnum)
+ {
+ ptdet->zd=ptdet->dvu=ptdet->dvd=0;
+ }
+ }
- if(indexDebug==0)lasttv1=ptdet->pDebug1[points-1];
- if(ptdet->pDebug1)ptdet->pDebug1[indexDebug]=lasttv1;
+ #if XPMR_DEBUG0 == 1
+ if(thit>=0 && thit==tnum)
+ TRACEF(6,(" ctcss_detect() %i %i %i %i \n",tnum,ptdet->peak,ptdet->setpt,ptdet->hyst));
- if(indexDebug==0)lasttv2=ptdet->pDebug2[points-1];
- if(ptdet->pDebug2)ptdet->pDebug2[indexDebug]=lasttv2;
+ if(ptdet->pDebug0)
+ {
+ tv0=ptdet->peak;
+ tv1=ptdet->decode;
+ tv2=tmp;
+ tv3=ptdet->dvu*32;
+
+ if(indexDebug==0)
+ {
+ ptdet->lasttv0=ptdet->pDebug0[points-1];
+ ptdet->lasttv1=ptdet->pDebug1[points-1];
+ ptdet->lasttv2=ptdet->pDebug2[points-1];
+ ptdet->lasttv3=ptdet->pDebug3[points-1];
+ }
- indexDebug++;
+ while(indexDebug<indexNow)
+ {
+ ptdet->pDebug0[indexDebug]=ptdet->lasttv0;
+ ptdet->pDebug1[indexDebug]=ptdet->lasttv1;
+ ptdet->pDebug2[indexDebug]=ptdet->lasttv2;
+ ptdet->pDebug3[indexDebug]=ptdet->lasttv3;
+ indexDebug++;
+ }
+ ptdet->lasttv0=tv0;
+ ptdet->lasttv1=tv1;
+ ptdet->lasttv2=tv2;
+ ptdet->lasttv3=tv3;
}
- lasttv0=tv0;
- lasttv1=tv1;
- lasttv2=tv2*100;
#endif
indexWas=indexNow;
ptdet->zIndex=(++ptdet->zIndex)%4;
@@ -1120,36 +1557,40 @@ i16 ctcss_detect(t_pmr_chan *pmrChan)
#if XPMR_DEBUG0 == 1
for(i=indexWas;i<points;i++)
{
- if(ptdet->pDebug0)ptdet->pDebug0[i]=lasttv0;
- if(ptdet->pDebug1)ptdet->pDebug1[i]=lasttv1;
- if(ptdet->pDebug2)ptdet->pDebug2[i]=lasttv2;
+ ptdet->pDebug0[i]=ptdet->lasttv0;
+ ptdet->pDebug1[i]=ptdet->lasttv1;
+ ptdet->pDebug2[i]=ptdet->lasttv2;
+ ptdet->pDebug3[i]=ptdet->lasttv3;
}
#endif
}
//TRACEX((" ctcss_detect() thit %i\n",thit));
- if(pmrChan->rxCtcss->BlankingTimer>0)pmrChan->rxCtcss->BlankingTimer-=points;
- if(pmrChan->rxCtcss->BlankingTimer<0)pmrChan->rxCtcss->BlankingTimer=0;
+ if(pChan->rxCtcss->BlankingTimer>0)pChan->rxCtcss->BlankingTimer-=points;
+ if(pChan->rxCtcss->BlankingTimer<0)pChan->rxCtcss->BlankingTimer=0;
- if(thit>=0 && pmrChan->rxCtcss->decode<0 && !pmrChan->rxCtcss->BlankingTimer)
+ if(thit>CTCSS_NULL && pChan->rxCtcss->decode<=CTCSS_NULL && !pChan->rxCtcss->BlankingTimer)
{
- pmrChan->rxCtcss->decode=thit;
+ pChan->rxCtcss->decode=thit;
+ sprintf(pChan->rxctcssfreq,"%.1f",freq_ctcss[thit]);
+ TRACEC(1,("ctcss decode %i %.1f\n",thit,freq_ctcss[thit]));
}
- else if(thit<0 && pmrChan->rxCtcss->decode>=0)
+ else if(thit<=CTCSS_NULL && pChan->rxCtcss->decode>CTCSS_NULL)
{
- pmrChan->rxCtcss->BlankingTimer=SAMPLE_RATE_NETWORK/5;
- pmrChan->rxCtcss->decode=-1;
-
+ pChan->rxCtcss->BlankingTimer=SAMPLE_RATE_NETWORK/5;
+ pChan->rxCtcss->decode=CTCSS_NULL;
+ strcpy(pChan->rxctcssfreq,"0");
+ TRACEC(1,("ctcss decode NULL\n"));
for(tnum=0;tnum<CTCSS_NUM_CODES;tnum++)
{
t_tdet *ptdet=NULL;
- ptdet=&(pmrChan->rxCtcss->tdet[tnum]);
+ ptdet=&(pChan->rxCtcss->tdet[tnum]);
ptdet->decode=0;
ptdet->z[0]=ptdet->z[1]=ptdet->z[2]=ptdet->z[3]=0;
}
}
- //TRACEX((" ctcss_detect() thit %i %i\n",thit,pmrChan->rxCtcss->decode));
+ //TRACEX((" ctcss_detect() thit %i %i\n",thit,pChan->rxCtcss->decode));
return(0);
}
/*
@@ -1161,6 +1602,7 @@ static i16 TxTestTone(t_pmr_chan *pChan, i16 function)
{
pChan->spsSigGen1->enabled=1;
pChan->spsSigGen1->option=1;
+ pChan->spsSigGen1->outputGain=(.23125*M_Q8); // to match *99 level
pChan->spsTx->source=pChan->spsSigGen1->sink;
}
else
@@ -1169,7 +1611,7 @@ static i16 TxTestTone(t_pmr_chan *pChan, i16 function)
}
return 0;
}
-/*
+/*
assumes:
sampling rate is 48KS/s
samples are all 16 bits
@@ -1178,36 +1620,37 @@ static i16 TxTestTone(t_pmr_chan *pChan, i16 function)
t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
{
i16 i, *inputTmp;
-
t_pmr_chan *pChan;
t_pmr_sps *pSps;
t_dec_ctcss *pDecCtcss;
- t_tdet *ptdet;
- TRACEX(("createPmrChannel(%p,%i)\n",tChan,numSamples));
+ TRACEJ(1,("createPmrChannel(%p,%i)\n",tChan,numSamples));
pChan = (t_pmr_chan *)calloc(sizeof(t_pmr_chan),1);
-
if(pChan==NULL)
{
printf("createPmrChannel() failed\n");
return(NULL);
}
-
- pChan->nSamplesRx=numSamples;
- pChan->nSamplesTx=numSamples;
+
+ #if XPMR_PPTP == 1
+ pptp_init();
+ #endif
pChan->index=pmrChanIndex++;
+ pChan->nSamplesTx=pChan->nSamplesRx=numSamples;
- for(i=0;i<CTCSS_NUM_CODES;i++)
- {
- pChan->rxCtcssMap[i]=-1;
- }
+ pDecCtcss = (t_dec_ctcss *)calloc(sizeof(t_dec_ctcss),1);
+ pChan->rxCtcss=pDecCtcss;
+ pChan->rxctcssfreq[0]=0;
- pChan->rxCtcssIndex=-1;
+ #ifdef HAVE_XPMRX
+ if(tChan->rptnum>=LSD_CHAN_MAX)tChan->rptnum=0;
+ #endif
if(tChan==NULL)
{
+ printf("createPmrChannel() WARNING: NULL tChan!\n");
pChan->rxNoiseSquelchEnable=0;
pChan->rxHpfEnable=0;
pChan->rxDeEmpEnable=0;
@@ -1218,13 +1661,10 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pChan->rxCarrierPoint = 17000;
pChan->rxCarrierHyst = 2500;
- pChan->rxCtcssFreq=103.5;
-
pChan->txHpfEnable=0;
pChan->txLimiterEnable=0;
pChan->txPreEmpEnable=0;
pChan->txLpfEnable=1;
- pChan->txCtcssFreq=103.5;
pChan->txMixA=TX_OUT_VOICE;
pChan->txMixB=TX_OUT_LSD;
}
@@ -1234,49 +1674,66 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pChan->rxCdType=tChan->rxCdType;
pChan->rxSquelchPoint = tChan->rxSquelchPoint;
pChan->rxCarrierHyst = 3000;
- pChan->rxCtcssFreq=tChan->rxCtcssFreq;
+ pChan->rxSqVoxAdj=tChan->rxSqVoxAdj;
- for(i=0;i<CTCSS_NUM_CODES;i++)
- pChan->rxCtcssMap[i]=tChan->rxCtcssMap[i];
-
pChan->txMod=tChan->txMod;
- pChan->txHpfEnable=1;
+ pChan->txHpfEnable=1;
pChan->txLpfEnable=1;
- pChan->txCtcssFreq=tChan->txCtcssFreq;
+
+ pChan->pTxCodeDefault=tChan->pTxCodeDefault;
+ pChan->pRxCodeSrc=tChan->pRxCodeSrc;
+ pChan->pTxCodeSrc=tChan->pTxCodeSrc;
+
pChan->txMixA=tChan->txMixA;
pChan->txMixB=tChan->txMixB;
pChan->radioDuplex=tChan->radioDuplex;
+ pChan->area=tChan->area;
+ pChan->rptnum=tChan->rptnum;
+ pChan->idleinterval=tChan->idleinterval;
+ pChan->turnoffs=tChan->turnoffs;
+ pChan->b.rxpolarity=tChan->b.rxpolarity;
+ pChan->b.txpolarity=tChan->b.txpolarity;
+ pChan->b.dcsrxpolarity=tChan->b.dcsrxpolarity;
+ pChan->b.dcstxpolarity=tChan->b.dcstxpolarity;
+ pChan->b.lsdrxpolarity=tChan->b.lsdrxpolarity;
+ pChan->b.lsdtxpolarity=tChan->b.lsdtxpolarity;
+
+ pChan->txsettletime=tChan->txsettletime;
+ pChan->tracelevel=tChan->tracelevel;
+ pChan->tracetype=tChan->tracetype;
+ pChan->ukey=tChan->ukey;
+ pChan->name=tChan->name;
}
- TRACEX(("misc settings \n"));
- if(pChan->rxCdType==CD_XPMR_NOISE){
- pChan->rxNoiseSquelchEnable=1;
- }
+ pChan->txHpfEnable=1;
+ pChan->txLpfEnable=1;
- if(pChan->rxDemod==RX_AUDIO_FLAT){
- pChan->rxHpfEnable=1;
- pChan->rxDeEmpEnable=1;
- }
+ if(pChan->rxCdType==CD_XPMR_NOISE) pChan->rxNoiseSquelchEnable=1;
+
+ if(pChan->rxDemod==RX_AUDIO_FLAT) pChan->rxDeEmpEnable=1;
pChan->rxCarrierPoint=(pChan->rxSquelchPoint*32767)/100;
pChan->rxCarrierHyst = 3000; //pChan->rxCarrierPoint/15;
-
+
pChan->rxDcsDecodeEnable=0;
- if(pChan->rxCtcssFreq!=0){
+ if(pChan->b.ctcssRxEnable || pChan->b.dcsRxEnable || pChan->b.lmrRxEnable)
+ {
pChan->rxHpfEnable=1;
pChan->rxCenterSlicerEnable=1;
pChan->rxCtcssDecodeEnable=1;
- pChan->rxCtcssIndex=CtcssFreqIndex(pChan->rxCtcssFreq);
}
if(pChan->txMod){
pChan->txPreEmpEnable=1;
pChan->txLimiterEnable=1;
}
-
- TRACEX(("calloc buffers \n"));
+
+ pChan->dd.option=9;
+ dedrift(pChan);
+
+ TRACEF(1,("calloc buffers \n"));
pChan->pRxDemod = calloc(numSamples,2);
pChan->pRxNoise = calloc(numSamples,2);
@@ -1287,8 +1744,8 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pChan->pRxCtcss = calloc(numSamples,2);
pChan->pRxDcTrack = calloc(numSamples,2);
pChan->pRxLsdLimit = calloc(numSamples,2);
-
-
+
+ pChan->pTxInput = calloc(numSamples,2);
pChan->pTxBase = calloc(numSamples,2);
pChan->pTxHpf = calloc(numSamples,2);
pChan->pTxPreEmp = calloc(numSamples,2);
@@ -1298,13 +1755,20 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pChan->pTxComposite = calloc(numSamples,2);
pChan->pSigGen0 = calloc(numSamples,2);
pChan->pSigGen1 = calloc(numSamples,2);
+
+ pChan->prxMeasure = calloc(numSamples,2);
- pChan->pTxCode = calloc(numSamples,2);
pChan->pTxOut = calloc(numSamples,2*2*6); // output buffer
-
+
+#ifdef HAVE_XPMRX
+ pChan->pLsdEnc = calloc(sizeof(t_encLsd),1);
+#endif
+
#if XPMR_DEBUG0 == 1
- pChan->pTxPttIn = calloc(numSamples,2);
- pChan->pTxPttOut = calloc(numSamples,2);
+ TRACEF(1,("configure tracing\n"));
+
+ pChan->pTstTxOut = calloc(numSamples,2);
+ pChan->pRxLsdCen = calloc(numSamples,2);
pChan->prxDebug0 = calloc(numSamples,2);
pChan->prxDebug1 = calloc(numSamples,2);
pChan->prxDebug2 = calloc(numSamples,2);
@@ -1314,41 +1778,175 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pChan->ptxDebug2 = calloc(numSamples,2);
pChan->ptxDebug3 = calloc(numSamples,2);
pChan->pNull = calloc(numSamples,2);
- for(i=0;i<numSamples;i++)pChan->pNull[i]=((i%(numSamples/2))*8000)-4000;
- #endif
- TRACEX(("create ctcss\n"));
+ for(i=0;i<numSamples;i++)pChan->pNull[i]=((i%(numSamples/2))*8000)-4000;
- pDecCtcss = (t_dec_ctcss *)calloc(sizeof(t_dec_ctcss),1);
-
- pChan->rxCtcss=pDecCtcss;
- pDecCtcss->enabled=1;
- pDecCtcss->gain=1*M_Q8;
- pDecCtcss->limit=8192;
- pDecCtcss->input=pChan->pRxLsdLimit;
- pDecCtcss->testIndex=pChan->rxCtcssIndex;
- if(!pDecCtcss->testIndex)pDecCtcss->testIndex=1;
- pChan->rxCtcssMap[pChan->rxCtcssIndex]=pChan->rxCtcssIndex;
- pDecCtcss->decode=-1;
+ pChan->rxCtcss->pDebug0=calloc(numSamples,2);
+ pChan->rxCtcss->pDebug1=calloc(numSamples,2);
+ pChan->rxCtcss->pDebug2=calloc(numSamples,2);
+ pChan->rxCtcss->pDebug3=calloc(numSamples,2);
for(i=0;i<CTCSS_NUM_CODES;i++)
{
- ptdet=&(pChan->rxCtcss->tdet[i]);
- ptdet->state=1;
- ptdet->setpt=(M_Q15*0.067); // 0.069
- ptdet->hyst =(M_Q15*0.020);
- ptdet->counterFactor=coef_ctcss_div[i];
- ptdet->binFactor=(M_Q15*0.135); // was 0.140
- ptdet->fudgeFactor=8;
- }
+ pChan->rxCtcss->tdet[i].pDebug0=calloc(numSamples,2);
+ pChan->rxCtcss->tdet[i].pDebug1=calloc(numSamples,2);
+ pChan->rxCtcss->tdet[i].pDebug2=calloc(numSamples,2);
+ pChan->rxCtcss->tdet[i].pDebug3=calloc(numSamples,2);
+ }
+
+ // buffer, 2 bytes per sample, and 16 channels
+ pChan->prxDebug=calloc(numSamples*16,2);
+ pChan->ptxDebug=calloc(numSamples*16,2);
+
+ // TSCOPE CONFIGURATION SETSCOPE configure debug traces and sources for each channel of the output
+ pChan->sdbg = (t_sdbg *)calloc(sizeof(t_sdbg),1);
+
+ for(i=0;i<XPMR_DEBUG_CHANS;i++)pChan->sdbg->trace[i]=-1;
+
+ TRACEF(1,("pChan->tracetype = %i\n",pChan->tracetype));
+
+ if(pChan->tracetype==1) // CTCSS DECODE
+ {
+ pChan->sdbg->source [0]=pChan->pRxDemod;
+ pChan->sdbg->source [1]=pChan->pRxBase;
+ pChan->sdbg->source [2]=pChan->pRxNoise;
+ pChan->sdbg->trace [3]=RX_NOISE_TRIG;
+ pChan->sdbg->source [4]=pChan->pRxLsd;
+ pChan->sdbg->source [5]=pChan->pRxLsdCen;
+ pChan->sdbg->source [6]=pChan->pRxLsdLimit;
+ pChan->sdbg->source [7]=pChan->rxCtcss->tdet[3].pDebug0;
+ pChan->sdbg->trace [8]=RX_CTCSS_DECODE;
+ pChan->sdbg->trace [9]=RX_SMODE;
+ }
+ if(pChan->tracetype==2) // CTCSS DECODE
+ {
+ pChan->sdbg->source [0]=pChan->pRxDemod;
+ pChan->sdbg->source [1]=pChan->pRxBase;
+ pChan->sdbg->trace [2]=RX_NOISE_TRIG;
+ pChan->sdbg->source [3]=pChan->pRxLsd;
+ pChan->sdbg->source [4]=pChan->pRxLsdCen;
+ pChan->sdbg->source [5]=pChan->pRxDcTrack;
+ pChan->sdbg->source [6]=pChan->pRxLsdLimit;
+ pChan->sdbg->source [7]=pChan->rxCtcss->tdet[3].pDebug0;
+ pChan->sdbg->source [8]=pChan->rxCtcss->tdet[3].pDebug1;
+ pChan->sdbg->source [9]=pChan->rxCtcss->tdet[3].pDebug2;
+ pChan->sdbg->source [10]=pChan->rxCtcss->tdet[3].pDebug3;
+ pChan->sdbg->trace [11]=RX_CTCSS_DECODE;
+ pChan->sdbg->trace [12]=RX_SMODE;
+ pChan->sdbg->trace [13]=TX_PTT_IN;
+ pChan->sdbg->trace [14]=TX_PTT_OUT;
+ pChan->sdbg->source [15]=pChan->pTxLsdLpf;
+ }
+ else if(pChan->tracetype==3) // DCS DECODE
+ {
+ pChan->sdbg->source [0]=pChan->pRxDemod;
+ pChan->sdbg->source [1]=pChan->pRxBase;
+ pChan->sdbg->trace [2]=RX_NOISE_TRIG;
+ pChan->sdbg->source [3]=pChan->pRxLsd;
+ pChan->sdbg->source [4]=pChan->pRxLsdCen;
+ pChan->sdbg->source [5]=pChan->pRxDcTrack;
+ pChan->sdbg->trace [6]=RX_DCS_CLK;
+ pChan->sdbg->trace [7]=RX_DCS_DIN;
+ pChan->sdbg->trace [8]=RX_DCS_DEC;
+ pChan->sdbg->trace [9]=RX_SMODE;
+ pChan->sdbg->trace [10]=TX_PTT_IN;
+ pChan->sdbg->trace [11]=TX_PTT_OUT;
+ pChan->sdbg->trace [12]=TX_LSD_CLK;
+ pChan->sdbg->trace [13]=TX_LSD_DAT;
+ pChan->sdbg->trace [14]=TX_LSD_GEN;
+ pChan->sdbg->source [14]=pChan->pTxLsd;
+ pChan->sdbg->source [15]=pChan->pTxLsdLpf;
+ }
+ else if(pChan->tracetype==4) // LSD DECODE
+ {
+ pChan->sdbg->source [0]=pChan->pRxDemod;
+ pChan->sdbg->source [1]=pChan->pRxBase;
+ pChan->sdbg->trace [2]=RX_NOISE_TRIG;
+ pChan->sdbg->source [3]=pChan->pRxLsd;
+ pChan->sdbg->source [4]=pChan->pRxLsdCen;
+ pChan->sdbg->source [5]=pChan->pRxDcTrack;
+ pChan->sdbg->trace [6]=RX_LSD_CLK;
+ pChan->sdbg->trace [7]=RX_LSD_DAT;
+ pChan->sdbg->trace [8]=RX_LSD_ERR;
+ pChan->sdbg->trace [9]=RX_LSD_SYNC;
+ pChan->sdbg->trace [10]=RX_SMODE;
+ pChan->sdbg->trace [11]=TX_PTT_IN;
+ pChan->sdbg->trace [12]=TX_PTT_OUT;
+ pChan->sdbg->trace [13]=TX_LSD_CLK;
+ pChan->sdbg->trace [14]=TX_LSD_DAT;
+ //pChan->sdbg->trace [14]=TX_LSD_GEN;
+ //pChan->sdbg->source [14]=pChan->pTxLsd;
+ pChan->sdbg->source [15]=pChan->pTxLsdLpf;
+ }
+ else if(pChan->tracetype==5) // LSD LOGIC
+ {
+ pChan->sdbg->source [0]=pChan->pRxBase;
+ pChan->sdbg->trace [1]=RX_NOISE_TRIG;
+ pChan->sdbg->source [2]=pChan->pRxDcTrack;
+ pChan->sdbg->trace [3]=RX_LSD_SYNC;
+ pChan->sdbg->trace [4]=RX_SMODE;
+ pChan->sdbg->trace [5]=TX_PTT_IN;
+ pChan->sdbg->trace [6]=TX_PTT_OUT;
+ pChan->sdbg->source [7]=pChan->pTxLsdLpf;
+ }
+ else if(pChan->tracetype==6)
+ {
+ // tx clock skew and jitter buffer
+ pChan->sdbg->source [0]=pChan->pRxDemod;
+ pChan->sdbg->source [5]=pChan->pTxBase;
+ pChan->sdbg->trace [6]=TX_DEDRIFT_LEAD;
+ pChan->sdbg->trace [7]=TX_DEDRIFT_ERR;
+ pChan->sdbg->trace [8]=TX_DEDRIFT_FACTOR;
+ pChan->sdbg->trace [9]=TX_DEDRIFT_DRIFT;
+ }
+ else if(pChan->tracetype==7)
+ {
+ // tx path
+ pChan->sdbg->source [0]=pChan->pRxBase;
+ pChan->sdbg->trace [1]=RX_NOISE_TRIG;
+ pChan->sdbg->source [2]=pChan->pRxLsd;
+ pChan->sdbg->trace [3]=RX_CTCSS_DECODE;
+ pChan->sdbg->source [4]=pChan->pRxHpf;
+
+ pChan->sdbg->trace [5]=TX_PTT_IN;
+ pChan->sdbg->trace [6]=TX_PTT_OUT;
+
+ pChan->sdbg->source [7]=pChan->pTxBase;
+ pChan->sdbg->source [8]=pChan->pTxHpf;
+ pChan->sdbg->source [9]=pChan->pTxPreEmp;
+ pChan->sdbg->source [10]=pChan->pTxLimiter;
+ pChan->sdbg->source [11]=pChan->pTxComposite;
+ pChan->sdbg->source [12]=pChan->pTxLsdLpf;
+ }
+
+ for(i=0;i<XPMR_DEBUG_CHANS;i++){
+ if(pChan->sdbg->trace[i]>=0)pChan->sdbg->point[pChan->sdbg->trace[i]]=i;
+ }
+ pChan->sdbg->mode=1;
+ #endif
+
+ #ifdef XPMRX_H
+ // LSD GENERATOR
+ pSps=pChan->spsLsdGen=createPmrSps(pChan);
+ pSps->source=NULL;
+ pSps->sink=pChan->pTxLsd;
+ pSps->numChanOut=1;
+ pSps->selChanOut=0;
+ pSps->sigProc=LsdGen;
+ pSps->nSamples=pChan->nSamplesTx;
+ pSps->outputGain=(.25*M_Q8);
+ pSps->option=0;
+ pSps->interpolate=1;
+ pSps->decimate=1;
+ pSps->enabled=0;
+ #endif
// General Purpose Function Generator
- pSps=pChan->spsSigGen1=createPmrSps();
- pSps->parentChan=pChan;
- pSps->sink=pChan->pSigGen1;
+ pSps=pChan->spsSigGen1=createPmrSps(pChan);
+ pSps->sink=pChan->pSigGen1;
pSps->numChanOut=1;
pSps->selChanOut=0;
- pSps->sigProc=SigGen;
+ pSps->sigProc=SigGen;
pSps->nSamples=pChan->nSamplesTx;
pSps->sampleRate=SAMPLE_RATE_NETWORK;
pSps->freq=10000; // in increments of 0.1 Hz
@@ -1360,26 +1958,24 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
// CTCSS ENCODER
- pSps = pChan->spsSigGen0 = createPmrSps();
- pSps->parentChan=pChan;
- pSps->sink=pChan->pTxLsd;
- pSps->sigProc=SigGen;
+ pSps = pChan->spsSigGen0 = createPmrSps(pChan);
+ pSps->sink=pChan->pTxLsd;
+ pSps->sigProc=SigGen;
pSps->numChanOut=1;
pSps->selChanOut=0;
pSps->nSamples=pChan->nSamplesTx;
pSps->sampleRate=SAMPLE_RATE_NETWORK;
- pSps->freq=pChan->txCtcssFreq*10; // in increments of 0.1 Hz
+ pSps->freq=1000; // in 0.1 Hz steps
pSps->outputGain=(0.5*M_Q8);
pSps->option=0;
pSps->interpolate=1;
pSps->decimate=1;
pSps->enabled=0;
-
// Tx LSD Low Pass Filter
- pSps=pChan->spsTxLsdLpf=pSps->nextSps=createPmrSps();
+ pSps=pChan->spsTxLsdLpf=createPmrSps(pChan);
pSps->source=pChan->pTxLsd;
- pSps->sink=pChan->pTxLsdLpf;
+ pSps->sink=pChan->pTxLsdLpf;
pSps->sigProc=pmr_gp_fir;
pSps->enabled=0;
pSps->numChanOut=1;
@@ -1389,41 +1985,30 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pSps->interpolate=1;
pSps->inputGain=(1*M_Q8);
pSps->outputGain=(1*M_Q8);
-
- if(pChan->txCtcssFreq>203.0)
- {
- pSps->ncoef=taps_fir_lpf_250_9_66;
- pSps->size_coef=2;
- pSps->coef=(void*)coef_fir_lpf_250_9_66;
- pSps->nx=taps_fir_lpf_250_9_66;
- pSps->size_x=2;
- pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
- pSps->calcAdjust=gain_fir_lpf_250_9_66;
- }
- else
- {
- pSps->ncoef=taps_fir_lpf_215_9_88;
- pSps->size_coef=2;
- pSps->coef=(void*)coef_fir_lpf_215_9_88;
- pSps->nx=taps_fir_lpf_215_9_88;
- pSps->size_x=2;
- pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
- pSps->calcAdjust=gain_fir_lpf_215_9_88;
- }
+
+ // configure the longer, lower cutoff filter by default
+ pSps->ncoef=taps_fir_lpf_215_9_88;
+ pSps->size_coef=2;
+ pSps->coef=(void*)coef_fir_lpf_215_9_88;
+ pSps->nx=taps_fir_lpf_215_9_88;
+ pSps->size_x=2;
+ pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
+ pSps->calcAdjust=gain_fir_lpf_215_9_88;
pSps->inputGain=(1*M_Q8);
pSps->outputGain=(1*M_Q8);
-
- if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
-
+ TRACEF(1,("spsTxLsdLpf = sps \n"));
+
+ if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
+
+
// RX Process
- TRACEX(("create rx\n"));
+ TRACEF(1,("create rx\n"));
pSps = NULL;
// allocate space for first sps and set pointers
- pSps=pChan->spsRx=createPmrSps();
- pSps->parentChan=pChan;
+ pSps=pChan->spsRx=createPmrSps(pChan);
pSps->source=NULL; //set when called
pSps->sink=pChan->pRxBase;
pSps->sigProc=pmr_rx_frontend;
@@ -1440,7 +2025,7 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pSps->x=(void*)(calloc(pSps->nx,pSps->size_coef));
pSps->calcAdjust=(gain_fir_lpf_3K_1*256)/0x0100;
pSps->outputGain=(1.0*M_Q8);
- pSps->discfactor=2;
+ pSps->discfactor=2;
pSps->hyst=pChan->rxCarrierHyst;
pSps->setpt=pChan->rxCarrierPoint;
pChan->prxSquelchAdjust=&pSps->setpt;
@@ -1450,11 +2035,10 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pSps->debugBuff2=pChan->prxDebug0;
#endif
-
+
// allocate space for next sps and set pointers
// Rx SubAudible Decoder Low Pass Filter
- pSps=pSps->nextSps=createPmrSps();
- pSps->parentChan=pChan;
+ pSps=pChan->spsRxLsd=pSps->nextSps=createPmrSps(pChan);
pSps->source=pChan->pRxBase;
pSps->sink=pChan->pRxLsd;
pSps->sigProc=pmr_gp_fir;
@@ -1465,59 +2049,40 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pSps->decimator=pSps->decimate=1;
pSps->interpolate=1;
- if(pChan->rxCtcssFreq>203.5)
- {
- pSps->ncoef=taps_fir_lpf_250_9_66;
- pSps->size_coef=2;
- pSps->coef=(void*)coef_fir_lpf_250_9_66;
- pSps->nx=taps_fir_lpf_250_9_66;
- pSps->size_x=2;
- pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
- pSps->calcAdjust=gain_fir_lpf_250_9_66;
- }
- else
- {
- pSps->ncoef=taps_fir_lpf_215_9_88;
- pSps->size_coef=2;
- pSps->coef=(void*)coef_fir_lpf_215_9_88;
- pSps->nx=taps_fir_lpf_215_9_88;
- pSps->size_x=2;
- pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
- pSps->calcAdjust=gain_fir_lpf_215_9_88;
- }
+ // configure the the larger, lower cutoff filter by default
+ pSps->ncoef=taps_fir_lpf_215_9_88;
+ pSps->size_coef=2;
+ pSps->coef=(void*)coef_fir_lpf_215_9_88;
+ pSps->nx=taps_fir_lpf_215_9_88;
+ pSps->size_x=2;
+ pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
+ pSps->calcAdjust=gain_fir_lpf_215_9_88;
pSps->inputGain=(1*M_Q8);
pSps->outputGain=(1*M_Q8);
pChan->prxCtcssMeasure=pSps->sink;
- pChan->prxCtcssAdjust=&(pSps->outputGain);
-
+ pChan->prxCtcssAdjust=&(pSps->outputGain);
+
+ // CTCSS CenterSlicer
+ pSps=pChan->spsRxLsdNrz=pSps->nextSps=createPmrSps(pChan);
+ pSps->source=pChan->pRxLsd;
+ pSps->sink=pChan->pRxDcTrack;
+ pSps->buff=pChan->pRxLsdLimit;
+ pSps->sigProc=CenterSlicer;
+ pSps->nSamples=pChan->nSamplesRx;
+ pSps->discfactor=LSD_DFS; // centering time constant
+ pSps->inputGain=(1*M_Q8);
+ pSps->outputGain=(1*M_Q8);
+ pSps->setpt=4900; // ptp clamp for DC centering
+ pSps->inputGainB=625; // peak output limiter clip point
+ pSps->enabled=0;
- // allocate space for next sps and set pointers
- // CenterSlicer
- if(pChan->rxCenterSlicerEnable)
- {
- pSps=pSps->nextSps=createPmrSps();
- pSps->parentChan=pChan;
- pSps->source=pChan->pRxLsd;
- pSps->sink=pChan->pRxDcTrack;
- pSps->buff=pChan->pRxLsdLimit;
- pSps->sigProc=CenterSlicer;
- pSps->enabled=1;
- pSps->nSamples=pChan->nSamplesRx;
- pSps->discfactor=800;
- pSps->inputGain=(1*M_Q8);
- pSps->outputGain=(1*M_Q8);
- pSps->setpt=3000;
- pSps->inputGainB=1000; // limiter set point
- }
- // allocate space for next sps and set pointers
// Rx HPF
- pSps=pSps->nextSps=createPmrSps();
- pSps->parentChan=pChan;
+ pSps=pSps->nextSps=createPmrSps(pChan);
pChan->spsRxHpf=pSps;
pSps->source=pChan->pRxBase;
- pSps->sink=pChan->pRxHpf;
+ pSps->sink=pChan->pRxHpf;
pSps->sigProc=pmr_gp_fir;
pSps->enabled=1;
pSps->numChanOut=1;
@@ -1531,49 +2096,49 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pSps->nx=taps_fir_hpf_300_9_66;
pSps->size_x=2;
pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
- if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
+ if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
pSps->calcAdjust=gain_fir_hpf_300_9_66;
pSps->inputGain=(1*M_Q8);
pSps->outputGain=(1*M_Q8);
+ pChan->prxVoiceAdjust=&(pSps->outputGain);
pChan->spsRxOut=pSps;
// allocate space for next sps and set pointers
// Rx DeEmp
if(pChan->rxDeEmpEnable){
- pSps=pSps->nextSps=createPmrSps();
- pSps->parentChan=pChan;
+ pSps=pSps->nextSps=createPmrSps(pChan);
pChan->spsRxDeEmp=pSps;
pSps->source=pChan->pRxHpf;
- pSps->sink=pChan->pRxSpeaker;
- pChan->spsRxOut=pSps; // OUTPUT STRUCTURE! maw
+ pSps->sink=pChan->pRxSpeaker;
+ pChan->spsRxOut=pSps; // OUTPUT STRUCTURE!
pSps->sigProc=gp_inte_00;
pSps->enabled=1;
pSps->nSamples=pChan->nSamplesRx;
-
+
pSps->ncoef=taps_int_lpf_300_1_2;
pSps->size_coef=2;
pSps->coef=(void*)coef_int_lpf_300_1_2;
-
+
pSps->nx=taps_int_lpf_300_1_2;
pSps->size_x=4;
pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
- if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
+ if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
pSps->calcAdjust=gain_int_lpf_300_1_2/2;
pSps->inputGain=(1.0*M_Q8);
pSps->outputGain=(1.0*M_Q8);
pChan->prxVoiceMeasure=pSps->sink;
- pChan->prxVoiceAdjust=&(pSps->outputGain);
+ pChan->prxVoiceAdjust=&(pSps->outputGain);
}
if(pChan->rxDelayLineEnable)
{
- TRACEX(("create delayline\n"));
- pSps=pChan->spsDelayLine=pSps->nextSps=createPmrSps();
+ TRACEF(1,("create delayline\n"));
+ pSps=pChan->spsDelayLine=pSps->nextSps=createPmrSps(pChan);
pSps->sigProc=DelayLine;
- pSps->source=pChan->pRxSpeaker;
+ pSps->source=pChan->pRxSpeaker;
pSps->sink=pChan->pRxSpeaker;
pSps->enabled=0;
- pSps->inputGain=1*M_Q8;
+ pSps->inputGain=1*M_Q8;
pSps->outputGain=1*M_Q8;
pSps->nSamples=pChan->nSamplesRx;
pSps->buffSize=4096;
@@ -1584,36 +2149,40 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
if(pChan->rxCdType==CD_XPMR_VOX)
{
- TRACEX(("create vox measureblock\n"));
- pSps=pChan->spsRxVox=pSps->nextSps=createPmrSps();
+ TRACEF(1,("create vox measureblock\n"));
+ pChan->prxVoxMeas=calloc(pChan->nSamplesRx,2);
+
+ pSps=pChan->spsRxVox=pSps->nextSps=createPmrSps(pChan);
pSps->sigProc=MeasureBlock;
pSps->parentChan=pChan;
pSps->source=pChan->pRxBase;
- pSps->sink=pChan->prxDebug1;
- pSps->inputGain=1*M_Q8;
+ pSps->sink=pChan->prxVoxMeas;
+ pSps->inputGain=1*M_Q8;
pSps->outputGain=1*M_Q8;
pSps->nSamples=pChan->nSamplesRx;
pSps->discfactor=3;
- pSps->setpt=(0.01*M_Q15);
+ if(pChan->rxSqVoxAdj==0)
+ pSps->setpt=(0.011*M_Q15);
+ else
+ pSps->setpt=(pChan->rxSqVoxAdj);
pSps->hyst=(pSps->setpt/10);
pSps->enabled=1;
}
// tuning measure block
- pSps=pChan->spsMeasure=pSps->nextSps=createPmrSps();
- pSps->parentChan=pChan;
- pSps->source=pChan->spsRx->sink;
- pSps->sink=pChan->prxDebug2;
+ pSps=pChan->spsMeasure=pSps->nextSps=createPmrSps(pChan);
+ pSps->source=pChan->spsRx->sink;
+ pSps->sink=pChan->prxMeasure;
pSps->sigProc=MeasureBlock;
pSps->enabled=0;
pSps->nSamples=pChan->nSamplesRx;
- pSps->discfactor=10;
+ pSps->discfactor=10;
pSps->nextSps=NULL; // last sps in chain RX
// CREATE TRANSMIT CHAIN
- TRACEX((" create tx\n"));
+ TRACEF(1,("create tx\n"));
inputTmp=NULL;
pSps = NULL;
@@ -1622,10 +2191,10 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
// Tx HPF SubAudible
if(pChan->txHpfEnable)
{
- pSps=createPmrSps();
+ pSps=createPmrSps(pChan);
pChan->spsTx=pSps;
pSps->source=pChan->pTxBase;
- pSps->sink=pChan->pTxHpf;
+ pSps->sink=pChan->pTxHpf;
pSps->sigProc=pmr_gp_fir;
pSps->enabled=1;
pSps->numChanOut=1;
@@ -1639,7 +2208,7 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pSps->nx=taps_fir_hpf_300_9_66;
pSps->size_x=2;
pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
- if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
+ if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
pSps->calcAdjust=gain_fir_hpf_300_9_66;
pSps->inputGain=(1*M_Q8);
pSps->outputGain=(1*M_Q8);
@@ -1649,37 +2218,36 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
// Tx PreEmphasis
if(pChan->txPreEmpEnable)
{
- if(pSps==NULL) pSps=pChan->spsTx=createPmrSps();
- else pSps=pSps->nextSps=createPmrSps();
-
- pSps->parentChan=pChan;
+ if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(pChan);
+ else pSps=pSps->nextSps=createPmrSps(pChan);
+
pSps->source=inputTmp;
- pSps->sink=pChan->pTxPreEmp;
-
+ pSps->sink=pChan->pTxPreEmp;
+
pSps->sigProc=gp_diff;
pSps->enabled=1;
pSps->nSamples=pChan->nSamplesTx;
-
+
pSps->ncoef=taps_int_hpf_4000_1_2;
pSps->size_coef=2;
pSps->coef=(void*)coef_int_hpf_4000_1_2;
-
+
pSps->nx=taps_int_hpf_4000_1_2;
pSps->size_x=2;
pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
- pSps->outputGain=(1*M_Q8);
+
pSps->calcAdjust=gain_int_hpf_4000_1_2;
pSps->inputGain=(1*M_Q8);
- pSps->outputGain=(1*M_Q8);
+ pSps->outputGain=(1*M_Q8); // to match flat at 1KHz
inputTmp=pSps->sink;
}
// Tx Limiter
if(pChan->txLimiterEnable)
{
- if(pSps==NULL) pSps=pChan->spsTx=createPmrSps();
- else pSps=pSps->nextSps=createPmrSps();
+ if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(pChan);
+ else pSps=pSps->nextSps=createPmrSps(pChan);
pSps->source=inputTmp;
pSps->sink=pChan->pTxLimiter;
pSps->sigProc=SoftLimiter;
@@ -1695,38 +2263,37 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
if((pChan->txMixA==TX_OUT_COMPOSITE)||(pChan->txMixB==TX_OUT_COMPOSITE))
{
if(pSps==NULL)
- pSps=pChan->spsTx=createPmrSps();
+ pSps=pChan->spsTx=createPmrSps(pChan);
else
- pSps=pSps->nextSps=createPmrSps();
+ pSps=pSps->nextSps=createPmrSps(pChan);
pSps->source=inputTmp;
pSps->sourceB=pChan->pTxLsdLpf; //asdf ??? !!! maw pTxLsdLpf
pSps->sink=pChan->pTxComposite;
pSps->sigProc=pmrMixer;
pSps->enabled=1;
pSps->nSamples=pChan->nSamplesTx;
- pSps->inputGain=2*M_Q8;
- pSps->inputGainB=1*M_Q8/8;
+ pSps->inputGain=2*M_Q8;
+ pSps->inputGainB=1*M_Q8/8;
pSps->outputGain=1*M_Q8;
pSps->setpt=0;
inputTmp=pSps->sink;
pChan->ptxCtcssAdjust=&pSps->inputGainB;
}
- // Chan A Upsampler and Filter
- if(pSps==NULL) pSps=pChan->spsTx=createPmrSps();
- else pSps=pSps->nextSps=createPmrSps();
+ // Chan A Upsampler and Filter
+ if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(pChan);
+ else pSps=pSps->nextSps=createPmrSps(pChan);
pChan->spsTxOutA=pSps;
if(!pChan->spsTx)pChan->spsTx=pSps;
- pSps->parentChan=pChan;
if(pChan->txMixA==TX_OUT_COMPOSITE)
{
- pSps->source=pChan->pTxComposite;
+ pSps->source=pChan->pTxComposite;
}
else if(pChan->txMixA==TX_OUT_LSD)
{
- pSps->source=pChan->pTxLsdLpf;
+ pSps->source=pChan->pTxLsdLpf;
}
else if(pChan->txMixA==TX_OUT_VOICE)
{
@@ -1734,14 +2301,15 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
}
else if (pChan->txMixA==TX_OUT_AUX)
{
- pSps->source=inputTmp;
+ pSps->source=inputTmp;
}
else
{
- pSps->source=NULL;
+ pSps->source=NULL; // maw sph asdf !!! no blow up
+ pSps->source=inputTmp;
}
-
- pSps->sink=pChan->pTxOut;
+
+ pSps->sink=pChan->pTxOut;
pSps->sigProc=pmr_gp_fir;
pSps->enabled=1;
pSps->numChanOut=2;
@@ -1754,7 +2322,7 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pSps->nx=taps_fir_lpf_3K_1;
pSps->size_x=2;
pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
- if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
+ if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
pSps->calcAdjust=gain_fir_lpf_3K_1;
pSps->inputGain=(1*M_Q8);
pSps->outputGain=(1*M_Q8);
@@ -1762,17 +2330,16 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
else pSps->monoOut=0;
- // Chan B Upsampler and Filter
+ // Chan B Upsampler and Filter
if((pChan->txMixA!=pChan->txMixB)&&(pChan->txMixB!=TX_OUT_OFF))
{
- if(pSps==NULL) pSps=pChan->spsTx=createPmrSps();
- else pSps=pSps->nextSps=createPmrSps();
+ if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(pChan);
+ else pSps=pSps->nextSps=createPmrSps(pChan);
pChan->spsTxOutB=pSps;
- pSps->parentChan=pChan;
if(pChan->txMixB==TX_OUT_COMPOSITE)
{
- pSps->source=pChan->pTxComposite;
+ pSps->source=pChan->pTxComposite;
}
else if(pChan->txMixB==TX_OUT_LSD)
{
@@ -1789,10 +2356,10 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
}
else
{
- pSps->source=NULL;
+ pSps->source=NULL;
}
- pSps->sink=pChan->pTxOut;
+ pSps->sink=pChan->pTxOut;
pSps->sigProc=pmr_gp_fir;
pSps->enabled=1;
pSps->numChanOut=2;
@@ -1810,46 +2377,33 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples)
pSps->calcAdjust=(gain_fir_lpf_3K_1);
pSps->inputGain=(1*M_Q8);
pSps->outputGain=(1*M_Q8);
-
}
pSps->nextSps=NULL;
- #if XPMR_DEBUG0 == 1
- {
- t_tdet *ptdet;
- TRACEX((" configure tracing\n"));
-
- pChan->rxCtcss->pDebug0=calloc(numSamples,2);
- pChan->rxCtcss->pDebug1=calloc(numSamples,2);
- pChan->rxCtcss->pDebug2=calloc(numSamples,2);
-
- for(i=0;i<CTCSS_NUM_CODES;i++){
- ptdet=&(pChan->rxCtcss->tdet[i]);
- ptdet->pDebug0=calloc(numSamples,2);
- ptdet->pDebug1=calloc(numSamples,2);
- ptdet->pDebug2=calloc(numSamples,2);
- }
+ // Configure Coded Signaling
+ code_string_parse(pChan);
- // buffer, 2 bytes per sample, and 16 channels
- pChan->prxDebug=calloc(numSamples*16,2);
- pChan->ptxDebug=calloc(numSamples*16,2);
- }
- #endif
+ pChan->smode=SMODE_NULL;
+ pChan->smodewas=SMODE_NULL;
+ pChan->smodetime=2500;
+ pChan->smodetimer=0;
+ pChan->b.smodeturnoff=0;
+
+ pChan->txsettletimer=0;
- TRACEX((" createPmrChannel() end\n"));
+ TRACEF(1,("createPmrChannel() end\n"));
return pChan;
}
-/*
+/*
*/
i16 destroyPmrChannel(t_pmr_chan *pChan)
{
t_pmr_sps *pmr_sps, *tmp_sps;
- i16 i;
-
- TRACEX(("destroyPmrChannel()\n"));
+ TRACEF(1,("destroyPmrChannel()\n"));
+
free(pChan->pRxDemod);
free(pChan->pRxNoise);
free(pChan->pRxBase);
@@ -1865,20 +2419,16 @@ i16 destroyPmrChannel(t_pmr_chan *pChan)
free(pChan->pTxLsd);
free(pChan->pTxLsdLpf);
if(pChan->pTxComposite)free(pChan->pTxComposite);
- free(pChan->pTxCode);
free(pChan->pTxOut);
+ if(pChan->prxMeasure)free(pChan->prxMeasure);
if(pChan->pSigGen0)free(pChan->pSigGen0);
if(pChan->pSigGen1)free(pChan->pSigGen1);
+
#if XPMR_DEBUG0 == 1
- free(pChan->pTxPttIn);
- free(pChan->pTxPttOut);
- if(pChan->prxDebug)free(pChan->prxDebug);
+ //if(pChan->prxDebug)free(pChan->prxDebug);
if(pChan->ptxDebug)free(pChan->ptxDebug);
- free(pChan->rxCtcss->pDebug0);
- free(pChan->rxCtcss->pDebug1);
-
free(pChan->prxDebug0);
free(pChan->prxDebug1);
free(pChan->prxDebug2);
@@ -1889,18 +2439,28 @@ i16 destroyPmrChannel(t_pmr_chan *pChan)
free(pChan->ptxDebug2);
free(pChan->ptxDebug3);
+ free(pChan->rxCtcss->pDebug0);
+ free(pChan->rxCtcss->pDebug1);
+
+ i16 i;
for(i=0;i<CTCSS_NUM_CODES;i++)
{
free(pChan->rxCtcss->tdet[i].pDebug0);
free(pChan->rxCtcss->tdet[i].pDebug1);
free(pChan->rxCtcss->tdet[i].pDebug2);
+ free(pChan->rxCtcss->tdet[i].pDebug3);
}
#endif
+ pChan->dd.option=8;
+ dedrift(pChan);
+
free(pChan->pRxCtcss);
pmr_sps=pChan->spsRx;
-
+
+ if(pChan->sdbg)free(pChan->sdbg);
+
while(pmr_sps)
{
tmp_sps = pmr_sps;
@@ -1914,16 +2474,19 @@ i16 destroyPmrChannel(t_pmr_chan *pChan)
}
/*
*/
-t_pmr_sps *createPmrSps(void)
+t_pmr_sps *createPmrSps(t_pmr_chan *pChan)
{
t_pmr_sps *pSps;
- TRACEX(("createPmrSps()\n"));
+ TRACEF(1,("createPmrSps()\n"));
pSps = (t_pmr_sps *)calloc(sizeof(t_pmr_sps),1);
if(!pSps)printf("Error: createPmrSps()\n");
+ pSps->parentChan=pChan;
+ pSps->index=pChan->spsIndex++;
+
// pSps->x=calloc(pSps->nx,pSps->size_x);
return pSps;
@@ -1932,21 +2495,63 @@ t_pmr_sps *createPmrSps(void)
*/
i16 destroyPmrSps(t_pmr_sps *pSps)
{
- TRACEX(("destroyPmrSps(%i)\n",pSps->index));
+ TRACEJ(1,("destroyPmrSps(%i)\n",pSps->index));
if(pSps->x!=NULL)free(pSps->x);
free(pSps);
return 0;
}
-/*
- PmrRx does the whole buffer
+/*
+ PmrTx - takes data from network and holds it for PmrRx
+*/
+i16 PmrTx(t_pmr_chan *pChan, i16 *input)
+{
+ pChan->frameCountTx++;
+
+ TRACEF(5,("PmrTx() start %i\n",pChan->frameCountTx));
+
+ #if XPMR_PPTP == 99
+ pptp_p2^=1;
+ if(pptp_p2)ioctl(ppdrvdev,PPDRV_IOC_PINSET,LP_PIN02);
+ else ioctl(ppdrvdev,PPDRV_IOC_PINCLEAR,LP_PIN02);
+ #endif
+
+ if(pChan==NULL){
+ printf("PmrTx() pChan == NULL\n");
+ return 1;
+ }
+
+ #if XPMR_DEBUG0 == 1
+ if(pChan->b.rxCapture && pChan->tracetype==5)
+ {
+ memcpy(pChan->pTxInput,input,pChan->nSamplesRx*2);
+ }
+ #endif
+
+ //if(pChan->b.radioactive)pChan->dd.debug=1;
+ //else pChan->dd.debug=0;
+
+ dedrift_write(pChan,input);
+
+ return 0;
+}
+/*
+ PmrRx handles a block of data from the usb audio device
*/
-i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *output)
+i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *outputrx, i16 *outputtx)
{
- int i,ii;
+ int i,hit;
+ float f=0;
t_pmr_sps *pmr_sps;
- TRACEX(("PmrRx() %i\n",pChan->frameCountRx));
+ TRACEC(5,("PmrRx(%p %p %p %p)\n",pChan, input, outputrx, outputtx));
+
+ #if XPMR_PPTP == 1
+ if(pChan->b.radioactive)
+ {
+ pptp_write(1,pChan->frameCountRx&0x00000001);
+ }
+ #endif
if(pChan==NULL){
printf("PmrRx() pChan == NULL\n");
@@ -1955,10 +2560,23 @@ i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *output)
pChan->frameCountRx++;
+ #if XPMR_DEBUG0 == 1
+ if(pChan->b.rxCapture)
+ {
+ //if(pChan->prxDebug)memset((void *)pChan->prxDebug,0,pChan->nSamplesRx*XPMR_DEBUG_CHANS*2);
+ if(pChan->ptxDebug)memset((void *)pChan->ptxDebug,0,pChan->nSamplesRx*XPMR_DEBUG_CHANS*2);
+ if(pChan->sdbg->buffer)
+ {
+ memset((void *)pChan->sdbg->buffer,0,pChan->nSamplesRx*XPMR_DEBUG_CHANS*2);
+ pChan->prxDebug=pChan->sdbg->buffer;
+ }
+ }
+ #endif
+
pmr_sps=pChan->spsRx; // first sps
pmr_sps->source=input;
- if(output!=NULL)pChan->spsRxOut->sink=output; //last sps
+ if(outputrx!=NULL)pChan->spsRxOut->sink=outputrx; //last sps
#if 0
if(pChan->inputBlanking>0)
@@ -1969,30 +2587,38 @@ i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *output)
input[i]=0;
}
#endif
-
- // || (pChan->radioDuplex && (pChan->pttIn || pChan->pttOut)))
- if(pChan->rxCpuSaver && !pChan->rxCarrierDetect)
+
+ if( pChan->rxCpuSaver && !pChan->rxCarrierDetect &&
+ pChan->smode==SMODE_NULL &&
+ !pChan->txPttIn && !pChan->txPttOut)
{
- if(pChan->spsRxHpf)pChan->spsRxHpf->enabled=0;
- if(pChan->spsRxDeEmp)pChan->spsRxDeEmp->enabled=0;
+ if(!pChan->b.rxhalted)
+ {
+ if(pChan->spsRxHpf)pChan->spsRxHpf->enabled=0;
+ if(pChan->spsRxDeEmp)pChan->spsRxDeEmp->enabled=0;
+ pChan->b.rxhalted=1;
+ TRACEC(1,("PmrRx() rx sps halted\n"));
+ }
}
- else
+ else if(pChan->b.rxhalted)
{
if(pChan->spsRxHpf)pChan->spsRxHpf->enabled=1;
if(pChan->spsRxDeEmp)pChan->spsRxDeEmp->enabled=1;
+ pChan->b.rxhalted=0;
+ TRACEC(1,("PmrRx() rx sps un-halted\n"));
}
i=0;
while(pmr_sps!=NULL && pmr_sps!=0)
{
- TRACEX(("PmrRx() sps %i\n",i++));
+ TRACEC(5,("PmrRx() sps %i\n",i++));
pmr_sps->sigProc(pmr_sps);
pmr_sps = (t_pmr_sps *)(pmr_sps->nextSps);
//pmr_sps=NULL; // sph maw
}
#define XPMR_VOX_HANGTIME 2000
-
+
if(pChan->rxCdType==CD_XPMR_VOX)
{
if(pChan->spsRxVox->compOut)
@@ -2015,242 +2641,692 @@ i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *output)
pChan->rxCarrierDetect=!pChan->spsRx->compOut;
}
- if( !pChan->rxCpuSaver || pChan->rxCarrierDetect
- || pChan->rxCtcss->decode!=-1) ctcss_detect(pChan);
+ // stop and start these engines instead to eliminate falsing
+ if( pChan->b.ctcssRxEnable &&
+ ( (!pChan->b.rxhalted ||
+ pChan->rxCtcss->decode!=CTCSS_NULL || pChan->smode==SMODE_CTCSS) &&
+ (pChan->smode!=SMODE_DCS&&pChan->smode!=SMODE_LSD) )
+ )
+ {
+ ctcss_detect(pChan);
+ }
- #if XPMR_DEBUG0 == 1
- // TRACEX(("Write file.\n"));
- ii=0;
- if(pChan->b.rxCapture)
+ #if 1
+ if(pChan->txPttIn!=pChan->b.pttwas)
{
- for(i=0;i<pChan->nSamplesRx;i++)
- {
- pChan->prxDebug[ii++]=input[i*2*6]; // input data
- pChan->prxDebug[ii++]=output[i]; // output data
- pChan->prxDebug[ii++]=pChan->rxCarrierDetect*M_Q14; // carrier detect
- if(pChan->rxCtcss)
- pChan->prxDebug[ii++]=pChan->rxCtcss->decode*M_Q15/CTCSS_NUM_CODES; // decoded ctcss
- else
- pChan->prxDebug[ii++]=0;
-
- pChan->prxDebug[ii++]=pChan->pRxNoise[i]; // rssi
- pChan->prxDebug[ii++]=pChan->pRxBase[i]; // decimated, low pass filtered
- pChan->prxDebug[ii++]=pChan->pRxHpf[i]; // output to network
- pChan->prxDebug[ii++]=pChan->pRxSpeaker[i];
-
- pChan->prxDebug[ii++]=pChan->pRxLsd[i]; // CTCSS Filtered
- pChan->prxDebug[ii++]=pChan->pRxDcTrack[i]; // DC Restoration
- pChan->prxDebug[ii++]=pChan->pRxLsdLimit[i]; // Amplitude Limited
-
- //pChan->prxDebug[ii++]=pChan->rxCtcss->tdet[pChan->rxCtcss->testIndex+1].pDebug0[i]; // Upper Adjacent CTCSS Code
- pChan->prxDebug[ii++]=pChan->rxCtcss->tdet[pChan->rxCtcss->testIndex].pDebug0[i]; // Primary CTCSS Code
- pChan->prxDebug[ii++]=pChan->rxCtcss->tdet[pChan->rxCtcss->testIndex].pDebug1[i]; // dv/dt of decoder output
- pChan->prxDebug[ii++]=pChan->rxCtcss->tdet[pChan->rxCtcss->testIndex].pDebug2[i];
-
- //pChan->prxDebug[ii++]=pChan->rxCtcss->tdet[pChan->rxCtcss->testIndex-1].pDebug0[i]; // Lower Adjacent CTCSS Code
-
- pChan->prxDebug[ii++]=pChan->prxDebug1[i]; // Measure Output for VOX
- pChan->prxDebug[ii++]=pChan->prxDebug2[i]; // Measure Output for Tuning
- }
+ pChan->b.pttwas=pChan->txPttIn;
+ TRACEC(1,("PmrRx() txPttIn=%i\n",pChan->b.pttwas));
}
#endif
- return 0;
-}
-/*
- PmrTx does the whole buffer
-*/
-i16 PmrTx(t_pmr_chan *pChan, i16 *input, i16 *output)
-{
- int i, hit=0;
- t_pmr_sps *pmr_sps;
-
- pChan->frameCountTx++;
-
- TRACEX(("PmrTx() %i\n",pChan->frameCountTx));
+ #ifdef XPMRX_H
+ xpmrx(pChan,XXO_RXDECODE);
+ #endif
- if(pChan==NULL){
- printf("PmrTx() pChan == NULL\n");
- return 1;
+ if(pChan->smodetimer>0 && !pChan->txPttIn)
+ {
+ pChan->smodetimer-=MS_PER_FRAME;
+
+ if(pChan->smodetimer<=0)
+ {
+ pChan->smodetimer=0;
+ pChan->smodewas=pChan->smode;
+ pChan->smode=SMODE_NULL;
+ pChan->b.smodeturnoff=1;
+ TRACEC(1,("smode timeout. smode was=%i\n",pChan->smodewas));
+ }
}
- if(pChan->b.startSpecialTone)
+ if(pChan->rxCtcss->decode > CTCSS_NULL &&
+ (pChan->smode==SMODE_NULL||pChan->smode==SMODE_CTCSS) )
{
- pChan->b.startSpecialTone=0;
- pChan->spsSigGen1->option=1;
- pChan->spsSigGen1->enabled=1;
- pChan->b.doingSpecialTone=1;
- } else if(pChan->b.stopSpecialTone)
- {
- pChan->b.stopSpecialTone=0;
- pChan->spsSigGen1->option=0;
- pChan->b.doingSpecialTone=0;
- pChan->spsSigGen1->enabled=0;
- } else if(pChan->b.doingSpecialTone)
- {
- pChan->spsSigGen1->sink=output;
- pChan->spsSigGen1->sigProc(pChan->spsSigGen1);
- for(i=0;i<(pChan->nSamplesTx*2*6);i+=2)output[i+1]=output[i];
- return 0;
+ if(pChan->smode!=SMODE_CTCSS)
+ {
+ TRACEC(1,("smode set=%i code=%i\n",pChan->smode,pChan->rxCtcss->decode));
+ pChan->smode=pChan->smodewas=SMODE_CTCSS;
+ }
+ pChan->smodetimer=pChan->smodetime;
}
- // handle transmitter ptt input
+ #ifdef HAVE_XPMRX
+ xpmrx(pChan,XXO_LSDCTL);
+ #endif
+
+ //TRACEX(("PmrRx() tx portion.\n"));
+
+ // handle radio transmitter ptt input
hit=0;
- if( pChan->txPttIn && pChan->txState==0)
+ if( !(pChan->smode==SMODE_DCS||pChan->smode==SMODE_LSD) )
+ {
+
+ if( pChan->txPttIn && pChan->txState==CHAN_TXSTATE_IDLE )
{
- pChan->txState = 2;
+ TRACEC(1,("txPttIn==1 from CHAN_TXSTATE_IDLE && !SMODE_LSD. codeindex=%i %i \n",pChan->rxCtcss->decode, pChan->rxCtcssMap[pChan->rxCtcss->decode] ));
+ pChan->dd.b.doitnow=1;
+
+ if(pChan->smode==SMODE_CTCSS && !pChan->b.txCtcssInhibit)
+ {
+ if(pChan->rxCtcss->decode>CTCSS_NULL)
+ {
+ if(pChan->rxCtcssMap[pChan->rxCtcss->decode]!=CTCSS_RXONLY)
+ {
+ f=freq_ctcss[pChan->rxCtcssMap[pChan->rxCtcss->decode]];
+ }
+ }
+ else
+ {
+ f=pChan->txctcssdefault_value;
+ }
+ TRACEC(1,("txPttIn - Start CTCSSGen %f \n",f));
+ if(f)
+ {
+ t_pmr_sps *pSps;
+
+ pChan->spsSigGen0->freq=f*10;
+ pSps=pChan->spsTxLsdLpf;
+ pSps->enabled=1;
+
+ #if 0
+ if(f>203.0)
+ {
+ pSps->ncoef=taps_fir_lpf_250_9_66;
+ pSps->size_coef=2;
+ pSps->coef=(void*)coef_fir_lpf_250_9_66;
+ pSps->nx=taps_fir_lpf_250_9_66;
+ pSps->size_x=2;
+ pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
+ pSps->calcAdjust=gain_fir_lpf_250_9_66;
+ }
+ else
+ {
+ pSps->ncoef=taps_fir_lpf_215_9_88;
+ pSps->size_coef=2;
+ pSps->coef=(void*)coef_fir_lpf_215_9_88;
+ pSps->nx=taps_fir_lpf_215_9_88;
+ pSps->size_x=2;
+ pSps->x=(void*)(calloc(pSps->nx,pSps->size_x));
+ pSps->calcAdjust=gain_fir_lpf_215_9_88;
+ }
+ #endif
+
+ pChan->spsSigGen0->option=1;
+ pChan->spsSigGen0->enabled=1;
+ pChan->spsSigGen0->discounterl=0;
+ }
+ }
+ else if(pChan->smode==SMODE_NULL && pChan->txcodedefaultsmode==SMODE_CTCSS && !pChan->b.txCtcssInhibit)
+ {
+ TRACEC(1,("txPtt Encode txcodedefaultsmode==SMODE_CTCSS %f\n",pChan->txctcssdefault_value));
+ pChan->spsSigGen0->freq=pChan->txctcssdefault_value*10;
+ pChan->spsSigGen0->option=1;
+ pChan->spsSigGen0->enabled=1;
+ pChan->spsSigGen0->discounterl=0;
+ pChan->smode=SMODE_CTCSS;
+ pChan->smodetimer=pChan->smodetime;
+ }
+ else if(pChan->txcodedefaultsmode==SMODE_NULL||pChan->b.txCtcssInhibit)
+ {
+ TRACEC(1,("txPtt Encode txcodedefaultsmode==SMODE_NULL\n"));
+ }
+ else
+ {
+ printf ("ERROR: txPttIn=%i NOT HANDLED PROPERLY.\n",pChan->txPttIn);
+ TRACEC(1,("ERROR: txPttIn=%i NOT HANDLED PROPERLY.\n",pChan->txPttIn));
+ }
+
+ pChan->txState = CHAN_TXSTATE_ACTIVE;
pChan->txPttOut=1;
- pChan->spsSigGen0->freq=pChan->txCtcssFreq*10;
- pChan->spsSigGen0->option=1;
- pChan->spsSigGen0->enabled=1;
+
+ pChan->txsettletimer=pChan->txsettletime;
+
if(pChan->spsTxOutA)pChan->spsTxOutA->enabled=1;
if(pChan->spsTxOutB)pChan->spsTxOutB->enabled=1;
if(pChan->spsTxLsdLpf)pChan->spsTxLsdLpf->enabled=1;
- TRACEX((" TxOn\n"));
+ if(pChan->txfreq)pChan->b.reprog=1;
+ TRACEC(1,("PmrRx() TxOn\n"));
+ }
+ else if(pChan->txPttIn && pChan->txState==CHAN_TXSTATE_ACTIVE)
+ {
+ // pChan->smode=SMODE_CTCSS;
+ pChan->smodetimer=pChan->smodetime;
}
- else if(!pChan->txPttIn && pChan->txState==2)
+ else if(!pChan->txPttIn && pChan->txState==CHAN_TXSTATE_ACTIVE)
{
- if( pChan->txTocType==TOC_NONE || !pChan->txCtcssFreq )
+ TRACEC(1,("txPttIn==0 from CHAN_TXSTATE_ACTIVE\n"));
+ if(pChan->smode==SMODE_CTCSS && !pChan->b.txCtcssInhibit)
{
- hit=1;
- TRACEX((" Tx Off Immediate.\n"));
- }
- else if(pChan->txCtcssFreq && pChan->txTocType==TOC_NOTONE)
+ if( pChan->txTocType==TOC_NONE || !pChan->b.ctcssTxEnable )
+ {
+ TRACEC(1,("Tx Off Immediate.\n"));
+ pChan->spsSigGen0->option=3;
+ pChan->txBufferClear=3;
+ pChan->txState=CHAN_TXSTATE_FINISHING;
+ }
+ else if(pChan->txTocType==TOC_NOTONE)
+ {
+ pChan->txState=CHAN_TXSTATE_TOC;
+ pChan->txHangTime=TOC_NOTONE_TIME/MS_PER_FRAME;
+ pChan->spsSigGen0->option=3;
+ TRACEC(1,("Tx Turn Off No Tone Start.\n"));
+ }
+ else
+ {
+ pChan->txState=CHAN_TXSTATE_TOC;
+ pChan->txHangTime=0;
+ pChan->spsSigGen0->option=2;
+ TRACEC(1,("Tx Turn Off Phase Shift Start.\n"));
+ }
+ }
+ else
{
- pChan->txState=3;
- pChan->txHangTime=TOC_NOTONE_TIME/MS_PER_FRAME;
- pChan->spsSigGen0->option=3;
- TRACEX((" Tx Turn Off No Tone Start.\n"));
+ pChan->txBufferClear=3;
+ pChan->txState=CHAN_TXSTATE_FINISHING;
+ TRACEC(1,("Tx Off No SMODE to Finish.\n"));
}
- else
+ }
+ else if(pChan->txState==CHAN_TXSTATE_TOC)
+ {
+ if( pChan->txPttIn && pChan->smode==SMODE_CTCSS )
{
- pChan->txState=3;
- pChan->txHangTime=0;
- pChan->spsSigGen0->option=2;
- TRACEX((" Tx Turn Off Phase Shift Start.\n"));
+ TRACEC(1,("Tx Key During HangTime\n"));
+ pChan->txState = CHAN_TXSTATE_ACTIVE;
+ pChan->spsSigGen0->option=1;
+ pChan->spsSigGen0->enabled=1;
+ pChan->spsSigGen0->discounterl=0;
+ hit=0;
}
- }
- else if(pChan->txState==3)
- {
- if(pChan->txHangTime)
+ else if(pChan->txHangTime)
{
- if(--pChan->txHangTime==0)hit=1;
-
+ if(--pChan->txHangTime==0)pChan->txState=CHAN_TXSTATE_FINISHING;
}
else if(pChan->txHangTime<=0 && pChan->spsSigGen0->state==0)
- {
- hit=1;
- TRACEX((" Tx Off TOC.\n"));
- }
- if(pChan->txPttIn)
{
- TRACEX((" Tx Key During HangTime\n"));
- if((pChan->txTocType==TOC_PHASE)||(pChan->txTocType==TOC_NONE))
- {
- pChan->txState = 2;
- hit=0;
- }
+ pChan->txBufferClear=3;
+ pChan->txState=CHAN_TXSTATE_FINISHING;
+ TRACEC(1,("Tx Off TOC.\n"));
}
}
-
- if( pChan->txCpuSaver && !hit && !pChan->txPttIn && !pChan->txPttOut && pChan->txState==0 ) return (1);
+ else if(pChan->txState==CHAN_TXSTATE_FINISHING)
+ {
+ if(--pChan->txBufferClear<=0)
+ pChan->txState=CHAN_TXSTATE_COMPLETE;
+ }
+ else if(pChan->txState==CHAN_TXSTATE_COMPLETE)
+ {
+ hit=1;
+ }
+ } // end of if SMODE==LSD
if(hit)
{
pChan->txPttOut=0;
- pChan->txState=0;
+ pChan->spsSigGen0->option=3;
+ pChan->txState=CHAN_TXSTATE_IDLE;
if(pChan->spsTxLsdLpf)pChan->spsTxLsdLpf->option=3;
if(pChan->spsTxOutA)pChan->spsTxOutA->option=3;
if(pChan->spsTxOutB)pChan->spsTxOutB->option=3;
- TRACEX((" Tx Off hit.\n"));
+ if(pChan->rxfreq||pChan->txfreq)pChan->b.reprog=1;
+ TRACEC(1,("Tx Off hit.\n"));
+ }
+
+ if(pChan->b.reprog)
+ {
+ pChan->b.reprog=0;
+ progdtx(pChan);
}
- if(pChan->spsSigGen0)
+ if(pChan->txsettletimer && pChan->txPttHid )
{
- pChan->spsSigGen0->sigProc(pChan->spsSigGen0);
- pmr_sps=pChan->spsSigGen0->nextSps;
- i=0;
- while(pmr_sps!=NULL && pmr_sps!=0)
+ pChan->txsettletimer-=MS_PER_FRAME;
+ if(pChan->txsettletimer<0)pChan->txsettletimer=0;
+ }
+
+ // enable this after we know everything else is working
+ if( pChan->txCpuSaver &&
+ !pChan->txPttIn && !pChan->txPttOut &&
+ pChan->txState==CHAN_TXSTATE_IDLE &&
+ !pChan->dd.b.doitnow
+ )
+ {
+ if(!pChan->b.txhalted)
{
- TRACEX((" PmrTx() subaudible sps %i\n",i++));
- //printf(" CTCSS ENCODE %i %i\n",pChan->spsSigGen0->freq,pChan->spsSigGen0->outputGain);
- pmr_sps->sigProc(pmr_sps);
- pmr_sps = (t_pmr_sps *)(pmr_sps->nextSps);
+ pChan->b.txhalted=1;
+ TRACEC(1,("PmrRx() tx sps halted\n"));
}
}
+ else if(pChan->b.txhalted)
+ {
+ pChan->dd.b.doitnow=1;
+ pChan->b.txhalted=0;
+ TRACEC(1,("PmrRx() tx sps un-halted\n"));
+ }
+
+ if(pChan->b.txhalted)return(1);
+
+ if(pChan->b.startSpecialTone)
+ {
+ pChan->b.startSpecialTone=0;
+ pChan->spsSigGen1->option=1;
+ pChan->spsSigGen1->enabled=1;
+ pChan->b.doingSpecialTone=1;
+ }
+ else if(pChan->b.stopSpecialTone)
+ {
+ pChan->b.stopSpecialTone=0;
+ pChan->spsSigGen1->option=0;
+ pChan->b.doingSpecialTone=0;
+ pChan->spsSigGen1->enabled=0;
+ }
+ else if(pChan->b.doingSpecialTone)
+ {
+ pChan->spsSigGen1->sink=outputtx;
+ pChan->spsSigGen1->sigProc(pChan->spsSigGen1);
+ for(i=0;i<(pChan->nSamplesTx*2*6);i+=2)outputtx[i+1]=outputtx[i];
+ return 0;
+ }
+
+ if(pChan->spsSigGen0 && pChan->spsSigGen0->enabled )
+ {
+ pChan->spsSigGen0->sigProc(pChan->spsSigGen0);
+ }
if(pChan->spsSigGen1 && pChan->spsSigGen1->enabled)
{
pChan->spsSigGen1->sigProc(pChan->spsSigGen1);
}
+ #ifdef XPMRX_H
+ pChan->spsLsdGen->sigProc(pChan->spsLsdGen); // maw sph ???
+ #endif
+
+ // Do Low Speed Data Low Pass Filter
+ pChan->spsTxLsdLpf->sigProc(pChan->spsTxLsdLpf);
+
// Do Voice
pmr_sps=pChan->spsTx;
- if(!pChan->spsSigGen1->enabled)pmr_sps->source=input;
+
+ // get tx data from de-drift process
+ pChan->dd.option=0;
+ pChan->dd.ptr=pChan->pTxBase;
+ dedrift(pChan);
+
+ // tx process
+ if(!pChan->spsSigGen1->enabled)
+ {
+ pmr_sps->source=pChan->pTxBase;
+ }
else input=pmr_sps->source;
- if(output!=NULL)
+ if(outputtx!=NULL)
{
- if(pChan->spsTxOutA)pChan->spsTxOutA->sink=output;
- if(pChan->spsTxOutB)pChan->spsTxOutB->sink=output;
+ if(pChan->spsTxOutA)pChan->spsTxOutA->sink=outputtx;
+ if(pChan->spsTxOutB)pChan->spsTxOutB->sink=outputtx;
}
i=0;
while(pmr_sps!=NULL && pmr_sps!=0)
{
- TRACEX((" PmrTx() sps %i\n",i++));
+ //TRACEF(1,("PmrTx() sps %i\n",i++));
pmr_sps->sigProc(pmr_sps);
pmr_sps = (t_pmr_sps *)(pmr_sps->nextSps);
}
-
+ //TRACEF(1,("PmrTx() - outputs \n"));
if(pChan->txMixA==TX_OUT_OFF || !pChan->txPttOut){
- for(i=0;i<pChan->nSamplesTx*2*6;i+=2)output[i]=0;
+ for(i=0;i<pChan->nSamplesTx*2*6;i+=2)outputtx[i]=0;
}
if(pChan->txMixB==TX_OUT_OFF || !pChan->txPttOut ){
- for(i=0;i<pChan->nSamplesTx*2*6;i+=2)output[i+1]=0;
+ for(i=0;i<pChan->nSamplesTx*2*6;i+=2)outputtx[i+1]=0;
}
- #if XPMR_DEBUG0 == 1
- if(pChan->b.txCapture)
+ #if XPMR_PPTP == 1
+ if( pChan->b.radioactive && pChan->b.pptp_p1!=pChan->txPttOut)
{
- i16 ii=0;
- for(i=0;i<pChan->nSamplesTx;i++)
+ pChan->b.pptp_p1=pChan->txPttOut;
+ pptp_write(0,pChan->b.pptp_p1);
+ }
+ #endif
+
+ #if XPMR_DEBUG0 == 1
+ // TRACEF(1,("PmrRx() - debug outputs \n"));
+ if(pChan->b.rxCapture){
+ for(i=0;i<pChan->nSamplesRx;i++)
{
- pChan->ptxDebug[ii++]=input[i];
- pChan->ptxDebug[ii++]=output[i*2*6];
- pChan->ptxDebug[ii++]=output[(i*2*6)+1];
- pChan->ptxDebug[ii++]=pChan->txPttIn*8192;
-
- pChan->ptxDebug[ii++]=pChan->txPttOut*8192;
- if(pChan->txHpfEnable)pChan->ptxDebug[ii++]=pChan->pTxHpf[i];
- else pChan->ptxDebug[ii++]=0;
- if(pChan->txPreEmpEnable)pChan->ptxDebug[ii++]=pChan->pTxPreEmp[i];
- else pChan->ptxDebug[ii++]=0;
- if(pChan->txLimiterEnable)pChan->ptxDebug[ii++]=pChan->pTxLimiter[i];
- else pChan->ptxDebug[ii++]=0;
-
- pChan->ptxDebug[ii++]=pChan->pTxLsd[i];
- pChan->ptxDebug[ii++]=pChan->pTxLsdLpf[i];
- pChan->ptxDebug[ii++]=pChan->pTxComposite[i];
- pChan->ptxDebug[ii++]=pChan->pSigGen1[i];
-
- #if 1
- pChan->ptxDebug[ii++]=pChan->ptxDebug0[i];
- pChan->ptxDebug[ii++]=pChan->ptxDebug1[i];
- pChan->ptxDebug[ii++]=pChan->ptxDebug2[i];
- pChan->ptxDebug[ii++]=pChan->ptxDebug3[i];
- #else
- pChan->ptxDebug[ii++]=0;
- pChan->ptxDebug[ii++]=0;
- pChan->ptxDebug[ii++]=0;
- pChan->ptxDebug[ii++]=0;
- #endif
+ pChan->pRxDemod[i]=input[i*2*6];
+ pChan->pTstTxOut[i]=outputtx[i*2*6+0]; // txa
+ //pChan->pTstTxOut[i]=outputtx[i*2*6+1]; // txb
+ TSCOPE((RX_NOISE_TRIG, pChan->sdbg, i, (pChan->rxCarrierDetect*XPMR_TRACE_AMP)-XPMR_TRACE_AMP/2));
+ TSCOPE((RX_CTCSS_DECODE, pChan->sdbg, i, pChan->rxCtcss->decode*(M_Q14/CTCSS_NUM_CODES)));
+ TSCOPE((RX_SMODE, pChan->sdbg, i, pChan->smode*(XPMR_TRACE_AMP/4)));
+ TSCOPE((TX_PTT_IN, pChan->sdbg, i, (pChan->txPttIn*XPMR_TRACE_AMP)-XPMR_TRACE_AMP/2));
+ TSCOPE((TX_PTT_OUT, pChan->sdbg, i, (pChan->txPttOut*XPMR_TRACE_AMP)-XPMR_TRACE_AMP/2));
+ TSCOPE((TX_DEDRIFT_LEAD, pChan->sdbg, i, pChan->dd.lead*8));
+ TSCOPE((TX_DEDRIFT_ERR, pChan->sdbg, i, pChan->dd.err*16));
+ TSCOPE((TX_DEDRIFT_FACTOR, pChan->sdbg, i, pChan->dd.factor*16));
+ TSCOPE((TX_DEDRIFT_DRIFT, pChan->sdbg, i, pChan->dd.drift*16));
}
- }
+ }
#endif
+ strace2(pChan->sdbg);
+ TRACEC(5,("PmrRx() return cd=%i smode=%i txPttIn=%i txPttOut=%i \n",pChan->rxCarrierDetect,pChan->smode,pChan->txPttIn,pChan->txPttOut));
return 0;
}
+/*
+ parallel binary programming of an RF Transceiver*/
+
+void ppbinout (u8 chan)
+{
+#if(DTX_PROG == 1)
+ i32 i;
+
+ if (ppdrvdev == 0)
+ ppdrvdev = open("/dev/ppdrv_device", 0);
+
+ if (ppdrvdev < 0)
+ {
+ ast_log(LOG_ERROR, "open /dev/ppdrv_ppdrvdev returned %i\n",ppdrvdev);
+ return;
+ }
+
+ i=0;
+ if(chan&0x01)i|=BIN_PROG_0;
+ if(chan&0x02)i|=BIN_PROG_1;
+ if(chan&0x04)i|=BIN_PROG_2;
+ if(chan&0x08)i|=BIN_PROG_3;
+
+ ioctl(ppdrvdev, PPDRV_IOC_PINMODE_OUT, BIN_PROG_3|BIN_PROG_2|BIN_PROG_1|BIN_PROG_0);
+ //ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, BIN_PROG_3|BIN_PROG_2|BIN_PROG_1|BIN_PROG_0);
+ //ioctl(ppdrvdev, PPDRV_IOC_PINSET, i );
+ ioctl(ppdrvdev, PPDRV_IOC_PINSET, BIN_PROG_3|BIN_PROG_2|BIN_PROG_1|BIN_PROG_0);
+ ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, i );
+
+ // ioctl(ppdrvdev, PPDRV_IOC_PINSET, BIN_PROG_3|BIN_PROG_2|BIN_PROG_1|BIN_PROG_0 );
+ ast_log(LOG_NOTICE, "mask=%i 0x%x\n",i,i);
+#endif
+}
+/*
+ SPI Programming of an RF Transceiver
+ need to add permissions check and mutex
+*/
+/*
+ need to add permissions check and mutex
+*/
+void ppspiout (u32 spidata)
+{
+#if(DTX_PROG == 1)
+ static char firstrun=0;
+ i32 i,ii;
+ u32 bitselect;
+
+ if (ppdrvdev < 0)
+ {
+ ast_log(LOG_ERROR, "no parallel port permission ppdrvdev %i\n",ppdrvdev);
+ exit(0);
+ }
+
+ ioctl(ppdrvdev, PPDRV_IOC_PINMODE_OUT, DTX_CLK | DTX_DATA | DTX_ENABLE | DTX_TXPWR | DTX_TX );
+ ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_CLK | DTX_DATA | DTX_ENABLE | DTX_TXPWR | DTX_TX );
+
+ if(firstrun==0)
+ {
+ firstrun=1;
+ for(ii=0;ii<PP_BIT_TIME*200;ii++);
+ }
+ else
+ {
+ for(ii=0;ii<PP_BIT_TIME*4;ii++);
+ }
+
+ bitselect=0x00080000;
+
+ for(i=0;i<(PP_REG_LEN-12);i++)
+ {
+ if((bitselect&spidata))
+ ioctl(ppdrvdev, PPDRV_IOC_PINSET, DTX_DATA );
+ else
+ ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_DATA );
+
+ for(ii=0;ii<PP_BIT_TIME;ii++);
+
+ ioctl(ppdrvdev, PPDRV_IOC_PINSET, DTX_CLK );
+ for(ii=0;ii<PP_BIT_TIME;ii++);
+ ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_CLK );
+ for(ii=0;ii<PP_BIT_TIME;ii++);
+
+ bitselect=(bitselect>>1);
+ }
+ ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_CLK | DTX_DATA );
+ ioctl(ppdrvdev, PPDRV_IOC_PINSET, DTX_ENABLE );
+ for(ii=0;ii<PP_BIT_TIME;ii++);
+ ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_ENABLE );
+#endif
+}
+/*
+ mutex needed
+ now assumes calling thread secures permissions
+ could set up a separate thread to program the radio? yuck!
+
+*/
+void progdtx(t_pmr_chan *pChan)
+{
+#if(DTX_PROG == 1)
+ //static u32 progcount=0;
+
+ u32 reffreq;
+ u32 stepfreq;
+ u32 rxiffreq;
+ u32 synthfreq;
+ u32 shiftreg;
+ u32 tmp;
+
+ TRACEC(1,("\nprogdtx() %i %i %i\n",pChan->rxfreq,pChan->txfreq,0));
+
+ if (ppdrvdev == 0)
+ ppdrvdev = open("/dev/ppdrv_device", 0);
+
+ if (ppdrvdev < 0)
+ {
+ ast_log(LOG_ERROR, "open /dev/ppdrv_ppdrvdev returned %i\n",ppdrvdev);
+ exit(0);
+ }
+
+ if(pChan->rxfreq>200000000)
+ {
+ reffreq=16012500;
+ stepfreq=12500;
+ rxiffreq=21400000;
+ }
+ else
+ {
+ reffreq=16000000;
+ stepfreq=5000;
+ rxiffreq=10700000;
+ }
+
+ shiftreg=(reffreq/stepfreq)<<1;
+ shiftreg=shiftreg|0x00000001;
+
+ ppspiout(shiftreg);
+
+ if(pChan->txPttOut)
+ synthfreq=pChan->txfreq;
+ else
+ synthfreq=pChan->rxfreq-rxiffreq;
+
+ shiftreg=(synthfreq/stepfreq)<<1;
+ tmp=(shiftreg&0xFFFFFF80)<<1;
+ shiftreg=tmp+(shiftreg&0x0000007F);
+
+ ppspiout(shiftreg);
+
+ ioctl(ppdrvdev, PPDRV_IOC_PINMODE_OUT, DTX_CLK | DTX_DATA | DTX_ENABLE | DTX_TXPWR | DTX_TX );
+ ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_CLK | DTX_DATA | DTX_ENABLE );
+
+ if(pChan->txPttOut)
+ {
+ ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_TXPWR );
+ ioctl(ppdrvdev, PPDRV_IOC_PINSET, DTX_TX );
+ if(pChan->txpower && 0) ioctl(ppdrvdev, PPDRV_IOC_PINSET, DTX_TXPWR );
+ }
+ else
+ {
+ ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_TX | DTX_TXPWR );
+ }
+#endif
+}
+
+/* dedrift
+ reconciles clock differences between the usb adapter and
+ asterisk's frame rate clock
+ take out all accumulated drift error on these events:
+ before transmitter on
+ when ptt release from mobile units detected
+*/
+void dedrift(t_pmr_chan *pChan)
+{
+ TRACEC(5,("dedrift()\n"));
+
+ if(pChan->dd.option==9)
+ {
+ TRACEF(1,("dedrift(9)\n"));
+ pChan->dd.framesize=DDB_FRAME_SIZE;
+ pChan->dd.frames=DDB_FRAMES_IN_BUFF;
+ pChan->dd.buffersize = pChan->dd.frames * pChan->dd.framesize;
+ pChan->dd.buff=calloc(DDB_FRAME_SIZE*DDB_FRAMES_IN_BUFF,2);
+ pChan->dd.modulus=DDB_ERR_MODULUS;
+ pChan->dd.inputindex=0;
+ pChan->dd.outputindex=0;
+ pChan->dd.skew = pChan->dd.lead=0;
+ pChan->dd.z1=0;
+ pChan->dd.debug=0;
+ pChan->dd.debugcnt=0;
+ pChan->dd.lock=pChan->dd.b.txlock=pChan->dd.b.rxlock=0;
+ pChan->dd.initcnt=2;
+ pChan->dd.timer=10000/20;
+ pChan->dd.drift=0;
+ pChan->dd.factor=pChan->dd.x1 = pChan->dd.x0 = pChan->dd.y1 = pChan->dd.y0 = 0;
+ pChan->dd.txframecnt=pChan->dd.rxframecnt=0;
+ // clear the buffer too!
+ return;
+ }
+ else if(pChan->dd.option==8)
+ {
+ free(pChan->dd.buff);
+ pChan->dd.lock=0;
+ pChan->dd.b.txlock=pChan->dd.b.rxlock=0;
+ return;
+ }
+ else if(pChan->dd.initcnt==0)
+ {
+ void *vptr;
+ i16 inputindex;
+ i16 indextweak;
+ i32 accum;
+
+ inputindex = pChan->dd.inputindex;
+ pChan->dd.skew = pChan->dd.txframecnt-pChan->dd.rxframecnt;
+ pChan->dd.rxframecnt++;
+
+ // pull data from buffer
+ if( (pChan->dd.outputindex + pChan->dd.framesize) > pChan->dd.buffersize )
+ {
+ i16 dofirst,donext;
+
+ dofirst = pChan->dd.buffersize - pChan->dd.outputindex;
+ donext = pChan->dd.framesize - dofirst;
+ vptr = (void*)(pChan->dd.ptr);
+ memcpy(vptr,(void*)(pChan->dd.buff + pChan->dd.outputindex),dofirst*2);
+ vptr=(void*)(pChan->dd.ptr + dofirst);
+ memcpy(vptr,(void*)(pChan->dd.buff),donext*2);
+ }
+ else
+ {
+ memcpy(pChan->dd.ptr,(void*)(pChan->dd.buff + pChan->dd.outputindex),pChan->dd.framesize*2);
+ }
+
+ // compute clock error and correction factor
+ if(pChan->dd.outputindex > inputindex)
+ {
+ pChan->dd.lead = (inputindex + pChan->dd.buffersize) - pChan->dd.outputindex;
+ }
+ else
+ {
+ pChan->dd.lead = inputindex - pChan->dd.outputindex;
+ }
+ pChan->dd.err = pChan->dd.lead - (pChan->dd.buffersize/2);
+
+ // WinFilter, IIR Fs=50, Fc=0.1
+ const i32 a0 = 26231;
+ const i32 a1 = 26231;
+ const i32 b0 = 32768;
+ const i32 b1 = -32358;
+ const i32 dg = 128;
+ pChan->dd.x1 = pChan->dd.x0;
+ pChan->dd.y1 = pChan->dd.y0;
+ pChan->dd.x0 = pChan->dd.err;
+ pChan->dd.y0 = a0 * pChan->dd.x0;
+ pChan->dd.y0 += (a1 * pChan->dd.x1 - (b1 * pChan->dd.y1));
+ pChan->dd.y0 /= b0;
+ accum = pChan->dd.y0/dg;
+
+ pChan->dd.factor=accum;
+ indextweak=0;
+
+ #if 1
+ // event sync'd correction
+ if(pChan->dd.b.doitnow)
+ {
+ pChan->dd.b.doitnow=0;
+ indextweak=pChan->dd.factor;
+ pChan->dd.factor = pChan->dd.x1 = pChan->dd.x0 = pChan->dd.y1 = pChan->dd.y0 = 0;
+ pChan->dd.timer=20000/MS_PER_FRAME;
+ }
+ // coarse lead adjustment if really far out of range
+ else if( pChan->dd.lead >= pChan->dd.framesize*(DDB_FRAMES_IN_BUFF-2) )
+ {
+ pChan->dd.factor = pChan->dd.x1 = pChan->dd.x0 = pChan->dd.y1 = pChan->dd.y0 = 0;
+ indextweak += (pChan->dd.framesize*5/4);
+ }
+ else if(pChan->dd.lead <= pChan->dd.framesize*2 )
+ {
+ pChan->dd.factor = pChan->dd.x1 = pChan->dd.x0 = pChan->dd.y1 = pChan->dd.y0 = 0;
+ indextweak -= (pChan->dd.framesize*5/4);
+ }
+ #endif
+
+ #if 1
+ if(pChan->dd.timer>0)pChan->dd.timer--;
+ if(pChan->dd.timer==0 && abs(pChan->dd.factor)>=16)
+ {
+ indextweak=pChan->dd.factor;
+ pChan->dd.factor = pChan->dd.x1 = pChan->dd.x0 = pChan->dd.y1 = pChan->dd.y0 = 0;
+ pChan->dd.timer=20000/MS_PER_FRAME;
+ }
+ #endif
+
+ #if XPMR_DEBUG0 == 1
+ if(indextweak!=0)TRACEF(4,("%08i indextweak %+4i %+4i %+5i %5i %5i %5i %+4i\n",pChan->dd.rxframecnt, indextweak, pChan->dd.err, accum, inputindex, pChan->dd.outputindex, pChan->dd.lead, pChan->dd.skew));
+ #endif
+
+ // set the output index based on lead and clock offset
+ pChan->dd.outputindex = (pChan->dd.outputindex + pChan->dd.framesize + indextweak)%pChan->dd.buffersize;
+ }
+}
+/*
+*/
+void dedrift_write(t_pmr_chan *pChan, i16 *src )
+{
+ void *vptr;
+
+ TRACEF(5,("dedrift_write()\n"));
+ vptr = pChan->dd.buff + pChan->dd.inputindex;
+ memcpy(vptr, src, pChan->dd.framesize*2);
+ pChan->dd.inputindex = (pChan->dd.inputindex + pChan->dd.framesize) % pChan->dd.buffersize;
+ pChan->dd.txframecnt++;
+ if(pChan->dd.initcnt!=0)pChan->dd.initcnt--;
+ pChan->dd.accum+=pChan->dd.framesize;
+}
+
/* end of file */
diff --git a/channels/xpmr/xpmr.h b/channels/xpmr/xpmr.h
index b39ce23d6..49f5148fa 100755
--- a/channels/xpmr/xpmr.h
+++ b/channels/xpmr/xpmr.h
@@ -5,15 +5,25 @@
*
* 20070808 1235 Steven Henke, W9SH, sph@xelatec.com
*
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This version may be optionally licenced under the GNU LGPL licence.
+ *
+ * A license has been granted to Digium (via disclaimer) for the use of
+ * this code.
*
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
*/
/*! \file
@@ -23,25 +33,73 @@
* \author Steven Henke, W9SH <sph@xelatec.com> Xelatec, LLC
*/
-#ifndef XPMR_H
-#define XPMR_H 1
+#ifndef XPMR_H
+#define XPMR_H 1
+
+#define XPMR_DEV 0 // when running in test mode
+
+#define XPMR_TRACE_LEVEL 0
+
+#ifdef RADIO_RTX
+#define DTX_PROG 1 // rf transceiver module
+#define XPMR_PPTP 0 // parallel port test probe
+#else
+#define DTX_PROG 0
+#define XPMR_PPTP 0
+#endif
+
+#if (DTX_PROG == 1) || XPMR_PPTP == 1
+#include <parapindriver.h>
+#endif
#ifdef CHAN_USBRADIO
#define XPMR_DEBUG0 1
-#define XPMR_TRACE 0
+#define XPMR_TRACE 1
+#define TRACEO(level,a) { if ( o->tracelevel >= level ) {printf a;} }
#else
#define XPMR_DEBUG0 1
#define XPMR_TRACE 1
+#define TRACEO(level,a)
#endif
+
+#define LSD_DFS 5
+#define LSD_DFD 1
+
+#if(XPMR_DEBUG0 == 1)
+#define XPMR_DEBUG_CHANS 16
+#define TSCOPE(a) {strace a;}
+#else
+#define XPMR_DEBUG_CHANS 0
+#define TSCOPE(a)
+#endif
+
+#define XPMR_TRACE_AMP 8192
+
+// TRACEM(3,TSYS_LSD,("pmr_lsdctl_exec() RX FRAME UNPROCESSED.\n"));
#if(XPMR_TRACE == 1)
#define TRACEX(a) {printf a;}
#define TRACEXL(a) {printf("%s @ %u : ",__FILE__ ,__LINE__); printf a; }
-#define TRACEXT(a) { struct timeval hack; gettimeofday(&hack,NULL); printf("%ld.",hack.tv_sec%100000); printf("%i : ",(int)hack.tv_usec); printf a; }
+#define TRACEXT(a) {struct timeval hack; gettimeofday(&hack,NULL); printf("%ld.",hack.tv_sec%100000); printf("%i : ",(int)hack.tv_usec); printf a; }
+#define TRACEXR(a) {printf a;}
+#define TRACEC(level,a) {if(pChan->tracelevel>=level){printf("%08i ",pChan->frameCountRx);printf a;} }
+#define TRACEF(level,a) {if(pChan->tracelevel>=level){printf a;} }
+#define TRACEJ(level,a) {if(XPMR_TRACE_LEVEL>=level){printf a;} }
+#define TRACES(level,a) {if(mySps->parentChan->tracelevel >= level){printf a;} }
+#define TRACET(level,a) {if(pChan->tracelevel>=level){printf("%08i %02i",pChan->frameCountRx,pChan->rptnum);printf a;} }
+#define TRACEXR(a) {printf a;}
+#define TRACEM(level,sys,a) {if(pChan->tracelevel>=level || (pChan->tracesys[sys])){printf a;} }
#else
#define TRACEX(a)
#define TRACEXL(a)
#define TRACEXT(a)
+#define TRACEC(level,a)
+#define TRACEF(level,a)
+#define TRACEJ(level,a)
+#define TRACES(level,a)
+#define TRACET(level,a)
+#define TRACEXR(a)
+#define TRACEM(level,sys,a)
#endif
#define i8 int8_t
@@ -52,11 +110,18 @@
#define u32 u_int32_t
#define i64 int64_t
#define u64 u_int64_t
-
+
+#define M_Q31 0x80000000 //
+#define M_Q30 0x40000000 //
+#define M_Q29 0x20000000 //
+#define M_Q28 0x10000000 //
+#define M_Q27 0x08000000 //
+#define M_Q26 0x04000000 //
+#define M_Q25 0x02000000 //
#define M_Q24 0x01000000 //
#define M_Q23 0x00800000 //
#define M_Q22 0x00400000 //
-#define M_Q21 0x00200000 //
+#define M_Q21 0x00200000 // undsoweiter
#define M_Q20 0x00100000 // 1048576
#define M_Q19 0x00080000 // 524288
#define M_Q18 0x00040000 // 262144
@@ -86,8 +151,11 @@
#define SAMPLES_PER_BLOCK 160
#define MS_PER_FRAME 20
+#define SAMPLES_PER_MS 8
-#define CTCSS_NUM_CODES 38
+#define CTCSS_NULL -1
+#define CTCSS_RXONLY -2
+#define CTCSS_NUM_CODES 38 // 0 - 37
#define CTCSS_SCOUNT_MUL 100
#define CTCSS_INTEGRATE 3932 // 32767*.120 // 120/1000 // 0.120
#define CTCSS_INPUT_LIMIT 1000
@@ -98,6 +166,61 @@
#define CTCSS_TURN_OFF_SHIFT 240 // degrees
#define TOC_NOTONE_TIME 600 // ms
+#define DDB_FRAME_SIZE 160 // clock de-drift defaults
+#define DDB_FRAMES_IN_BUFF 8
+#define DDB_ERR_MODULUS 10000
+
+#define DCS_TURN_OFF_TIME 180
+
+#define NUM_TXLSD_FRAMEBUFFERS 4
+
+#define CHAN_TXSTATE_IDLE 0
+#define CHAN_TXSTATE_ACTIVE 1
+#define CHAN_TXSTATE_TOC 2
+#define CHAN_TXSTATE_HANGING 3
+#define CHAN_TXSTATE_FINISHING 4
+#define CHAN_TXSTATE_COMPLETE 5
+#define CHAN_TXSTATE_USURPED 9
+
+#define SMODE_NULL 0
+#define SMODE_CARRIER 1
+#define SMODE_CTCSS 2
+#define SMODE_DCS 3
+#define SMODE_LSD 4
+#define SMODE_MPT 5
+#define SMODE_DST 6
+#define SMODE_P25 7
+#define SMODE_MDC 8
+
+
+#define SPS_OPT_START 1
+#define SPS_OPT_STOP 2
+#define SPS_OPT_TURNOFF 3
+#define SPS_OPT_STOPNOW 4
+
+#define SPS_STAT_STOPPED 0
+#define SPS_STAT_STARTING 1
+#define SPS_STAT_RUNNING 2
+#define SPS_STAT_HALTING 3
+
+
+#define PP_BIT_TEST 6
+#define PP_REG_LEN 32
+#define PP_BIT_TIME 100000
+
+#define DTX_CLK LP_PIN02
+#define DTX_DATA LP_PIN03
+#define DTX_ENABLE LP_PIN04
+#define DTX_TX LP_PIN05 // only used on older mods
+#define DTX_TXPWR LP_PIN06 // not used
+#define DTX_TP1 LP_PIN07 // not used
+#define DTX_TP2 LP_PIN08 // not used
+
+#define BIN_PROG_0 LP_PIN06
+#define BIN_PROG_1 LP_PIN07
+#define BIN_PROG_2 LP_PIN08
+#define BIN_PROG_3 LP_PIN09
+
#ifndef CHAN_USBRADIO
enum {RX_AUDIO_NONE,RX_AUDIO_SPEAKER,RX_AUDIO_FLAT};
enum {TX_AUDIO_NONE,TX_AUDIO_FLAT,TX_AUDIO_FILTERED,TX_AUDIO_PROC};
@@ -108,6 +231,130 @@ enum {TX_OUT_OFF,TX_OUT_VOICE,TX_OUT_LSD,TX_OUT_COMPOSITE,TX_OUT_AUX};
enum {TOC_NONE,TOC_PHASE,TOC_NOTONE};
#endif
+enum dbg_pts {
+
+RX_INPUT,
+RX_NOISE_AMP,
+RX_NOISE_TRIG,
+
+RX_CTCSS_LPF,
+RX_CTCSS_CENTER,
+RX_CTCSS_NRZ,
+RX_CTCSS_CLK,
+RX_CTCSS_P0,
+RX_CTCSS_P1,
+RX_CTCSS_ACCUM,
+RX_CTCSS_DVDT,
+RX_CTCSS_DECODE,
+
+RX_DCS_CENTER,
+RX_DCS_DEC,
+RX_DCS_DIN,
+RX_DCS_CLK,
+RX_DCS_DAT,
+
+RX_LSD_LPF,
+RX_LSD_CLK,
+RX_LSD_DAT,
+RX_LSD_DEC,
+
+RX_LSD_CENTER,
+RX_LSD_SYNC,
+RX_LSD_STATE,
+RX_LSD_ERR,
+RX_LSD_INTE,
+
+RX_SMODE,
+
+TX_PTT_IN,
+TX_PTT_OUT,
+
+TX_DEDRIFT_LEAD,
+TX_DEDRIFT_ERR,
+TX_DEDRIFT_FACTOR,
+TX_DEDRIFT_DRIFT,
+TX_DEDRIFT_TWIDDLE,
+
+TX_CTCSS_GEN,
+
+TX_SIGGEN_0,
+
+TX_DCS_CLK,
+TX_DCS_DAT,
+TX_DCS_LPF,
+
+TX_LSD_CLK,
+TX_LSD_DAT,
+TX_LSD_GEN,
+TX_LSD_LPF,
+
+TX_NET_INT,
+TX_VOX_HPF,
+TX_VOX_LIM,
+
+TX_VOX_LPF,
+
+TX_OUT_A,
+TX_OUT_B,
+
+NUM_DEBUG_PTS
+};
+
+typedef struct
+{
+ i16 mode;
+ i16 point[NUM_DEBUG_PTS];
+ i16 trace[16];
+ i16 scale[16];
+ i16 offset[16];
+ i16 buffer[16 * SAMPLES_PER_BLOCK]; // allocate for rx and tx
+ i16 *source[16];
+} t_sdbg;
+
+typedef struct
+{
+ i16 lock;
+ i16 option; // 1 = data in, 0 = data out
+ i16 debug;
+ i16 debugcnt;
+ i32 rxframecnt;
+ i32 txframecnt;
+
+ i32 skew;
+
+ i16 frames;
+ i16 framesize;
+ i16 buffersize;
+
+ i32 timer;
+
+ i32 x0,x1,y0,y1;
+
+ i16 inputindex;
+ i16 outputindex;
+ i16 lead;
+ i16 err;
+ i16 accum;
+
+ i16 *ptr; // source or destination
+ i16 *buff;
+
+ i16 inputcnt;
+ i16 initcnt;
+
+ i32 factor;
+ i32 drift;
+ i32 modulus;
+ i32 z1;
+ struct {
+ unsigned rxlock:1;
+ unsigned txlock:1;
+ unsigned twiddle:1;
+ unsigned doitnow:1;
+ }b;
+}
+t_dedrift;
+
/*
one structure for each ctcss tone to decode
*/
@@ -121,7 +368,7 @@ typedef struct
i16 enabled;
i16 state; // dead, running, error
i16 zIndex; // z bucket index
- i16 z[4]; // maw sph today
+ i16 z[4];
i16 zi;
i16 dvu;
i16 dvd;
@@ -130,78 +377,62 @@ typedef struct
i16 hyst;
i16 decode;
i16 diffpeak;
- i16 debug; // value held from last pass
+ i16 debug;
+
+ #if XPMR_DEBUG0 == 1
+ i16 lasttv0;
+ i16 lasttv1;
+ i16 lasttv2;
+ i16 lasttv3;
+
i16 *pDebug0; // pointer to debug output
i16 *pDebug1; // pointer to debug output
i16 *pDebug2; // pointer to debug output
+ i16 *pDebug3; // pointer to debug output
+ #endif
} t_tdet;
typedef struct
{
i16 enabled; // if 0 none, 0xFFFF all tones, or single tone
- i16 *input;
+ i16 *input; // source data
i16 clamplitude;
i16 center;
i16 decode; // current ctcss decode index
i32 BlankingTimer;
u32 TurnOffTimer;
- t_tdet tdet[CTCSS_NUM_CODES];
i16 gain;
i16 limit;
+ i16 debugIndex;
i16 *pDebug0;
i16 *pDebug1;
i16 *pDebug2;
+ i16 *pDebug3;
i16 testIndex;
i16 multiFreq;
i8 relax;
+ t_tdet tdet[CTCSS_NUM_CODES];
-} t_dec_ctcss;
+ i8 numrxcodes;
+ i16 rxCtcssMap[CTCSS_NUM_CODES];
+ char *rxctcss[CTCSS_NUM_CODES]; // pointers to each tone in string above
+ char *txctcss[CTCSS_NUM_CODES];
-typedef struct
-{
- i16 enabled; // if 0 none, 0xFFFF all tones, or single tone
- i16 clamplitude;
- i16 center;
- i16 decode; // current ctcss decode value
- i32 BlankingTimer;
- u32 TurnOffTimer;
- i16 gain;
- i16 limit;
- i16 *pDebug0;
- i16 *pDebug1;
- i16 rxPolarity;
-} t_dec_dcs;
+ i32 txctcssdefault_index;
+ float txctcssdefault_value;
+
+ struct{
+ unsigned valid:1;
+ }b;
+} t_dec_ctcss;
/*
- Low Speed Data decoding both polarities
+ Low Speed Data
+*/
+/*
+ general purpose pmr signal processing element
*/
-typedef struct
-{
- i16 counter; // counter to next sample
- i16 synced;
- u32 syncCorr[2];
- u32 data[2];
- i16 state; // disabled, enabled,
- i16 decode;
- i16 debug;
-
- i16 polarity;
- u32 frameNum;
-
- u16 area;
- u16 chan;
- u16 home;
- u16 id;
- u16 free;
-
- u16 crc;
- i16 rssi;
-
-} t_decLsd;
-
-
-/* general purpose pmr signal processing element */
struct t_pmr_chan;
@@ -211,6 +442,7 @@ typedef struct t_pmr_sps
i16 enabled; // enabled/disabled
+
struct t_pmr_chan *parentChan;
i16 *source; // source buffer
@@ -220,7 +452,9 @@ typedef struct t_pmr_sps
i16 numChanOut; // allows output direct to interleaved buffer
i16 selChanOut;
- u32 ticks;
+ i32 ticks;
+ i32 timer;
+ i32 count;
void *buff; // this structure's internal buffer
@@ -258,6 +492,29 @@ typedef struct t_pmr_sps
i16 err; // error condition
i16 option; // option / request zero
i16 state; // stopped, start, stopped assumes zero'd
+
+ i16 pending;
+
+ struct {
+ unsigned hit:1;
+ unsigned hitlast:1;
+ unsigned hita:1;
+ unsigned hitb:1;
+ unsigned bithit:1;
+ unsigned now:1;
+ unsigned next:1;
+ unsigned prev:1;
+ unsigned clock:1;
+ unsigned hold:1;
+ unsigned opt1:1;
+ unsigned opt2:1;
+ unsigned polarity:1;
+ unsigned dotting:1;
+ unsigned lastbitpending:1;
+ unsigned outzero:1;
+ unsigned settling:1;
+ unsigned syncing:1;
+ }b;
i16 cleared; // output buffer cleared
@@ -288,14 +545,28 @@ typedef struct t_pmr_sps
} t_pmr_sps;
+
+struct t_dec_dcs;
+struct t_lsd_control;
+struct t_decLsd;;
+struct t_encLsd;
+
/*
pmr channel
*/
typedef struct t_pmr_chan
{
i16 index; // which one
+ i16 devicenum; // belongs to
+
+ char *name;
+
i16 enabled; // enabled/disabled
i16 status; // ok, error, busy, idle, initializing
+
+ i16 tracelevel;
+ i16 tracetype;
+ u32 tracemask;
i16 nSamplesRx; // max frame size
i16 nSamplesTx;
@@ -306,11 +577,23 @@ typedef struct t_pmr_chan
i16 inputGain;
i16 inputOffset;
+ i32 ticks; // time ticks
u32 frameCountRx; // number processed
u32 frameCountTx;
+ i8 txframelock;
+
i32 txHangTime;
+ i32 txHangTimer;
i32 txTurnOff;
+ i16 txBufferClear;
+
+ u32 txfreq;
+ u32 rxfreq;
+ i8 txpower;
+
+ i32 txsettletime; // in samples
+ i32 txsettletimer;
i16 rxDC; // average DC value of input
i16 rxSqSet; // carrier squelch threshold
@@ -319,6 +602,7 @@ typedef struct t_pmr_chan
i16 rxQuality; // signal quality metric
i16 rxCarrierDetect; // carrier detect
i16 rxCdType;
+ i16 rxSqVoxAdj;
i16 rxExtCarrierDetect;
i32 inputBlanking; // Tx pulse eliminator
@@ -340,20 +624,54 @@ typedef struct t_pmr_chan
char radioDuplex;
- struct {
- unsigned pmrNoiseSquelch:1;
- unsigned rxHpf:1;
- unsigned txHpf:1;
- unsigned txLpf:1;
- unsigned rxDeEmphasis:1;
- unsigned txPreEmphasis:1;
- unsigned startSpecialTone:1;
- unsigned stopSpecialTone:1;
- unsigned doingSpecialTone:1;
- unsigned extCarrierDetect:1;
- unsigned txCapture:1;
- unsigned rxCapture:1;
- }b;
+ char *pStr;
+
+ // start channel signaling codes source
+ char *pRxCodeSrc; // source
+ char *pTxCodeSrc; // source
+ char *pTxCodeDefault; // source
+ // end channel signaling codes source
+
+ // start signaling code info derived from source
+ i16 numrxcodes;
+ i16 numtxcodes;
+ char *pRxCodeStr; // copied and cut up
+ char **pRxCode; // pointers to subs
+ char *pTxCodeStr;
+ char **pTxCode;
+
+ char txctcssdefault[16]; // codes from higher level
+
+ char *rxctcssfreqs; // rest are derived from this
+ char *txctcssfreqs;
+
+ char numrxctcssfreqs;
+ char numtxctcssfreqs;
+
+ char *rxctcss[CTCSS_NUM_CODES]; // pointers to each tone in string above
+ char *txctcss[CTCSS_NUM_CODES];
+
+ i16 rxCtcssMap[CTCSS_NUM_CODES];
+
+ i8 txcodedefaultsmode;
+ i16 txctcssdefault_index;
+ float txctcssdefault_value;
+
+ char txctcssfreq[32]; // encode now
+ char rxctcssfreq[32]; // decode now
+ // end most of signaling code info derived from source
+
+ struct t_lsd_control *pLsdCtl;
+
+ i16 rptnum;
+ i16 area;
+ char *ukey;
+ u32 idleinterval;
+ char turnoffs;
+
+ char pplock;
+
+ t_dedrift dd;
i16 dummy;
@@ -379,21 +697,34 @@ typedef struct t_pmr_chan
i16 rxCarrierPoint;
i16 rxCarrierHyst;
-
- i16 rxCtcssMap[CTCSS_NUM_CODES];
i16 txCtcssTocShift;
i16 txCtcssTocTime;
i8 txTocType;
- float txCtcssFreq;
- float rxCtcssFreq;
- float rxInputGain;
-
- i16 rxCtcssIndex;
+ i16 smode; // ctcss, dcs, lsd
+ i16 smodecode;
+ i16 smodewas; // ctcss, dcs, lsd
+ i32 smodetimer; // in ms
+ i32 smodetime; // to set in ms
+
+ t_dec_ctcss *rxCtcss;
+ struct t_dec_dcs *decDcs;
+ struct t_decLsd *decLsd;
+ struct t_encLsd *pLsdEnc;
+
+ i16 clamplitudeDcs;
+ i16 centerDcs;
+ u32 dcsBlankingTimer;
+ i16 dcsDecode; // current dcs decode value
+
+ i16 clamplitudeLsd;
+ i16 centerLsd;
+
i16 txPttIn; // from external request
i16 txPttOut; // to radio hardware
+ i16 txPttHid;
i16 bandwidth; // wide/narrow
i16 txCompand; // type
@@ -410,12 +741,15 @@ typedef struct t_pmr_chan
i16 function;
- i16 txState; // off,settling,on,hangtime,turnoff
+ i16 txState; // off,settling,on,hangtime,turnoff
+
+ i16 spsIndex;
- t_pmr_sps *spsMeasure; // measurement block
+ t_pmr_sps *spsMeasure; // measurement block
t_pmr_sps *spsRx; // 1st signal processing struct
t_pmr_sps *spsRxLsd;
+ t_pmr_sps *spsRxLsdNrz;
t_pmr_sps *spsRxDeEmp;
t_pmr_sps *spsRxHpf;
t_pmr_sps *spsRxVox;
@@ -423,14 +757,14 @@ typedef struct t_pmr_chan
t_pmr_sps *spsRxOut; // Last signal processing struct
t_pmr_sps *spsTx; // 1st signal processing struct
-
- t_pmr_sps *spsTxLsdLpf;
+
t_pmr_sps *spsTxOutA; // Last signal processing struct
-
t_pmr_sps *spsTxOutB; // Last signal processing struct
t_pmr_sps *spsSigGen0; // ctcss
t_pmr_sps *spsSigGen1; // test and other tones
+ t_pmr_sps *spsLsdGen;
+ t_pmr_sps *spsTxLsdLpf;
// tune tweaks
@@ -452,6 +786,58 @@ typedef struct t_pmr_chan
i32 *ptxLimiterAdjust; // from calling application
+ struct {
+ unsigned pmrNoiseSquelch:1;
+ unsigned rxHpf:1;
+ unsigned txHpf:1;
+ unsigned txLpf:1;
+ unsigned rxDeEmphasis:1;
+ unsigned txPreEmphasis:1;
+ unsigned startSpecialTone:1;
+ unsigned stopSpecialTone:1;
+ unsigned doingSpecialTone:1;
+ unsigned extCarrierDetect:1;
+ unsigned txCapture:1;
+ unsigned rxCapture:1;
+ unsigned reprog:1;
+ unsigned radioactive:1;
+ unsigned rxplmon:1;
+ unsigned remoted:1;
+ unsigned loopback:1;
+ unsigned rxpolarity:1;
+ unsigned txpolarity:1;
+ unsigned dcsrxpolarity:1;
+ unsigned dcstxpolarity:1;
+ unsigned lsdrxpolarity:1;
+ unsigned lsdtxpolarity:1;
+ unsigned txsettling:1;
+ unsigned smodeturnoff:1;
+
+ unsigned ctcssRxEnable:1;
+ unsigned ctcssTxEnable:1;
+ unsigned dcsRxEnable:1;
+ unsigned dcsTxEnable:1;
+ unsigned lmrRxEnable:1;
+ unsigned lmrTxEnable:1;
+ unsigned mdcRxEnable:1;
+ unsigned mdcTxEnable:1;
+ unsigned dstRxEnable:1;
+ unsigned dstTxEnable:1;
+ unsigned p25RxEnable:1;
+ unsigned p25TxEnable:1;
+ unsigned ax25Enable:1;
+
+ unsigned txCtcssInhibit:1;
+
+ unsigned rxkeyed:1;
+ unsigned rxhalted:1;
+ unsigned txhalted:1;
+ unsigned pptp_p1:1;
+ unsigned pptp_p2:1;
+ unsigned tuning:1;
+ unsigned pttwas:1;
+ }b;
+
i16 *pRxDemod; // buffers
i16 *pRxBase; // decimated lpf input
i16 *pRxNoise;
@@ -463,7 +849,10 @@ typedef struct t_pmr_chan
i16 *pRxLsdLimit; // LSD Limited
i16 *pRxCtcss; //
i16 *pRxSquelch;
+ i16 *prxVoxMeas;
+ i16 *prxMeasure;
+ i16 *pTxInput; // input data
i16 *pTxBase; // input data
i16 *pTxHpf;
i16 *pTxPreEmp;
@@ -474,11 +863,6 @@ typedef struct t_pmr_chan
i16 *pTxMod; // upsampled, low pass filtered
i16 *pTxOut; //
-
- i16 *pTxPttIn;
- i16 *pTxPttOut;
- i16 *pTxHang;
- i16 *pTxCode;
i16 *pSigGen0;
i16 *pSigGen1;
@@ -488,6 +872,12 @@ typedef struct t_pmr_chan
i16 *pNull;
+ #if XPMR_DEBUG0 == 1
+
+ i16 *pRxLsdCen;
+
+ i16 *pTstTxOut;
+
i16 *prxDebug; // consolidated debug buffer
i16 *ptxDebug; // consolidated debug buffer
@@ -501,23 +891,23 @@ typedef struct t_pmr_chan
i16 *ptxDebug2;
i16 *ptxDebug3;
- t_dec_ctcss *rxCtcss;
-
- i16 clamplitudeDcs;
- i16 centerDcs;
- u32 dcsBlankingTimer;
- i16 dcsDecode; // current dcs decode value
+ #endif
- i16 clamplitudeLsd;
- i16 centerLsd;
- t_decLsd decLsd[2]; // for both polarities
+ i16 numDebugChannels;
+
+ t_sdbg *sdbg;
} t_pmr_chan;
-static i16 TxTestTone(t_pmr_chan *pChan, i16 function);
+/*
+ function prototype declarations
+*/
+void strace(i16 point, t_sdbg *sdbg, i16 index, i16 value);
+void strace2(t_sdbg *sdbg);
+static i16 TxTestTone(t_pmr_chan *pChan, i16 function);
t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples);
-t_pmr_sps *createPmrSps(void);
+t_pmr_sps *createPmrSps(t_pmr_chan *pChan);
i16 destroyPmrChannel(t_pmr_chan *pChan);
i16 destroyPmrSps(t_pmr_sps *pSps);
i16 pmr_rx_frontend(t_pmr_sps *mySps);
@@ -531,10 +921,28 @@ i16 SoftLimiter(t_pmr_sps *mySps);
i16 SigGen(t_pmr_sps *mySps);
i16 pmrMixer(t_pmr_sps *mySps);
i16 DelayLine(t_pmr_sps *mySps);
-i16 PmrRx(t_pmr_chan *PmrChan, i16 *input, i16 *output);
-i16 PmrTx(t_pmr_chan *PmrChan, i16 *input, i16 *output);
+
+i16 PmrRx(t_pmr_chan *PmrChan, i16 *input, i16 *outputrx, i16 *outputtx );
+i16 PmrTx(t_pmr_chan *PmrChan, i16 *input);
+
+i16 string_parse(char *src, char **dest, char ***ptrs);
+i16 code_string_parse(t_pmr_chan *pChan);
+
i16 CtcssFreqIndex(float freq);
i16 MeasureBlock(t_pmr_sps *mySps);
+
+void dedrift (t_pmr_chan *pChan);
+void dedrift_write (t_pmr_chan *pChan, i16 *src);
+
+void ppspiout (u32 spidata);
+void progdtx (t_pmr_chan *pChan);
+void ppbinout (u8 chan);
+
+#if XPMR_PPTP == 1
+void pptp_init (void);
+void pptp_write (i16 bit, i16 state);
+#endif
+
#endif /* ! XPMR_H */
/* end of file */
diff --git a/channels/xpmr/xpmr_coef.h b/channels/xpmr/xpmr_coef.h
index fda6762da..84254e884 100755
--- a/channels/xpmr/xpmr_coef.h
+++ b/channels/xpmr/xpmr_coef.h
@@ -4,16 +4,28 @@
* All Rights Reserved. Copyright (C)2007, Xelatec, LLC
*
* 20070808 1235 Steven Henke, W9SH, sph@xelatec.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This version may be optionally licenced under the GNU LGPL licence.
+ *
+ * A license has been granted to Digium (via disclaimer) for the use of
+ * this code.
*
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
+ * Some filter coeficients via 'WinFilter' http://www.winfilter.20m.com.
*
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
*/
/*! \file
@@ -24,30 +36,25 @@
*/
#ifndef XPMR_COEF_H
-#define XMPR_COEF_H 1
+#define XMPR_COEF_H 1
// frequencies in 0.1 Hz
-const u32 dtmf_row[] =
+static const u32 dtmf_row[] =
{
6970, 7700, 8520, 9410
};
-const u32 dtmf_col[] =
+static const u32 dtmf_col[] =
{
12090, 13360, 14770, 16330
};
-const i16 coef_dcs_rx = 1488; // dcs rx data divisor for oversampling 8000/134.4
-const i16 coef_dcs_tx = 5952; // dcs tx data divisor
-
-const i16 coef_lsd_div = 672; // low speed data divisor
-const u32 coef_lsd_sync = 0x158; // 000101011000
-const u32 coef_lsd_sync_pattern[] = {0x0000000F, 0x0F0FF000};
#define CTCSS_COEF_INT 120
#define CTCSS_SAMPLE_RATE 8000
#define TDIV(x) ((CTCSS_SAMPLE_RATE*1000/x)+5)/10
-i32 coef_ctcss[4][5]=
+#if 0
+static i32 coef_ctcss[4][5]=
{
// freq, divisor, integrator, filter
{770,TDIV(770),CTCSS_COEF_INT,0,0},
@@ -55,9 +62,9 @@ i32 coef_ctcss[4][5]=
{1035,TDIV(1035),CTCSS_COEF_INT,0,0},
{0,0,0,0}
};
+#endif
-
-i16 coef_ctcss_div[]=
+static i16 coef_ctcss_div[]=
{
2985, // 00 067.0
2782, // 01 071.9
@@ -99,7 +106,7 @@ i16 coef_ctcss_div[]=
799 // 37 250.3
};
-float freq_ctcss[]=
+static float freq_ctcss[]=
{
067.0, // 00
071.9, // 01
@@ -378,7 +385,8 @@ static const int16_t coef_int_lpf_300_1_2[]={
// pre-emphasis differentiator 4000 Hz with 8KS/s
// a0,a1,b0,
static const int16_t taps_int_hpf_4000_1_2 = 2;
-static const int32_t gain_int_hpf_4000_1_2 = 16384;
+//static const int32_t gain_int_hpf_4000_1_2 = 16384; // per calculations
+static const int32_t gain_int_hpf_4000_1_2 = 13404; // hand tweaked for unity gain at 1KHz
static const int16_t coef_int_hpf_4000_1_2[]={
17610,
-17610,
@@ -386,298 +394,6 @@ static const int16_t coef_int_hpf_4000_1_2[]={
};
-/*
- ltr crc table
- from http://www.radioreference.com/forums/showthread.php?t=24126
-*/
-
-static const u8 ltr_table[]=
-{
-0x38, // 00 Area 0111000
-0x1c, // 01 Channel 4 0011100
-0x0e, // 02 Channel 3 0001110
-0x46, // 03 Channel 2 1000110
-0x23, // 04 Channel 1 0100011
-0x51, // 05 Channel 0 1010001
-0x68, // 06 Home 4 1101000
-0x75, // 07 Home 3 1110101
-0x7a, // 08 Home 2 1111010
-0x3d, // 09 Home 1 0111101
-0x1f, // 10 Home 0 0011111
-0x4f, // 11 Group 7 1001111
-0x26, // 12 Group 6 0100110
-0x52, // 13 Group 5 1010010
-0x29, // 14 Group 4 0101001
-0x15, // 15 Group 3 0010101
-0x0d, // 16 Group 2 0001101
-0x45, // 17 Group 1 1000101
-0x62, // 18 Group 0 1100010
-0x31, // 19 Free 4 0110001
-0x19, // 20 Free 3 0011001
-0x0d, // 21 Free 2 0001101
-0x07, // 22 Free 1 0000111
-0x43 // 23 Free 0 1000011
-};
-
-static const i16 bitWeight[]=
-{
-0, // 0
-1, // 1
-1, // 2
-2, // 3
-1, // 4
-2, // 5
-2, // 6
-3, // 7
-1, // 8
-2, // 9
-2, // 10
-3, // 11
-2, // 12
-3, // 13
-3, // 14
-4, // 15
-1, // 16
-2, // 17
-2, // 18
-3, // 19
-2, // 20
-3, // 21
-3, // 22
-4, // 23
-2, // 24
-3, // 25
-3, // 26
-4, // 27
-3, // 28
-4, // 29
-4, // 30
-5, // 31
-1, // 32
-2, // 33
-2, // 34
-3, // 35
-2, // 36
-3, // 37
-3, // 38
-4, // 39
-2, // 40
-3, // 41
-3, // 42
-4, // 43
-3, // 44
-4, // 45
-4, // 46
-5, // 47
-2, // 48
-3, // 49
-3, // 50
-4, // 51
-3, // 52
-4, // 53
-4, // 54
-5, // 55
-3, // 56
-4, // 57
-4, // 58
-5, // 59
-4, // 60
-5, // 61
-5, // 62
-6, // 63
-1, // 64
-2, // 65
-2, // 66
-3, // 67
-2, // 68
-3, // 69
-3, // 70
-4, // 71
-2, // 72
-3, // 73
-3, // 74
-4, // 75
-3, // 76
-4, // 77
-4, // 78
-5, // 79
-2, // 80
-3, // 81
-3, // 82
-4, // 83
-3, // 84
-4, // 85
-4, // 86
-5, // 87
-3, // 88
-4, // 89
-4, // 90
-5, // 91
-4, // 92
-5, // 93
-5, // 94
-6, // 95
-2, // 96
-3, // 97
-3, // 98
-4, // 99
-3, // 100
-4, // 101
-4, // 102
-5, // 103
-3, // 104
-4, // 105
-4, // 106
-5, // 107
-4, // 108
-5, // 109
-5, // 110
-6, // 111
-3, // 112
-4, // 113
-4, // 114
-5, // 115
-4, // 116
-5, // 117
-5, // 118
-6, // 119
-4, // 120
-5, // 121
-5, // 122
-6, // 123
-5, // 124
-6, // 125
-6, // 126
-7, // 127
-1, // 128
-2, // 129
-2, // 130
-3, // 131
-2, // 132
-3, // 133
-3, // 134
-4, // 135
-2, // 136
-3, // 137
-3, // 138
-4, // 139
-3, // 140
-4, // 141
-4, // 142
-5, // 143
-2, // 144
-3, // 145
-3, // 146
-4, // 147
-3, // 148
-4, // 149
-4, // 150
-5, // 151
-3, // 152
-4, // 153
-4, // 154
-5, // 155
-4, // 156
-5, // 157
-5, // 158
-6, // 159
-2, // 160
-3, // 161
-3, // 162
-4, // 163
-3, // 164
-4, // 165
-4, // 166
-5, // 167
-3, // 168
-4, // 169
-4, // 170
-5, // 171
-4, // 172
-5, // 173
-5, // 174
-6, // 175
-3, // 176
-4, // 177
-4, // 178
-5, // 179
-4, // 180
-5, // 181
-5, // 182
-6, // 183
-4, // 184
-5, // 185
-5, // 186
-6, // 187
-5, // 188
-6, // 189
-6, // 190
-7, // 191
-2, // 192
-3, // 193
-3, // 194
-4, // 195
-3, // 196
-4, // 197
-4, // 198
-5, // 199
-3, // 200
-4, // 201
-4, // 202
-5, // 203
-4, // 204
-5, // 205
-5, // 206
-6, // 207
-3, // 208
-4, // 209
-4, // 210
-5, // 211
-4, // 212
-5, // 213
-5, // 214
-6, // 215
-4, // 216
-5, // 217
-5, // 218
-6, // 219
-5, // 220
-6, // 221
-6, // 222
-7, // 223
-3, // 224
-4, // 225
-4, // 226
-5, // 227
-4, // 228
-5, // 229
-5, // 230
-6, // 231
-4, // 232
-5, // 233
-5, // 234
-6, // 235
-5, // 236
-6, // 237
-6, // 238
-7, // 239
-4, // 240
-5, // 241
-5, // 242
-6, // 243
-5, // 244
-6, // 245
-6, // 246
-7, // 247
-5, // 248
-6, // 249
-6, // 250
-7, // 251
-6, // 252
-7, // 253
-7, // 254
-8 // 255
-};
/*