Newer
Older
/* 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);
return -1;
}
if (!strcmp(myrpt->name, chan->cid.cid_num)) {
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') {
/* if found matching string */
if (!strcmp(l->name, chan->cid.cid_num))
break;
}
/* if found */
if (l != &myrpt->links) {
l->killme = 1;
l->retries = MAX_RETRIES + 1;
l->disced = 2;
Jim Dixon
committed
reconnects = l->reconnects;
reconnects++;
rpt_mutex_unlock(&myrpt->lock);
usleep(500000);
} else
rpt_mutex_unlock(&myrpt->lock);
/* establish call in tranceive mode */
Tilghman Lesher
committed
l = ast_calloc(1, sizeof(*l));
if (!l) {
ast_log(LOG_WARNING, "Unable to malloc\n");
pthread_exit(NULL);
}
l->mode = 1;
ast_copy_string(l->name, chan->cid.cid_num, sizeof(l->name));
l->isremote = 0;
l->chan = chan;
l->connected = 1;
Jim Dixon
committed
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);
/* 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");
pthread_exit(NULL);
}
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");
pthread_exit(NULL);
}
rpt_mutex_lock(&myrpt->lock);
if (phone_mode > 1)
l->lastrx = 1;
/* insert at end of queue */
insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
rpt_mutex_unlock(&myrpt->lock);
if (chan->_state != AST_STATE_UP) {
ast_answer(chan);
}
return AST_PBX_KEEPALIVE;
}
rpt_mutex_lock(&myrpt->lock);
/* if remote, error if anyone else already linked */
if (myrpt->remoteon) {
rpt_mutex_unlock(&myrpt->lock);
if (myrpt->remoteon) {
ast_log(LOG_WARNING, "Trying to use busy link on %s\n", args.node);
rpt_mutex_lock(&myrpt->lock);
}
myrpt->remoteon = 1;
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);
return -1;
}
Jim Dixon
committed
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);
Jim Dixon
committed
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");
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);
myrpt->rxchannel->whentohangup = 0;
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);
rpt_mutex_unlock(&myrpt->lock);
ast_call(myrpt->rxchannel, tele, 999);
rpt_mutex_lock(&myrpt->lock);
} else {
ast_log(LOG_ERROR, "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");
rpt_mutex_unlock(&myrpt->lock);
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);
myrpt->txchannel->whentohangup = 0;
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);
rpt_mutex_unlock(&myrpt->lock);
ast_call(myrpt->txchannel, tele, 999);
rpt_mutex_lock(&myrpt->lock);
} else {
ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n");
rpt_mutex_unlock(&myrpt->lock);
pthread_exit(NULL);
}
*--tele = '/';
} else {
myrpt->txchannel = myrpt->rxchannel;
}
myrpt->remoterx = 0;
myrpt->remotetx = 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);
Steve Murphy
committed
if (myrpt->p.startupgosub) {
myrpt->remchannel = chan; /* Save copy of channel */
snprintf(myrpt->gosubbuf, sizeof(myrpt->gosubbuf), "PPPP%s", myrpt->p.startupgosub);
}
Jim Dixon
committed
myrpt->reload = 0;
rpt_mutex_unlock(&myrpt->lock);
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 */
if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel)) {
i = 128;
ioctl(myrpt->rxchannel->fds[0], ZT_ECHOCANCEL, &i);
}
if (chan->_state != AST_STATE_UP) {
ast_answer(chan);
}
if (ioctl(myrpt->txchannel->fds[0], ZT_GET_PARAMS, &par) != -1) {
if (par.rxisoffhook) {
ast_indicate(chan, AST_CONTROL_RADIO_KEY);
n = 0;
cs[n++] = chan;
cs[n++] = myrpt->rxchannel;
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) {
Jim Dixon
committed
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);
Jim Dixon
committed
break;
}
}
rpt_mutex_lock(&myrpt->lock);
}
ms = MSWAIT;
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;
Steve Murphy
committed
if (myrpt->gosubtimer)
myrpt->gosubtimer -= elap;
if (myrpt->gosubtimer < 0)
myrpt->gosubtimer = 0;
rpt_mutex_unlock(&myrpt->lock);
if (!ms)
continue;
rem_totx = keyed;
if ((!myrpt->remoterx) && (!myrpt->remotetx)) {
if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME) {
ast_indicate(chan, AST_CONTROL_RADIO_UNKEY);
} 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 (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;
rmt_telem_finish(myrpt, chan);
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 incoming */
f = ast_read(chan);
if (!f) {
ast_debug(1, "@@@@ link:Hung Up\n");
break;
}
if (f->frametype == AST_FRAME_VOICE) {
/* 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");
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");
ast_frfree(f);
break;
}
}
if (f->frametype == AST_FRAME_CONTROL) {
if (f->subclass == AST_CONTROL_HANGUP) {
ast_debug(1, "@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
/* if RX key */
if (f->subclass == AST_CONTROL_RADIO_KEY) {
ast_debug(8, "@@@@ rx key\n");
keyed = 1;
}
/* if RX un-key */
if (f->subclass == AST_CONTROL_RADIO_UNKEY) {
ast_debug(8, "@@@@ 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;
Steve Murphy
committed
}
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 */
f = ast_read(myrpt->rxchannel);
if (!f) {
ast_debug(1, "@@@@ 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");
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 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;
}
}
}
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");
break;
}
if (f->frametype == AST_FRAME_CONTROL) {
if (f->subclass == AST_CONTROL_HANGUP) {
ast_debug(1, "@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
}
ast_frfree(f);
continue;
}
}
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);
closerem(myrpt);
return res;
}
static int unload_module(void)
Mark Spencer
committed
int i;
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);
i = ast_unregister_application(app);
/* Unregister cli extensions */
ast_cli_unregister_multiple(cli_rpt, sizeof(cli_rpt) / sizeof(struct ast_cli_entry));
static int load_module(void)
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);
/* Register cli extensions */
ast_cli_register_multiple(cli_rpt, sizeof(cli_rpt) / sizeof(struct ast_cli_entry));
return ast_register_application(app, rpt_exec, synopsis, descrip);
static int reload(void)
Jim Dixon
committed
for (n = 0; n < nrpts; n++)
rpt_vars[n].reload = 1;
Jim Dixon
committed
return(0);
}
Kevin P. Fleming
committed
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater / Remote Base",
.load = load_module,
.unload = unload_module,
.reload = reload,