* Asterisk -- A telephony toolkit for Linux.
*
* Radio Repeater / Remote Base program
- * version 0.27 07/09/05
+ * version 0.28 08/21/05
*
* See http://www.zapatatelephony.org/app_rpt.html
*
- * Copyright (C) 2002-2004, Jim Dixon, WB6NIL
+ * Copyright (C) 2002-2005, Jim Dixon, WB6NIL
*
* Jim Dixon, WB6NIL <jim@lambdatel.com>
* Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
*
* remote cmds:
*
- * 0 - Recall Memory MM (*000-*099) (Gets memory from rpt.conf)
- * 1 - Set VFO MMMMM*KKK*O (Mhz digits, Khz digits, Offset)
- * 2 - Set Rx PL Tone HHH*D*
- * 3 - Set Tx PL Tone HHH*D* (Not currently implemented with DHE RBI-1)
- * 5 - Link Status
+ * 1 - Recall Memory MM (*000-*099) (Gets memory from rpt.conf)
+ * 2 - Set VFO MMMMM*KKK*O (Mhz digits, Khz digits, Offset)
+ * 3 - Set Rx PL Tone HHH*D*
+ * 4 - Set Tx PL Tone HHH*D* (Not currently implemented with DHE RBI-1)
+ * 5 - Link Status (long)
+ * 6 - Set operating mode M (FM, USB, LSB, AM, etc)
* 100 - RX PL off (Default)
* 101 - RX PL On
* 102 - TX PL Off (Default)
* 104 - Low Power
* 105 - Med Power
* 106 - Hi Power
+ * 107 - Bump Down 20 Hz
+ * 108 - Bump Down 100 Hz
+ * 109 - Bump Down 500 Hz
+ * 110 - Bump Up 20 Hz
+ * 111 - Bump Up 100 Hz
+ * 112 - Bump Up 500 Hz
+ * 113 - Scan Down Slow
+ * 114 - Scan Down Medium
+ * 115 - Scan Down Fast
+ * 116 - Scan Up Slow
+ * 117 - Scan Up Medium
+ * 118 - Scan Up Fast
+ * 119 - Transmit allowing auto-tune
+ * 140 - Link Status (brief)
*
*
*/
#define TELEPARAMSIZE 32
+#define REM_SCANTIME 100
+
enum {REM_OFF,REM_MONITOR,REM_TX};
enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM};
+enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
+
+enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
+
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/say.h"
#include "asterisk/localtime.h"
-static char *tdesc = "Radio Repeater / Remote Base version 0.27 07/09/2005";
+static char *tdesc = "Radio Repeater / Remote Base version 0.28 08/21/2005";
static char *app = "Rpt";
static int nrpts = 0;
char *discstr = "!!DISCONNECT!!";
+static char *remote_rig_ft897="ft897";
+static char *remote_rig_rbi="rbi";
struct ast_config *cfg;
struct rpt_tele tele;
pthread_t rpt_call_thread,rpt_thread;
time_t rem_dtmf_time,dtmf_time_rem;
- int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx;
+ int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer;
int mustid;
int politeid;
int dtmfidx,rem_dtmfidx;
char powerlevel;
char txplon;
char rxplon;
+ char remmode;
+ char tunerequest;
+ char hfscanmode;
+ int hfscanstatus;
+ char lastlinknode[MAXNODESTR];
char funcchar;
char endchar;
char stopgen;
return res;
}
+static int saynum(struct ast_channel *mychannel, int num)
+{
+ int res;
+ res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
+ if(!res)
+ res = ast_waitstream(mychannel, "");
+ else
+ ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
+ ast_stopstream(mychannel);
+ return res;
+}
+
+
/* Retrieve an int from a config file */
static int retrieve_astcfgint(char *category, char *name, int min, int max, int defl)
static void *rpt_tele_thread(void *this)
{
ZT_CONFINFO ci; /* conference info */
-int res = 0,hastx,imdone = 0, unkeys_queued, x;
+int res = 0,hastx,hasremote,imdone = 0, unkeys_queued, x;
struct rpt_tele *mytele = (struct rpt_tele *)this;
struct rpt_tele *tlist;
struct rpt *myrpt;
}
hastx = 0;
-
+ hasremote = 0;
l = myrpt->links.next;
if (l != &myrpt->links)
{
ast_mutex_lock(&myrpt->lock);
while(l != &myrpt->links)
{
- if (l->mode) hastx++;
+ if (l->mode) {
+ hastx++;
+ if (l->isremote) hasremote++;
+ }
l = l->next;
}
ast_mutex_unlock(&myrpt->lock);
ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
}
+ 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)
+ {
+ ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+ ast_mutex_lock(&myrpt->lock);
+ remque((struct qelem *)mytele);
+ ast_mutex_unlock(&myrpt->lock);
+ free(mytele);
+ ast_hangup(mychannel);
+ pthread_exit(NULL);
+ }
+ if((ct = ast_variable_retrieve(cfg, nodename, "remotect"))){ /* Unlinked Courtesy Tone */
+ ast_safe_sleep(mychannel,200);
+ ct_copy = ast_strdupa(ct);
+ res = telem_lookup(mychannel, myrpt->name, ct_copy);
+ if(res)
+ ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
+ }
+ }
imdone = 1;
break;
case REMDISC:
* Internet linking function
*/
-static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source)
+static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source)
{
char *val, *s, *s1, *tele;
char tmp[300], deststr[300] = "",modechange = 0;
+ char digitbuf[MAXNODESTR];
struct rpt_link *l;
ZT_CONFINFO ci; /* conference info */
if (!myrpt->enable)
return DC_ERROR;
+ strncpy(digitbuf,digits,MAXNODESTR - 1);
+
if(debug)
printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
switch(myatoi(param)){
case 1: /* Link off */
+ if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
+ strcpy(digitbuf,myrpt->lastlinknode);
val = ast_variable_retrieve(cfg, NODES, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
if (l != &myrpt->links){ /* if found */
struct ast_frame wf;
+ strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
l->retries = MAX_RETRIES + 1;
l->disced = 1;
ast_mutex_unlock(&myrpt->lock);
ast_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(cfg, NODES, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
modechange = 1;
} else
ast_mutex_unlock(&myrpt->lock);
+ strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
/* establish call in monitor mode */
l = malloc(sizeof(struct rpt_link));
if (!l){
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(cfg, NODES, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
modechange = 1;
} else
ast_mutex_unlock(&myrpt->lock);
+ strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
/* establish call in tranceive mode */
l = malloc(sizeof(struct rpt_link));
if (!l){
rpt_telemetry(myrpt, REMALREADY, 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(cfg, NODES, digitbuf);
if (!val){
}
ast_mutex_lock(&myrpt->lock);
+ strcpy(myrpt->lastlinknode,digitbuf);
strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
ast_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt, REMGO, NULL);
}
/*
-* Remote base function
+* Collect digits one by one until something matches
*/
-static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source)
+static int collect_function_digits(struct rpt *myrpt, char *digits, int command_source)
{
- char *s,*s1,*s2,*val;
- int i,j,k,l,res,offset,offsave;
- char oc;
- char tmp[20], freq[20] = "", savestr[20] = "";
- struct ast_channel *mychannel;
-
- if((!param) || (command_source != SOURCE_RMT))
- return DC_ERROR;
-
- mychannel = myrpt->remchannel;
+ int i;
+ char *stringp,*action,*param,*functiondigits;
+ char function_table_name[30] = "";
+ char workstring[80];
+ struct ast_variable *vp;
- switch(myatoi(param)){
+ if(debug)
+ printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
+
+ if (command_source == SOURCE_LNK)
+ strncpy(function_table_name, myrpt->link_functions, sizeof(function_table_name) - 1);
+ else
+ strncpy(function_table_name, myrpt->functions, sizeof(function_table_name) - 1);
+ vp = ast_variable_browse(cfg, function_table_name);
+ while(vp) {
+ if(!strncasecmp(vp->name, digits, strlen(vp->name)))
+ break;
+ vp = vp->next;
+ }
+ if(!vp) {
+ if(strlen(digits) >= ((command_source == SOURCE_LNK) ?
+ myrpt->link_longestfunc : myrpt->longestfunc)) /* Get out of function mode if longes func length reached */
+ return DC_ERROR;
+ else
+ return DC_INDETERMINATE;
+ }
+ /* Found a match, retrieve value part and parse */
+ 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(action, function_table[i].action, strlen(action)))
+ break;
+ }
+ 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){
+ /* Error, function undefined */
+ if(debug)
+ printf("@@@@ NULL for action: %s\n",action);
+ return DC_ERROR;
+ }
+ functiondigits = digits + strlen(vp->name);
+ return (*function_table[i].function)(myrpt, param, functiondigits, command_source);
+}
- 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;
+
+static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
+ char *str)
+{
+char tmp[300],cmd[300] = "",dest[300],src[300],c;
+int seq, res;
+struct rpt_link *l;
+struct ast_frame wf;
+
+ wf.frametype = AST_FRAME_TEXT;
+ wf.subclass = 0;
+ wf.offset = 0;
+ wf.mallocd = 1;
+ wf.datalen = strlen(str) + 1;
+ wf.samples = 0;
+ /* put string in our buffer */
+ strncpy(tmp,str,sizeof(tmp) - 1);
+
+ if (!strcmp(tmp,discstr))
+ {
+ mylink->disced = 1;
+ mylink->retries = MAX_RETRIES + 1;
+ ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
+ return;
+ }
+ 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 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)
+ {
+ /* dont send back from where it came */
+ if ((l == mylink) || (!strcmp(l->name,mylink->name)))
+ {
+ l = l->next;
+ continue;
}
-
- val = ast_variable_retrieve(cfg, MEMORY, digitbuf);
- if (!val){
- if (ast_safe_sleep(mychannel,1000) == -1)
- return DC_ERROR;
- sayfile(mychannel,"rpt/memory_notfound");
- return DC_COMPLETE;
- }
- strncpy(tmp,val,sizeof(tmp) - 1);
- s = strchr(tmp,',');
- if (!s)
- return DC_ERROR;
- *s++ = 0;
- s1 = strchr(s,',');
- if (!s1)
- return DC_ERROR;
- *s1++ = 0;
- strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
- strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
- myrpt->offset = REM_SIMPLEX;
- myrpt->powerlevel = REM_MEDPWR;
- myrpt->rxplon = 0;
- myrpt->txplon = 0;
- while(*s1)
+ /* if it is, send it and we're done */
+ if (!strcmp(l->name,dest))
{
- switch(*s1++){
-
- 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;
+ /* send, but not to src */
+ if (strcmp(l->name,src)) {
+ wf.data = strdup(str);
+ if (l->chan) ast_write(l->chan,&wf);
}
+ return;
}
-
-
- if (setrbi(myrpt) == -1)
- return DC_ERROR;
-
-
- return DC_COMPLETE;
-
- case 2: /* set freq + offset */
-
-
- for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N+*N */
- if(digitbuf[i] == '*'){
- j++;
- continue;
- }
- if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
- return DC_ERROR;
- else{
- if(j == 0)
- l++;
- if(j == 1)
- k++;
- }
+ l = l->next;
+ }
+ l = myrpt->links.next;
+ /* otherwise, send it to all of em */
+ while(l != &myrpt->links)
+ {
+ /* dont send back from where it came */
+ if ((l == mylink) || (!strcmp(l->name,mylink->name)))
+ {
+ l = l->next;
+ continue;
}
-
- i = strlen(digitbuf) - 1;
- if((j > 2) || (l > 5) || (k > 3))
- return DC_ERROR; /* &$@^! */
-
- if((j < 2) || (digitbuf[i] == '*'))
- break; /* Not yet */
-
- strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
-
- s = tmp;
- s1 = strsep(&s, "*"); /* Pick off MHz */
- s2 = strsep(&s,"*"); /* Pick off KHz */
- oc = *s; /* Pick off offset */
-
-
- switch(strlen(s2)){ /* Allow partial entry of khz digits for laziness support */
- case 1:
- k = 100 * atoi(s2);
- break;
-
- case 2:
- k = 10 * atoi(s2);
- break;
-
- case 3:
- if((s2[2] != '0')&&(s2[2] != '5'))
- return DC_ERROR;
- k = atoi(s2);
- break;
-
- default:
- return DC_ERROR;
-
+ /* send, but not to src */
+ if (strcmp(l->name,src)) {
+ wf.data = strdup(str);
+ if (l->chan) ast_write(l->chan,&wf);
}
-
-
-
- snprintf(freq, sizeof(freq), "%s.%03d", s1, k);
-
- offset = REM_SIMPLEX;
-
- if (oc){
- switch(oc){
-
- case '1':
- offset = REM_MINUS;
- break;
-
- case '2':
- offset = REM_SIMPLEX;
- break;
-
- case '3':
- offset = REM_PLUS;
- break;
-
- default:
-
- return DC_ERROR;
- }
- }
+ l = l->next;
+ }
+ return;
+ }
+ ast_mutex_lock(&myrpt->lock);
+ if (myrpt->callmode == 1)
+ {
+ myrpt->exten[myrpt->cidx++] = c;
+ myrpt->exten[myrpt->cidx] = 0;
+ /* if this exists */
+ if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
+ {
+ myrpt->callmode = 2;
+ rpt_telemetry(myrpt,PROC,NULL);
+ }
+ /* if can continue, do so */
+ if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,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->funcchar)
+ {
+ myrpt->rem_dtmfidx = 0;
+ myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
+ time(&myrpt->rem_dtmf_time);
+ ast_mutex_unlock(&myrpt->lock);
+ return;
+ }
+ else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
+ {
+ time(&myrpt->rem_dtmf_time);
+ if (myrpt->rem_dtmfidx < MAXDTMF)
+ {
+ myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
+ myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
- offsave = myrpt->offset;
- strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
- strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
+ ast_mutex_unlock(&myrpt->lock);
+ strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
+ res = collect_function_digits(myrpt, cmd, SOURCE_LNK);
+ ast_mutex_lock(&myrpt->lock);
- if(debug)
- printf("@@@@ Frequency entered: %s\n", myrpt->freq);
-
- strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
- myrpt->offset = offset;
-
- if (setrbi(myrpt) == -1){
- myrpt->offset = offsave;
- strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
- return DC_ERROR;
- }
+ switch(res){
- return DC_COMPLETE;
-
- 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++;
- }
- }
- 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 (setrbi(myrpt) == -1){
- strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
- return DC_ERROR;
- }
-
-
- return DC_COMPLETE;
-
- case 100: /* other stuff */
- case 101:
- case 102:
- case 103:
- case 104:
- case 105:
- case 106:
- switch(myatoi(param)){
- case 100: /* RX PL Off */
- myrpt->rxplon = 0;
- break;
-
- case 101: /* RX PL On */
- myrpt->rxplon = 1;
- break;
-
- case 102: /* TX PL Off */
- myrpt->txplon = 0;
- break;
-
- case 103: /* TX PL On */
- myrpt->txplon = 1;
- break;
-
- case 104: /* Low Power */
- myrpt->powerlevel = REM_LOWPWR;
- break;
-
- case 105: /* Medium Power */
- myrpt->powerlevel = REM_MEDPWR;
- break;
-
- case 106: /* Hi Power */
- myrpt->powerlevel = REM_HIPWR;
- break;
- default:
- return DC_ERROR;
- }
- if (setrbi(myrpt) == -1)
- return DC_ERROR;
- return DC_COMPLETE;
- case 5: /* Status */
- 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 ((sayfile(mychannel,"rpt/node") == -1) ||
- (saycharstr(mychannel,myrpt->name) == -1) ||
- (sayfile(mychannel,"rpt/frequency") == -1) ||
- (saycharstr(mychannel,myrpt->freq) == -1)){
-
- if (!myrpt->remoterx){
-
- ast_indicate(mychannel,AST_CONTROL_RADIO_UNKEY);
- }
- return DC_ERROR;
- }
- switch(myrpt->offset){
-
- case REM_MINUS:
- res = sayfile(mychannel,"rpt/minus");
+ case DC_INDETERMINATE:
break;
- case REM_SIMPLEX:
- res = sayfile(mychannel,"rpt/simplex");
+ case DC_REQ_FLUSH:
+ myrpt->rem_dtmfidx = 0;
+ myrpt->rem_dtmfbuf[0] = 0;
break;
-
- case REM_PLUS:
- res = sayfile(mychannel,"rpt/plus");
+
+
+ case DC_COMPLETE:
+ myrpt->rem_dtmfbuf[0] = 0;
+ myrpt->rem_dtmfidx = -1;
+ myrpt->rem_dtmf_time = 0;
break;
-
+
+ case DC_ERROR:
default:
- return DC_ERROR;
- }
- if (res == -1){
-
- if (!myrpt->remoterx){
-
- ast_indicate(mychannel,AST_CONTROL_RADIO_UNKEY);
- }
- return -1;
- }
- 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");
+ myrpt->rem_dtmfbuf[0] = 0;
+ myrpt->rem_dtmfidx = -1;
+ myrpt->rem_dtmf_time = 0;
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,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1) ||
- (sayfile(mychannel,"rpt/rxpl") == -1) ||
- (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1)){
- if (!myrpt->remoterx){
- ast_indicate(mychannel,AST_CONTROL_RADIO_UNKEY);
- }
- return -1;
- }
- if (!myrpt->remoterx){
- ast_indicate(mychannel,AST_CONTROL_RADIO_UNKEY);
- }
- return DC_COMPLETE;
-
- default:
- return DC_ERROR;
- }
+ }
- return DC_INDETERMINATE;
+ }
+ ast_mutex_unlock(&myrpt->lock);
+ return;
}
-
-/*
-* Collect digits one by one until something matches
-*/
+/* Doug Hall RBI-1 serial data definitions:
+ *
+ * Byte 0: Expansion external outputs
+ * Byte 1:
+ * Bits 0-3 are BAND as follows:
+ * Bits 4-5 are POWER bits as follows:
+ * 00 - Low Power
+ * 01 - Hi Power
+ * 02 - Med Power
+ * Bits 6-7 are always set
+ * Byte 2:
+ * Bits 0-3 MHZ in BCD format
+ * Bits 4-5 are offset as follows:
+ * 00 - minus
+ * 01 - plus
+ * 02 - simplex
+ * 03 - minus minus (whatever that is)
+ * Bit 6 is the 0/5 KHZ bit
+ * Bit 7 is always set
+ * Byte 3:
+ * Bits 0-3 are 10 KHZ in BCD format
+ * Bits 4-7 are 100 KHZ in BCD format
+ * Byte 4: PL Tone code and encode/decode enable bits
+ * Bits 0-5 are PL tone code (comspec binary codes)
+ * Bit 6 is encode enable/disable
+ * Bit 7 is decode enable/disable
+ */
-static int collect_function_digits(struct rpt *myrpt, char *digits, int command_source)
+/* take the frequency from the 10 mhz digits (and up) and convert it
+ to a band number */
+
+static int rbi_mhztoband(char *str)
{
- int i;
- char *stringp,*action,*param,*functiondigits;
- char function_table_name[30] = "";
- char workstring[80];
-
- struct ast_variable *vp;
-
- if(debug)
- printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
-
- if (command_source == SOURCE_LNK)
- strncpy(function_table_name, myrpt->link_functions, sizeof(function_table_name) - 1);
- else
- strncpy(function_table_name, myrpt->functions, sizeof(function_table_name) - 1);
- vp = ast_variable_browse(cfg, function_table_name);
- while(vp) {
- if(!strncasecmp(vp->name, digits, strlen(vp->name)))
- break;
- vp = vp->next;
- }
- if(!vp) {
- if(strlen(digits) >= ((command_source == SOURCE_LNK) ?
- myrpt->link_longestfunc : myrpt->longestfunc)) /* Get out of function mode if longes func length reached */
- return DC_ERROR;
- else
- return DC_INDETERMINATE;
- }
- /* Found a match, retrieve value part and parse */
- 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(action, function_table[i].action, strlen(action)))
- break;
- }
- 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){
- /* Error, function undefined */
- if(debug)
- printf("@@@@ NULL for action: %s\n",action);
- return DC_ERROR;
+int i;
+
+ i = atoi(str) / 10; /* get the 10's of mhz */
+ switch(i)
+ {
+ case 2:
+ return 10;
+ case 5:
+ return 11;
+ case 14:
+ return 2;
+ case 22:
+ return 3;
+ case 44:
+ return 4;
+ case 124:
+ return 0;
+ case 125:
+ return 1;
+ case 126:
+ return 8;
+ case 127:
+ return 5;
+ case 128:
+ return 6;
+ case 129:
+ return 7;
+ default:
+ break;
}
- functiondigits = digits + strlen(vp->name);
- return (*function_table[i].function)(myrpt, param, functiondigits, command_source);
+ return -1;
}
-
-static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
- char *str)
+/* take a PL frequency and turn it into a code */
+static int rbi_pltocode(char *str)
{
-char tmp[300],cmd[300] = "",dest[300],src[300],c;
-int seq, res;
-struct rpt_link *l;
-struct ast_frame wf;
-
- wf.frametype = AST_FRAME_TEXT;
- wf.subclass = 0;
- wf.offset = 0;
- wf.mallocd = 1;
- wf.datalen = strlen(str) + 1;
- wf.samples = 0;
- /* put string in our buffer */
- strncpy(tmp,str,sizeof(tmp) - 1);
+int i;
+char *s;
- if (!strcmp(tmp,discstr))
- {
- mylink->disced = 1;
- mylink->retries = MAX_RETRIES + 1;
- ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
- return;
- }
- 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"))
+ s = strchr(str,'.');
+ i = 0;
+ if (s) i = atoi(s + 1);
+ i += atoi(str) * 10;
+ switch(i)
{
- ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
- return;
+ case 670:
+ return 0;
+ case 719:
+ return 1;
+ case 744:
+ return 2;
+ case 770:
+ return 3;
+ case 797:
+ return 4;
+ case 825:
+ return 5;
+ case 854:
+ return 6;
+ case 885:
+ return 7;
+ case 915:
+ return 8;
+ case 948:
+ return 9;
+ case 974:
+ return 10;
+ case 1000:
+ return 11;
+ case 1035:
+ return 12;
+ case 1072:
+ return 13;
+ case 1109:
+ return 14;
+ case 1148:
+ return 15;
+ case 1188:
+ return 16;
+ case 1230:
+ return 17;
+ case 1273:
+ return 18;
+ case 1318:
+ return 19;
+ case 1365:
+ return 20;
+ case 1413:
+ return 21;
+ case 1462:
+ return 22;
+ case 1514:
+ return 23;
+ case 1567:
+ return 24;
+ case 1622:
+ return 25;
+ case 1679:
+ return 26;
+ case 1738:
+ return 27;
+ case 1799:
+ return 28;
+ case 1862:
+ return 29;
+ case 1928:
+ return 30;
+ case 2035:
+ return 31;
+ case 2107:
+ return 32;
+ case 2181:
+ return 33;
+ case 2257:
+ return 34;
+ case 2336:
+ return 35;
+ case 2418:
+ return 36;
+ case 2503:
+ return 37;
}
- /* 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)
- {
- /* dont send back from where it came */
- if ((l == mylink) || (!strcmp(l->name,mylink->name)))
+ return -1;
+}
+
+/*
+* 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;
+ 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->iobase);
+ /* >= 15 us */
+ for(delayvar = 1; delayvar < 15000; delayvar++);
+ od >>= 1;
+ outb(d | 2,myrpt->iobase);
+ /* >= 30 us */
+ for(delayvar = 1; delayvar < 30000; delayvar++);
+ outb(d,myrpt->iobase);
+ /* >= 10 us */
+ for(delayvar = 1; delayvar < 10000; delayvar++);
+ }
+ }
+ /* >= 50 us */
+ for(delayvar = 1; delayvar < 50000; delayvar++);
+ }
+
+static void rbi_out(struct rpt *myrpt,unsigned char *data)
+{
+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);
+ 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);
+ return;
+ }
+}
+
+static int serial_remote_io(struct rpt *myrpt, char *txbuf, int txbytes, char *rxbuf,
+ int rxmaxbytes, int asciiflag)
+{
+ int i;
+ struct zt_radio_param prm;
+
+ if(debug){
+ printf("String output was: ");
+ for(i = 0; i < txbytes; i++)
+ printf("%02X ", (unsigned char ) txbuf[i]);
+ printf("\n");
+ }
+
+ 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);
+ }
+ return(prm.index);
+}
+
+static int setrbi(struct rpt *myrpt)
+{
+char tmp[MAXREMSTR] = "",rbicmd[5],*s;
+int band,txoffset = 0,txpower = 0,txpl;
+
+ /* must be a remote system */
+ if (!myrpt->remote) return(0);
+ /* must have rbi hardware */
+ if (strncmp(myrpt->remote,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;
+ }
+
+
+ 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;
+ }
+ rbicmd[0] = 0;
+ rbicmd[1] = band | txpower | 0xc0;
+ rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
+ 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);
+ return 0;
+}
+
+
+/* Check for valid rbi frequency */
+/* Hard coded limits now, configurable later, maybe? */
+
+static int check_freq_rbi(int m, int d)
+{
+ if(m == 50){ /* 6 meters */
+ if(d < 10100)
+ return -1;
+ }
+ else if((m >= 51) && ( m < 54)){
+ ;
+ }
+ else if(m == 144){ /* 2 meters */
+ if(d < 10100)
+ return -1;
+ }
+ 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;
+ return 0;
+}
+
+/*
+* Split frequency into mhz and decimals
+*/
+
+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;
+
+}
+
+/*
+* FT-897 I/O handlers
+*/
+
+/* Check to see that the frequency is valid */
+/* Hard coded limits now, configurable later, maybe? */
+
+
+static int check_freq_ft897(int m, int d)
+{
+
+ if(m == 1){ /* 160 meters */
+ if(d < 80001)
+ return -1;
+ }
+ else if(m == 3){ /* 80 meters */
+ if(d < 75001)
+ return -1;
+ }
+ else if(m == 7){ /* 40 meters */
+ if((d < 71501) || (d > 72999))
+ return -1;
+ }
+ else if(m == 14){ /* 20 meters */
+ if((d < 15001) || (d > 34999))
+ return -1;
+ }
+ else if(m == 18){ /* 17 meters */
+ if((d < 11001) || (d > 11679))
+ return -1;
+ }
+ else if(m == 21){ /* 15 meters */
+ if((d < 20001) || (d > 44999))
+ return -1;
+ }
+ else if(m == 24){ /* 12 meters */
+ if((d < 93001) || (d > 98999))
+ return -1;
+ }
+ else if(m == 28){ /* 10 meters */
+ if(d < 30001)
+ return -1;
+ }
+ else if(m == 29){
+ if(d > 69999)
+ return -1;
+ }
+ else if(m == 50){ /* 6 meters */
+ if(d < 10100)
+ return -1;
+ }
+ else if((m >= 51) && ( m < 54)){
+ ;
+ }
+ else 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;
+ return 0;
+}
+
+/*
+* Set a new frequency for the FT897
+*/
+
+static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
+{
+ char mhz[MAXREMSTR];
+ char decimals[MAXREMSTR];
+ unsigned char cmdstr[5];
+ int fd,m,d;
+
+ fd = 0;
+ if(debug)
+ printf("New frequency: %s\n",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 */
+
+ 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];
+
+ 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];
+
+ 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;
+ }
+
+ cmdstr[4] = 0x09;
+
+ return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
+}
+
+/* ft-897 mode */
+
+static int set_mode_ft897(struct rpt *myrpt, char newmode)
+{
+ unsigned char cmdstr[5];
+
+ memset(cmdstr, 0, 5);
+
+ 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;
+ }
+ cmdstr[4] = 0x07;
+
+ return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
+}
+
+/* Set tone encode and decode modes */
+
+static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
+{
+ 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 */
+ else if (rxplon && !txplon)
+ cmdstr[0] = 0x3A; /* Encode only */
+ else
+ cmdstr[0] = 0x8A; /* OFF */
+
+ cmdstr[4] = 0x0A;
+
+ return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
+}
+
+
+/* Set transmit and receive ctcss tone frequencies */
+
+static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
+{
+ unsigned char cmdstr[5];
+ char hertz[MAXREMSTR],decimals[MAXREMSTR];
+ int h,d;
+
+
+ memset(cmdstr, 0, 5);
+
+ if(split_freq(hertz, decimals, txtone))
+ return -1;
+
+ h = atoi(hertz);
+ d = atoi(decimals);
+
+ cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
+ cmdstr[1] = ((h % 10) << 4) + (d % 10);
+
+ if(rxtone){
+
+ if(split_freq(hertz, decimals, rxtone))
+ return -1;
+
+ h = atoi(hertz);
+ d = atoi(decimals);
+
+ 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);
+}
+
+
+
+static int set_ft897(struct rpt *myrpt)
+{
+ int res;
+
+ if(debug)
+ printf("@@@@ lock on\n");
+
+ res = simple_command_ft897(myrpt, 0x00); /* LOCK on */
+
+ if(debug)
+ printf("@@@@ ptt off\n");
+
+ if(!res)
+ res = simple_command_ft897(myrpt, 0x88); /* PTT off */
+
+ if(debug)
+ printf("Modulation mode\n");
+
+ if(!res)
+ res = set_mode_ft897(myrpt, myrpt->remmode); /* Modulation mode */
+
+ if(debug)
+ printf("Split off\n");
+
+ if(!res)
+ simple_command_ft897(myrpt, 0x82); /* Split off */
+
+ if(debug)
+ printf("Frequency\n");
+
+ if(!res)
+ res = set_freq_ft897(myrpt, myrpt->freq); /* Frequency */
+ 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)){
+ 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){
+ 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)){
+ if(debug)
+ printf("Clarifier off\n");
+ simple_command_ft897(myrpt, 0x85); /* Clarifier off if LSB or USB */
+ }
+ return res;
+}
+
+static int closerem_ft897(struct rpt *myrpt)
+{
+ simple_command_ft897(myrpt, 0x88); /* PTT off */
+ return 0;
+}
+
+/*
+* 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 multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
+{
+ int m,d;
+ char mhz[MAXREMSTR], decimals[MAXREMSTR];
+
+ if(debug)
+ printf("Before bump: %s\n", 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){
+ m--;
+ d += 100000;
+ }
+ else if(d >= 100000){
+ m++;
+ d -= 100000;
+ }
+
+ if(check_freq_ft897(m, d)){
+ if(debug)
+ printf("Bump freq invalid\n");
+ return -1;
+ }
+
+ snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
+
+ if(debug)
+ printf("After bump: %s\n", myrpt->freq);
+
+ return set_freq_ft897(myrpt, myrpt->freq);
+}
+
+
+
+/*
+* Dispatch to correct I/O handler
+*/
+
+static int setrem(struct rpt *myrpt)
+{
+ 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;
+}
+
+static int closerem(struct rpt *myrpt)
+{
+ if(!strcmp(myrpt->remote, remote_rig_ft897))
+ return closerem_ft897(myrpt);
+ else
+ return 0;
+}
+
+/*
+* Dispatch to correct frequency checker
+*/
+
+static int check_freq(struct rpt *myrpt, int m, int d)
+{
+ if(!strcmp(myrpt->remote, remote_rig_ft897))
+ return check_freq_ft897(m, d);
+ else if(!strcmp(myrpt->remote, remote_rig_rbi))
+ return check_freq_rbi(m, d);
+ else
+ return -1;
+}
+
+/*
+* Return 1 if rig is multimode capable
+*/
+
+static int multimode_capable(struct rpt *myrpt)
+{
+ if(!strcmp(myrpt->remote, remote_rig_ft897))
+ return 1;
+ return 0;
+}
+
+/*
+* Dispatch to correct frequency bumping function
+*/
+
+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;
+}
+
+
+/*
+* Queue announcment that scan has been stopped
+*/
+
+static void stop_scan(struct rpt *myrpt, int flag)
+{
+ myrpt->hfscanmode = 0;
+ myrpt->hfscanstatus = ((flag) ? -2 : -1);
+}
+
+/*
+* This is called periodically when in scan mode
+*/
+
+
+static int service_scan(struct rpt *myrpt)
+{
+ int res, interval;
+ char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
+
+ switch(myrpt->hfscanmode){
+
+ case HF_SCAN_DOWN_SLOW:
+ interval = -10; /* 100Hz /sec */
+ break;
+
+ case HF_SCAN_DOWN_QUICK:
+ interval = -50; /* 500Hz /sec */
+ break;
+
+ case HF_SCAN_DOWN_FAST:
+ interval = -200; /* 2KHz /sec */
+ break;
+
+ case HF_SCAN_UP_SLOW:
+ interval = 10; /* 100Hz /sec */
+ break;
+
+ case HF_SCAN_UP_QUICK:
+ interval = 50; /* 500 Hz/sec */
+ break;
+
+ case HF_SCAN_UP_FAST:
+ interval = 200; /* 2KHz /sec */
+ break;
+
+ default:
+ myrpt->hfscanmode = 0; /* Huh? */
+ return -1;
+ }
+
+ res = split_freq(mhz, decimals, myrpt->freq);
+
+ if(!res){
+ k100 =decimals[0];
+ k10 = decimals[1];
+ res = multimode_bump_freq(myrpt, interval);
+ }
+
+ if(!res)
+ res = split_freq(mhz, decimals, myrpt->freq);
+
+
+ if(res){
+ stop_scan(myrpt,1);
+ return -1;
+ }
+
+ /* 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;
+ }
+ return res;
+
+}
+
+
+
+/*
+* Remote base function
+*/
+
+static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source)
+{
+ char *s,*s1,*s2,*val;
+ int i,j,ht,k,l,ls2,m,d,res,offset,offsave;
+ char multimode = 0;
+ char oc;
+ char tmp[20], freq[20] = "", savestr[20] = "";
+ char mhz[MAXREMSTR], decimals[MAXREMSTR];
+ struct ast_channel *mychannel;
+
+ if((!param) || (command_source != SOURCE_RMT))
+ return DC_ERROR;
+
+
+ multimode = multimode_capable(myrpt);
+
+ mychannel = myrpt->remchannel;
+
+
+ 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;
+ }
+
+ val = ast_variable_retrieve(cfg, MEMORY, digitbuf);
+ if (!val){
+ if (ast_safe_sleep(mychannel,1000) == -1)
+ return DC_ERROR;
+ sayfile(mychannel,"rpt/memory_notfound");
+ return DC_COMPLETE;
+ }
+ strncpy(tmp,val,sizeof(tmp) - 1);
+ s = strchr(tmp,',');
+ if (!s)
+ return DC_ERROR;
+ *s++ = 0;
+ s1 = strchr(s,',');
+ if (!s1)
+ return DC_ERROR;
+ *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)
{
- l = l->next;
- continue;
+ 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;
+ }
}
- /* 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 = strdup(str);
- if (l->chan) ast_write(l->chan,&wf);
+
+
+ if (setrem(myrpt) == -1)
+ 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 N+*N+*N or N+*N+* depending on mode */
+ if(digitbuf[i] == '*'){
+ j++;
+ continue;
+ }
+ if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
+ return DC_ERROR;
+ else{
+ if(j == 0)
+ l++; /* # of digits before first * */
+ if(j == 1)
+ k++; /* # of digits after first * */
}
- return;
}
- l = l->next;
- }
- l = myrpt->links.next;
- /* otherwise, send it to all of em */
- while(l != &myrpt->links)
- {
- /* dont send back from where it came */
- if ((l == mylink) || (!strcmp(l->name,mylink->name)))
- {
- l = l->next;
- continue;
+
+ i = strlen(digitbuf) - 1;
+ if(multimode){
+ if((j > 2) || (l > 3) || (k > 6))
+ return DC_ERROR; /* &^@#! */
+ }
+ else{
+ if((j > 2) || (l > 4) || (k > 3))
+ return DC_ERROR; /* &^@#! */
}
- /* send, but not to src */
- if (strcmp(l->name,src)) {
- wf.data = strdup(str);
- if (l->chan) ast_write(l->chan,&wf);
+
+ /* For FM modulation mode, we require M+*K+*O, for other modulation modes M+*K+* will suffice */
+
+ if((j < 2) || ((myrpt->remmode == REM_MODE_FM) && (digitbuf[i] == '*')))
+ break; /* Not yet */
+
+ strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
+
+ s = tmp;
+ s1 = strsep(&s, "*"); /* Pick off MHz */
+ s2 = strsep(&s,"*"); /* Pick off KHz and Hz */
+ oc = *s; /* Pick off offset */
+ 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'))
+ return DC_ERROR;
+ }
+ 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:
+ return DC_ERROR;
+
}
- l = l->next;
- }
- return;
- }
- ast_mutex_lock(&myrpt->lock);
- if (myrpt->callmode == 1)
- {
- myrpt->exten[myrpt->cidx++] = c;
- myrpt->exten[myrpt->cidx] = 0;
- /* if this exists */
- if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
- {
- myrpt->callmode = 2;
- rpt_telemetry(myrpt,PROC,NULL);
- }
- /* if can continue, do so */
- if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,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->funcchar)
- {
- myrpt->rem_dtmfidx = 0;
- myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
- time(&myrpt->rem_dtmf_time);
- ast_mutex_unlock(&myrpt->lock);
- return;
- }
- else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
- {
- time(&myrpt->rem_dtmf_time);
- if (myrpt->rem_dtmfidx < MAXDTMF)
- {
- myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
- myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
+
+
- ast_mutex_unlock(&myrpt->lock);
- strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
- res = collect_function_digits(myrpt, cmd, SOURCE_LNK);
- ast_mutex_lock(&myrpt->lock);
+ snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
+ if(debug)
+ printf("New frequency: %s\n", freq);
+
+ split_freq(mhz, decimals, freq);
+ m = atoi(mhz);
+ d = atoi(decimals);
+
+ if(check_freq(myrpt, m, d)) /* Check to see if frequency entered is legit */
+ return DC_ERROR;
+
+ if((myrpt->remmode == REM_MODE_FM) && (m < 29)) /* FM not allowed below 29 MHZ */
+ return DC_ERROR;
+
+ offset = REM_SIMPLEX;
- switch(res){
+ if (oc){
+ switch(oc){
+ case '1':
+ offset = REM_MINUS;
+ break;
+
+ case '2':
+ case 0:
+ offset = REM_SIMPLEX;
+ break;
+
+ case '3':
+ offset = REM_PLUS;
+ break;
+
+ default:
+
+ return DC_ERROR;
+ }
+ }
+
+ offsave = myrpt->offset;
+ strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
+ strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
+
+ myrpt->offset = offset;
+
+ if (setrem(myrpt) == -1){
+ myrpt->offset = offsave;
+ strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
+ return DC_ERROR;
+ }
+
+ return DC_COMPLETE;
+
+ case 3: /* 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;
+ }
+ 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;
+
+ case 4: /* 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++;
+ }
+ }
+ 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 (setrem(myrpt) == -1){
+ strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
+ return DC_ERROR;
+ }
+
+
+ return DC_COMPLETE;
+
- case DC_INDETERMINATE:
+ 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;
break;
-
- case DC_REQ_FLUSH:
- myrpt->rem_dtmfidx = 0;
- myrpt->rem_dtmfbuf[0] = 0;
+
+ case '2':
+ myrpt->remmode = REM_MODE_USB;
break;
-
-
- case DC_COMPLETE:
- myrpt->rem_dtmfbuf[0] = 0;
- myrpt->rem_dtmfidx = -1;
- myrpt->rem_dtmf_time = 0;
+
+ case '3':
+ myrpt->remmode = REM_MODE_LSB;
break;
- case DC_ERROR:
+ case '4':
+ myrpt->remmode = REM_MODE_AM;
+ break;
+
default:
- myrpt->rem_dtmfbuf[0] = 0;
- myrpt->rem_dtmfidx = -1;
- myrpt->rem_dtmf_time = 0;
+ return DC_ERROR;
+ }
+
+ 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:
+
+ switch(myatoi(param)){ /* Quick commands requiring a setrem call */
+ case 100: /* RX PL Off */
+ myrpt->rxplon = 0;
+ break;
+
+ case 101: /* RX PL On */
+ myrpt->rxplon = 1;
+ break;
+
+ case 102: /* TX PL Off */
+ myrpt->txplon = 0;
+ break;
+
+ case 103: /* TX PL On */
+ myrpt->txplon = 1;
+ break;
+
+ case 104: /* Low Power */
+ myrpt->powerlevel = REM_LOWPWR;
+ break;
+
+ case 105: /* Medium Power */
+ myrpt->powerlevel = REM_MEDPWR;
+ break;
+
+ case 106: /* Hi Power */
+ myrpt->powerlevel = REM_HIPWR;
break;
+
+ default:
+ return DC_ERROR;
}
- }
- }
- ast_mutex_unlock(&myrpt->lock);
- return;
-}
+ if (setrem(myrpt) == -1)
+ return DC_ERROR;
+ return DC_COMPLETE;
-/* Doug Hall RBI-1 serial data definitions:
- *
- * Byte 0: Expansion external outputs
- * Byte 1:
- * Bits 0-3 are BAND as follows:
- * Bits 4-5 are POWER bits as follows:
- * 00 - Low Power
- * 01 - Hi Power
- * 02 - Med Power
- * Bits 6-7 are always set
- * Byte 2:
- * Bits 0-3 MHZ in BCD format
- * Bits 4-5 are offset as follows:
- * 00 - minus
- * 01 - plus
- * 02 - simplex
- * 03 - minus minus (whatever that is)
- * Bit 6 is the 0/5 KHZ bit
- * Bit 7 is always set
- * Byte 3:
- * Bits 0-3 are 10 KHZ in BCD format
- * Bits 4-7 are 100 KHZ in BCD format
- * Byte 4: PL Tone code and encode/decode enable bits
- * Bits 0-5 are PL tone code (comspec binary codes)
- * Bit 6 is encode enable/disable
- * Bit 7 is decode enable/disable
- */
+ case 107: /* Bump down 20Hz */
+ multimode_bump_freq(myrpt, -20);
+ return DC_COMPLETE;
-/* take the frequency from the 10 mhz digits (and up) and convert it
- to a band number */
+ case 108: /* Bump down 100Hz */
+ multimode_bump_freq(myrpt, -100);
+ return DC_COMPLETE;
-static int rbi_mhztoband(char *str)
-{
-int i;
+ case 109: /* Bump down 500Hz */
+ multimode_bump_freq(myrpt, -500);
+ return DC_COMPLETE;
- i = atoi(str) / 10; /* get the 10's of mhz */
- switch(i)
- {
- case 2:
- return 10;
- case 5:
- return 11;
- case 14:
- return 2;
- case 22:
- return 3;
- case 44:
- return 4;
- case 124:
- return 0;
- case 125:
- return 1;
- case 126:
- return 8;
- case 127:
- return 5;
- case 128:
- return 6;
- case 129:
- return 7;
- default:
- break;
- }
- 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;
-/* take a PL frequency and turn it into a code */
-static int rbi_pltocode(char *str)
-{
-int i;
-char *s;
+ case 112: /* Bump up 500Hz */
+ multimode_bump_freq(myrpt, 500);
+ return DC_COMPLETE;
- s = strchr(str,'.');
- i = 0;
- if (s) i = atoi(s + 1);
- i += atoi(str) * 10;
- switch(i)
- {
- case 670:
- return 0;
- case 719:
- return 1;
- case 744:
- return 2;
- case 770:
- return 3;
- case 797:
- return 4;
- case 825:
- return 5;
- case 854:
- return 6;
- case 885:
- return 7;
- case 915:
- return 8;
- case 948:
- return 9;
- case 974:
- return 10;
- case 1000:
- return 11;
- case 1035:
- return 12;
- case 1072:
- return 13;
- case 1109:
- return 14;
- case 1148:
- return 15;
- case 1188:
- return 16;
- case 1230:
- return 17;
- case 1273:
- return 18;
- case 1318:
- return 19;
- case 1365:
- return 20;
- case 1413:
- return 21;
- case 1462:
- return 22;
- case 1514:
- return 23;
- case 1567:
- return 24;
- case 1622:
- return 25;
- case 1679:
- return 26;
- case 1738:
- return 27;
- case 1799:
- return 28;
- case 1862:
- return 29;
- case 1928:
- return 30;
- case 2035:
- return 31;
- case 2107:
- return 32;
- case 2181:
- return 33;
- case 2257:
- return 34;
- case 2336:
- return 35;
- case 2418:
- return 36;
- case 2503:
- return 37;
- }
- return -1;
-}
-/*
-* Shift out a formatted serial bit stream
-*/
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
-static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
- {
- int i,j;
- unsigned char od,d;
- static volatile long long delayvar;
+ 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;
+ }
+ break;
- for(i = 0 ; i < 5 ; i++){
- od = *data++;
- for(j = 0 ; j < 8 ; j++){
- d = od & 1;
- outb(d,myrpt->iobase);
- /* >= 15 us */
- for(delayvar = 1; delayvar < 15000; delayvar++);
- od >>= 1;
- outb(d | 2,myrpt->iobase);
- /* >= 30 us */
- for(delayvar = 1; delayvar < 30000; delayvar++);
- outb(d,myrpt->iobase);
- /* >= 10 us */
- for(delayvar = 1; delayvar < 10000; delayvar++);
- }
- }
- /* >= 50 us */
- for(delayvar = 1; delayvar < 50000; delayvar++);
- }
+ 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;
+ }
+ break;
+ }
+ if (!myrpt->remoterx){
+ ast_indicate(mychannel,AST_CONTROL_RADIO_UNKEY);
+ }
+ return DC_COMPLETE;
-static void rbi_out(struct rpt *myrpt,unsigned char *data)
-{
-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);
- 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);
- return;
- }
-}
+ case 119: /* Tune Request */
+ myrpt->tunerequest = 1;
+ return DC_COMPLETE;
-static int setrbi(struct rpt *myrpt)
-{
-char tmp[MAXREMSTR] = "",rbicmd[5],*s;
-int band,txoffset = 0,txpower = 0,rxpl;
+ case 5: /* Long Status */
+ case 140: /* Short Status */
+ 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;
- /* must be a remote system */
- if (!myrpt->remote) return(0);
- /* must have rbi hardware */
- if (strncmp(myrpt->remote,"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;
- }
-
- rxpl = rbi_pltocode(myrpt->rxpl);
+ 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){
+ 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){
+ if (!myrpt->remoterx){
+
+ ast_indicate(mychannel,AST_CONTROL_RADIO_UNKEY);
+ }
+ return DC_ERROR;
+ }
+ if(myrpt->remmode == REM_MODE_FM){ /* Mode FM? */
+ switch(myrpt->offset){
- if (rxpl == -1){
- if(debug)
- printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
- return -1;
- }
+ 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:
+ return DC_ERROR;
-
- 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;
- }
- rbicmd[0] = 0;
- rbicmd[1] = band | txpower | 0xc0;
- rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
- if (s[2] == '5') rbicmd[2] |= 0x40;
- rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
- rbicmd[4] = rxpl;
- if (myrpt->txplon) rbicmd[4] |= 0x40;
- if (myrpt->rxplon) rbicmd[4] |= 0x80;
- rbi_out(myrpt,rbicmd);
- return 0;
-}
+ }
+ }
+ 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:
+ return DC_ERROR;
+ }
+ }
+
+ if (res == -1){
+
+ if (!myrpt->remoterx){
+
+ ast_indicate(mychannel,AST_CONTROL_RADIO_UNKEY);
+ }
+ return DC_ERROR;
+ }
+
+ if(myatoi(param) == 140) /* Short status? */
+ 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");
+ 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)){
+ if (!myrpt->remoterx){
+ ast_indicate(mychannel,AST_CONTROL_RADIO_UNKEY);
+ }
+ return DC_ERROR;
+ }
+ if (!myrpt->remoterx){
+ ast_indicate(mychannel,AST_CONTROL_RADIO_UNKEY);
+ }
+ return DC_COMPLETE;
+
+ default:
+ return DC_ERROR;
+ }
+
+ return DC_INDETERMINATE;
+}
static int handle_remote_dtmf_digit(struct rpt *myrpt,char c)
{
time_t now;
int ret,res = 0;
+ /* Stop scan mode if in scan mode */
+ if(myrpt->hfscanmode){
+ stop_scan(myrpt,0);
+ return 0;
+ }
+
time(&now);
/* if timed-out */
if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
{
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_MEDPWR;
continue;
myrpt->dtmfidx = -1;
myrpt->dtmfbuf[0] = 0;
myrpt->dtmf_time_rem = 0;
+ myrpt->hfscanmode = 0;
+ myrpt->hfscanstatus = 0;
ast_mutex_unlock(&myrpt->lock);
- setrbi(myrpt);
+ setrem(myrpt);
ast_set_write_format(chan, AST_FORMAT_SLINEAR);
ast_set_read_format(chan, AST_FORMAT_SLINEAR);
/* if we are on 2w loop and are a remote, turn EC on */
cs[n++] = myrpt->rxchannel;
if (myrpt->rxchannel != myrpt->txchannel)
cs[n++] = myrpt->txchannel;
- for(;;)
+ for(;;)
{
if (ast_check_hangup(chan)) break;
if (ast_check_hangup(myrpt->rxchannel)) break;
myrpt->remotetx = 0;
ast_indicate(myrpt->txchannel,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);
+ 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;
+ if(myrpt->remoterx == 0)
+ ast_indicate(chan, AST_CONTROL_RADIO_UNKEY);
+ set_mode_ft897(myrpt, 0x88);
+ setrem(myrpt);
+ }
+
+
+
+
+ if (myrpt->hfscanmode){
+ myrpt->scantimer -= elap;
+ if(myrpt->scantimer <= 0){
+ myrpt->scantimer = REM_SCANTIME;
+ service_scan(myrpt);
+ }
+ }
+
+
if (who == chan) /* if it was a read from incomming */
{
f = ast_read(chan);
memset(f->data,0,f->datalen);
ast_write(myrpt->txchannel,f);
}
- else if (f->frametype == AST_FRAME_TEXT)
+ if (f->frametype == AST_FRAME_TEXT)
{
myrpt->remchannel = chan; /* Save copy of channel */
if (handle_remote_data(myrpt,f->data) == -1)
break;
}
}
- else if (f->frametype == AST_FRAME_CONTROL)
+ if (f->frametype == AST_FRAME_CONTROL)
{
if (f->subclass == AST_CONTROL_HANGUP)
{
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 );
+ }
+ if (!myrpt->remoterx)
+ {
+ ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_UNKEY);
+ }
+ myrpt->hfscanstatus = 0;
+ }
ast_frfree(f);
continue;
}
ast_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;
ast_mutex_unlock(&myrpt->lock);
+ closerem(myrpt);
LOCAL_USER_REMOVE(u);
return res;
}