Skip to content
Snippets Groups Projects
app_rpt.c 199 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		/* 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 (!strcmp(myrpt->name, chan->cid.cid_num)) {
    
    			ast_log(LOG_WARNING, "Trying to link to self!!\n");
    			return -1;
    		}
    
    		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 (!strcmp(l->name, chan->cid.cid_num))
    				break;
    
    Jim Dixon's avatar
    Jim Dixon committed
    			l->killme = 1;
    			l->retries = MAX_RETRIES + 1;
    			l->disced = 2;
    
    		/* establish call in tranceive mode */
    
    			ast_log(LOG_WARNING, "Unable to malloc\n");
    
    		ast_copy_string(l->name, chan->cid.cid_num, sizeof(l->name));
    
    		l->isremote = 0;
    		l->chan = chan;
    		l->connected = 1;
    
    Jim Dixon's avatar
    Jim Dixon committed
    		l->hasconnected = 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");
    
    		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);
    		}
    
    		insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
    
    		if (chan->_state != AST_STATE_UP) {
    			ast_answer(chan);
    		}
    		return AST_PBX_KEEPALIVE;
    	}
    
    	/* if remote, error if anyone else already linked */
    
    		usleep(500000);
    
    		if (myrpt->remoteon) {
    			ast_log(LOG_WARNING, "Trying to use busy link on %s\n", args.node);
    
    			return -1;
    		}		
    
    	if (ioperm(myrpt->p.iobase, 1, 1) == -1) {
    
    		ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n", myrpt->p.iobase);
    
    	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);
    
    	tele = strchr(myrpt->rxchanname, '/');
    	if (!tele) {
    		ast_log(LOG_ERROR, "rpt:Dial number must be in format tech/number\n");
    
    	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);
    
    		ast_call(myrpt->rxchannel, tele, 999);
    
    	} else {
    		ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Rx channel\n");
    
    	if (myrpt->txchanname) {
    		tele = strchr(myrpt->txchanname, '/');
    		if (!tele) {
    			ast_log(LOG_ERROR, "rpt:Dial number must be in format tech/number\n");
    
    Jim Dixon's avatar
    Jim Dixon committed
    			ast_hangup(myrpt->rxchannel);
    
    		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);
    
    			ast_call(myrpt->txchannel, tele, 999);
    
    		} else {
    			ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n");
    
    Jim Dixon's avatar
    Jim Dixon committed
    			ast_hangup(myrpt->rxchannel);
    
    		myrpt->txchannel = myrpt->rxchannel;
    	}
    	myrpt->remoterx = 0;
    	myrpt->remotetx = 0;
    
    Jim Dixon's avatar
    Jim Dixon committed
    	myrpt->retxtimer = 0;
    
    	myrpt->dtmfidx = -1;
    	myrpt->dtmfbuf[0] = 0;
    	myrpt->dtmf_time_rem = 0;
    
    	myrpt->hfscanmode = 0;
    	myrpt->hfscanstatus = 0;
    
    		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);
    	}
    
    	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)) {
    
    		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);
    
    Jim Dixon's avatar
    Jim Dixon committed
    			myrpt->remoterx = 1;
    		}
    	}
    
    	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) {
    
    			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);
    
    		who = ast_waitfor_n(cs, n, &ms);
    		if (who == NULL)
    			ms = 0;
    
    		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->remoterx) && (!myrpt->remotetx)) {
    			if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME) {
    
    Jim Dixon's avatar
    Jim Dixon committed
    				myrpt->retxtimer = 0;
    
    				ast_indicate(chan, AST_CONTROL_RADIO_UNKEY);
    
    Jim Dixon's avatar
    Jim Dixon committed
    			}
    
    		} else
    			myrpt->retxtimer = 0;
    		if (rem_totx && (!myrpt->remotetx)) { /* Remote base radio TX key */
    
    			ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_KEY);
    
    		if ((!rem_totx) && myrpt->remotetx) { /* Remote base radio TX unkey */
    
    			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)
    
    				myrpt->scantimer = REM_SCANTIME;
    				service_scan(myrpt);
    			}
    		}
    
    		if (who == chan) { /* if it was a read from incoming */
    
    			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) {
    
    			if (f->frametype == AST_FRAME_TEXT) {
    
    				myrpt->remchannel = chan; /* Save copy of channel */
    
    				if (handle_remote_data(myrpt, f->data) == -1) {
    
    			if (f->frametype == AST_FRAME_CONTROL) {
    				if (f->subclass == AST_CONTROL_HANGUP) {
    
    				if (f->subclass == AST_CONTROL_RADIO_KEY) {
    
    				if (f->subclass == AST_CONTROL_RADIO_UNKEY) {
    
    				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 == -1) {
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    						if (ast_safe_sleep(myrpt->remchannel, 1000) == -1)
    
    					}
    					sayfile(myrpt->remchannel, "rpt/stop");
    
    					saynum(myrpt->remchannel, myrpt->hfscanstatus );
    				}	
    
    				rmt_telem_finish(myrpt, myrpt->remchannel);
    
    			rpt_mutex_lock(&myrpt->lock);
    			c = myrpt->macrobuf[0];
    
    				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;
    
    			}
    			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;
    
    		if (who == myrpt->rxchannel) { /* if it was a read from radio */
    
    			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) {
    
    				if (f->subclass == AST_CONTROL_RADIO_KEY) {
    
    					ast_debug(8, "@@@@ remote rx key\n");
    
    					if (!myrpt->remotetx) {
    						ast_indicate(chan, AST_CONTROL_RADIO_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);
    
    		if ((myrpt->rxchannel != myrpt->txchannel) && (who == myrpt->txchannel)) {
    			/* do this cuz you have to */
    
    			if (f->frametype == AST_FRAME_CONTROL) {
    				if (f->subclass == AST_CONTROL_HANGUP) {
    
    	if (myrpt->rxchannel != myrpt->txchannel)
    		ast_hangup(myrpt->txchannel);
    
    	myrpt->hfscanmode = 0;
    	myrpt->hfscanstatus = 0;
    
    static int unload_module(void)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	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)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	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);
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	for (n = 0; n < nrpts; n++)
    		rpt_vars[n].reload = 1;
    
    AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater / Remote Base",
    		.load = load_module,
    		.unload = unload_module,
    		.reload = reload,