Skip to content
Snippets Groups Projects
app_rpt.c 176 KiB
Newer Older
  • Learn to ignore specific revisions
  • static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
    
    Jim Dixon's avatar
    Jim Dixon committed
    	int i,j,ht,k,l,ls2,m,d,res,offset,offsave, modesave, defmode;
    
    	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_RPT) || (command_source == SOURCE_LNK))
    
    		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, myrpt->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)
    
    				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 (setrem(myrpt) == -1)
    				return DC_ERROR;
    		
    		
    			return DC_COMPLETE;	
    			
    		case 2:  /* set freq and offset */
    	   
    			
    
    Jim Dixon's avatar
    Jim Dixon committed
    	    		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'))
    
    Jim Dixon's avatar
    Jim Dixon committed
    					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))
    
    Jim Dixon's avatar
    Jim Dixon committed
    					goto invalid_freq; /* &^@#! */
    
     			}
    			else{
    				if((j > 2) || (l > 4) || (k > 3))
    
    Jim Dixon's avatar
    Jim Dixon committed
    					goto invalid_freq; /* &^@#! */
    
    Jim Dixon's avatar
    Jim Dixon committed
    			/* Wait for M+*K+* */
    
    Jim Dixon's avatar
    Jim Dixon committed
    			if(j < 2)
    
    Jim Dixon's avatar
    Jim Dixon committed
    			/* 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'))
    
    Jim Dixon's avatar
    Jim Dixon committed
    							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:
    
    Jim Dixon's avatar
    Jim Dixon committed
    					goto invalid_freq;
    
    Jim Dixon's avatar
    Jim Dixon committed
    			/* Check frequency for validity and establish a default mode */
    
    			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);
    
    
    Jim Dixon's avatar
    Jim Dixon committed
                            if(check_freq(myrpt, m, d, &defmode)) /* Check to see if frequency entered is legit */
                                    goto invalid_freq;
    
    Jim Dixon's avatar
    Jim Dixon committed
     			if((defmode == REM_MODE_FM) && (digitbuf[i] == '*')) /* If FM, user must enter and additional offset digit */
    				break; /* Not yet */
    
    
    			offset = REM_SIMPLEX; /* Assume simplex */
    
    			if(defmode == REM_MODE_FM){
    				oc = *s; /* Pick off offset */
    
    Jim Dixon's avatar
    Jim Dixon committed
    				if (oc){
    					switch(oc){
    						case '1':
    							offset = REM_MINUS;
    							break;
    
    Jim Dixon's avatar
    Jim Dixon committed
    						case '2':
    							offset = REM_SIMPLEX;
    
    Jim Dixon's avatar
    Jim Dixon committed
    						case '3':
    							offset = REM_PLUS;
    							break;
    
    Jim Dixon's avatar
    Jim Dixon committed
    						default:
    							goto invalid_freq;
    					} 
    
    Jim Dixon's avatar
    Jim Dixon committed
    			modesave = myrpt->remmode;
    
    			strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
    			strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
    			myrpt->offset = offset;
    
    Jim Dixon's avatar
    Jim Dixon committed
    			myrpt->remmode = defmode;
    
    
    			if (setrem(myrpt) == -1){
    				myrpt->offset = offsave;
    
    Jim Dixon's avatar
    Jim Dixon committed
    				myrpt->remmode = modesave;
    
    				strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
    
    Jim Dixon's avatar
    Jim Dixon committed
    				goto invalid_freq;
    
    Jim Dixon's avatar
    Jim Dixon committed
    
    
    			invalid_freq:
    	
    			rmt_sayfile(myrpt, mychannel, 1000, "rpt/invalid-freq");
    
    			return DC_ERROR; 
    
    Jim Dixon's avatar
    Jim Dixon committed
    		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 = '.';
    
    Jim Dixon's avatar
    Jim Dixon committed
    			strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
    			strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
    
    Jim Dixon's avatar
    Jim Dixon committed
    				strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
    
    Jim Dixon's avatar
    Jim Dixon committed
    		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;
    				}
    				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 = '.';
    
    Jim Dixon's avatar
    Jim Dixon committed
    			strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
    			strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
    
    Jim Dixon's avatar
    Jim Dixon committed
    				strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
    
    Jim Dixon's avatar
    Jim Dixon committed
    
    
    		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;
    
    Jim Dixon's avatar
    Jim Dixon committed
    					res = rmt_saycharstr(myrpt, mychannel, 1000,"FM");
    
    Jim Dixon's avatar
    Jim Dixon committed
    					res = rmt_saycharstr(myrpt, mychannel, 1000,"USB");
    					break;	
    
    Jim Dixon's avatar
    Jim Dixon committed
    					res = rmt_saycharstr(myrpt, mychannel, 1000,"LSB");
    
    				case '4':
    					myrpt->remmode = REM_MODE_AM;
    
    Jim Dixon's avatar
    Jim Dixon committed
    					res = rmt_saycharstr(myrpt, mychannel, 1000,"AM");
    
    Jim Dixon's avatar
    Jim Dixon committed
    			if(res)
    				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:
    
    Jim Dixon's avatar
    Jim Dixon committed
     			res = rmt_telem_start(myrpt, mychannel, 1000);
    
    			switch(myatoi(param)){ /* Quick commands requiring a setrem call */
    				case 100: /* RX PL Off */
    					myrpt->rxplon = 0;
    
    Jim Dixon's avatar
    Jim Dixon committed
    					if(!res)
    						res = sayfile(mychannel, "rpt/rxpl");
    					if(!res)
    						sayfile(mychannel, "rpt/off");
    
    					break;
    					
    				case 101: /* RX PL On */
    					myrpt->rxplon = 1;
    
    Jim Dixon's avatar
    Jim Dixon committed
    					if(!res)
    						res = sayfile(mychannel, "rpt/rxpl");
    					if(!res)
    						sayfile(mychannel, "rpt/on");
    
    					
    				case 102: /* TX PL Off */
    					myrpt->txplon = 0;
    
    Jim Dixon's avatar
    Jim Dixon committed
    					if(!res)
    						res = sayfile(mychannel, "rpt/txpl");
    					if(!res)
    						sayfile(mychannel, "rpt/off");
    
    					break;
    					
    				case 103: /* TX PL On */
    					myrpt->txplon = 1;
    
    Jim Dixon's avatar
    Jim Dixon committed
    					if(!res)
    						res = sayfile(mychannel, "rpt/txpl");
    					if(!res)
    						sayfile(mychannel, "rpt/on");
    
    					break;
    					
    				case 104: /* Low Power */
    					myrpt->powerlevel = REM_LOWPWR;
    
    Jim Dixon's avatar
    Jim Dixon committed
    					if(!res)
    						res = sayfile(mychannel, "rpt/lopwr");
    
    					break;
    					
    				case 105: /* Medium Power */
    					myrpt->powerlevel = REM_MEDPWR;
    
    Jim Dixon's avatar
    Jim Dixon committed
    					if(!res)
    						res = sayfile(mychannel, "rpt/medpwr");
    
    					break;
    					
    				case 106: /* Hi Power */
    					myrpt->powerlevel = REM_HIPWR;
    
    Jim Dixon's avatar
    Jim Dixon committed
    					if(!res)
    						res = sayfile(mychannel, "rpt/hipwr");
    
    Jim Dixon's avatar
    Jim Dixon committed
    					if(!res)
    						rmt_telem_finish(myrpt, mychannel);
    
    Jim Dixon's avatar
    Jim Dixon committed
    			if(!res)
    				res = rmt_telem_finish(myrpt, mychannel);
    			if(res)
    				return DC_ERROR;
    
    			if (setrem(myrpt) == -1) 
    				return DC_ERROR;
    			return DC_COMPLETE;
    
    		case 107: /* Bump down 20Hz */
    			multimode_bump_freq(myrpt, -20);
    			return DC_COMPLETE;
    
    		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:
    		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;
    
    				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;
    
    				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;
    			}
    
    Jim Dixon's avatar
    Jim Dixon committed
    			rmt_telem_finish(myrpt,mychannel);
    
    		case 119: /* Tune Request */
    			myrpt->tunerequest = 1;
    			return DC_COMPLETE;
    
    		case 5: /* Long Status */
    		case 140: /* Short Status */
    
    Jim Dixon's avatar
    Jim Dixon committed
    			res = rmt_telem_start(myrpt, mychannel, 1000);
    
    			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){	
    
    Jim Dixon's avatar
    Jim Dixon committed
    				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;
    				
    					case REM_SIMPLEX:
    						res = sayfile(mychannel,"rpt/simplex");
    						break;
    					
    					case REM_PLUS:
    						res = sayfile(mychannel,"rpt/plus");
    						break;
    					
    					default:
    						return DC_ERROR;
    
    				}
    			}
    			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){
    
    Jim Dixon's avatar
    Jim Dixon committed
    				rmt_telem_finish(myrpt,mychannel);
    
    Jim Dixon's avatar
    Jim Dixon committed
    			if(myatoi(param) == 140){ /* Short status? */
    				if(!res)
    					res = rmt_telem_finish(myrpt, mychannel);
    				if(res)
    					return DC_ERROR;
    
    			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) ||
    
    Jim Dixon's avatar
    Jim Dixon committed
    				(sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1))
    				{
    					rmt_telem_finish(myrpt,mychannel);
    					return DC_ERROR;
    
    Jim Dixon's avatar
    Jim Dixon committed
    			if(!res)
    				res = rmt_telem_finish(myrpt,mychannel);
    			if(res)
    
    			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)
    
    	/* 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)
    	{
    		myrpt->dtmfidx = -1;
    		myrpt->dtmfbuf[0] = 0;
    		myrpt->dtmf_time_rem = 0;
    	}
    	/* if decode not active */
    	if (myrpt->dtmfidx == -1)
    	{
    		/* if not lead-in digit, dont worry */
    
    		if (c != myrpt->funcchar) 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)
    	{
    		myrpt->dtmfidx = 0;
    		myrpt->dtmfbuf[0] = 0;
    		myrpt->dtmf_time_rem = now;
    	}
    
    	{
    		/* if star at beginning, or 2 together, erase buffer */
    		if ((myrpt->dtmfidx < 1) || 
    
    			(myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->funcchar))
    
    		{
    			myrpt->dtmfidx = 0;
    			myrpt->dtmfbuf[0] = 0;
    			myrpt->dtmf_time_rem = now;
    			return 0;
    		}
    	}
    	myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
    	myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
    	myrpt->dtmf_time_rem = now;
    
    	src = SOURCE_RMT;
    	if (phonemode > 1) src = SOURCE_DPHONE;
    	else if (phonemode) src = SOURCE_PHONE;
    	ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
    
    		case DC_REQ_FLUSH:
    			myrpt->dtmfidx = 0;
    			myrpt->dtmfbuf[0] = 0;
    			res = 0;
    
    				
    				
    		case DC_COMPLETE:
    			myrpt->dtmfbuf[0] = 0;
    			myrpt->dtmfidx = -1;
    			myrpt->dtmf_time_rem = 0;
    			res = 1;
    
    				
    		case DC_ERROR:
    		default:
    			myrpt->dtmfbuf[0] = 0;
    			myrpt->dtmfidx = -1;
    			myrpt->dtmf_time_rem = 0;
    			res = 0;
    
    static int handle_remote_data(struct rpt *myrpt, char *str)
    
    {
    char	tmp[300],cmd[300],dest[300],src[300],c;
    
    
     	/* put string in our buffer */
    	strncpy(tmp,str,sizeof(tmp) - 1);
    
    Jim Dixon's avatar
    Jim Dixon committed
    	if (!strcmp(tmp,discstr)) return 0;
    
    	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);
    
    	}
    	if (strcmp(cmd,"D"))
    	{
    		ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
    
    	if (strcmp(dest,myrpt->name)) 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->remchannel, myrpt->name, "functcomplete");
    	rmt_telem_finish(myrpt,myrpt->remchannel);
    	return res;
    }
    
    static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
    {
    int	res;
    
    
    	if (keyed && *keyed && (c == myrpt->endchar))
    	{
    		*keyed = 0;
    		return DC_INDETERMINATE;
    	}
    
    	res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
    
    	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->remchannel, myrpt->name, "functcomplete");
    
    Jim Dixon's avatar
    Jim Dixon committed
    	rmt_telem_finish(myrpt,myrpt->remchannel);
    
    static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
    {
    
    	char tmp[300], deststr[300] = "";
    
    
    	val = ast_variable_retrieve(cfg, myrpt->nodes, l->name);
    
    	if (!val)
    	{
    		fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
    		return -1;
    	}
    
    Jim Dixon's avatar
    Jim Dixon committed
    	/* remove from queue */
    	remque((struct qelem *) l);
    
    	strncpy(tmp,val,sizeof(tmp) - 1);
    	s = tmp;
    	s1 = strsep(&s,",");
    
    	snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
    	tele = strchr(deststr, '/');
    	if (!tele) {
    		fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
    		return -1;
    	}
    	*tele++ = 0;
    	l->elaptime = 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);
    		l->chan->whentohangup = 0;
    		l->chan->appl = "Apprpt";
    		l->chan->data = "(Remote Rx)";
    		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)
    			free(l->chan->cid.cid_num);
    		l->chan->cid.cid_num = strdup(myrpt->name);
    
                    ast_call(l->chan,tele,999); 
    
    
    	}
    	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;
    	}
    
    Jim Dixon's avatar
    Jim Dixon committed
    	/* put back in queue queue */
    	insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
    
    	ast_log(LOG_NOTICE,"Reconnect Attempt to %s in process\n",l->name);
    
    /* 0 return=continue, 1 return = break, -1 return = error */
    static void local_dtmf_helper(struct rpt *myrpt,char c)
    {
    int	res;
    pthread_attr_t	attr;
    char	cmd[MAXDTMF+1] = "";
    
    	if (c == myrpt->endchar)
    	{
    	/* if in simple mode, kill autopatch */
    		if (myrpt->simple && myrpt->callmode)
    		{
    			rpt_mutex_lock(&myrpt->lock);
    			myrpt->callmode = 0;
    			rpt_mutex_unlock(&myrpt->lock);
    			rpt_telemetry(myrpt,TERM,NULL);
    			return;
    		}
    		rpt_mutex_lock(&myrpt->lock);
    		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);
    		} else rpt_mutex_unlock(&myrpt->lock);
    		return;
    	}
    	rpt_mutex_lock(&myrpt->lock);
    	if (myrpt->cmdnode[0])
    	{
    		rpt_mutex_unlock(&myrpt->lock);
    		send_link_dtmf(myrpt,c);
    		return;
    	}
    	if (!myrpt->simple)
    	{
    		if (c == myrpt->funcchar)
    		{
    			myrpt->dtmfidx = 0;
    			myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
    			rpt_mutex_unlock(&myrpt->lock);
    			time(&myrpt->dtmf_time);
    			return;
    		} 
    		else if ((c != myrpt->endchar) && (myrpt->dtmfidx >= 0))
    		{
    			time(&myrpt->dtmf_time);
    			
    			if (myrpt->dtmfidx < MAXDTMF)
    			{
    				myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
    				myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
    				
    				strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
    				
    				rpt_mutex_unlock(&myrpt->lock);
    				res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL);
    				rpt_mutex_lock(&myrpt->lock);
    				switch(res){
    				    case DC_INDETERMINATE:
    					break;
    				    case DC_REQ_FLUSH:
    					myrpt->dtmfidx = 0;
    					myrpt->dtmfbuf[0] = 0;
    					break;
    				    case DC_COMPLETE:
    					myrpt->dtmfbuf[0] = 0;
    					myrpt->dtmfidx = -1;
    					myrpt->dtmf_time = 0;
    					break;
    
    				    case DC_ERROR:
    				    default:
    					myrpt->dtmfbuf[0] = 0;
    					myrpt->dtmfidx = -1;
    					myrpt->dtmf_time = 0;
    					break;
    				}
    				if(res != DC_INDETERMINATE) {
    					rpt_mutex_unlock(&myrpt->lock);
    					return;
    				}
    			} 
    		}
    	}
    	else /* if simple */