Skip to content
Snippets Groups Projects
app_rpt.c 197 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		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? */
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    static int check_freq_rbi(int m, int d, int *defmode)
    
    Jim Dixon's avatar
    Jim Dixon committed
    	int dflmd = REM_MODE_FM;
    
    
    	if (m == 50) { /* 6 meters */
    		if (d < 10100)
    
    	} else if ((m >= 51) && ( m < 54)) {
    		/* nada */
    	} else if (m == 144) { /* 2 meters */
    		if (d < 10100)
    
    	} else if ((m >= 145) && (m < 148)) {
    		/* nada */
    	} else if ((m >= 222) && (m < 225)) { /* 1.25 meters */
    		/* nada */
    	} else if ((m >= 430) && (m < 450)) { /* 70 centimeters */
    		/* nada */
    	} else if ((m >= 1240) && (m < 1300)) { /* 23 centimeters */
    		/* nada */
    	} else
    
    Jim Dixon's avatar
    Jim Dixon committed
    		*defmode = dflmd;	
    
    
    static int split_decimal(char *input, int *ints, int *decs, int places)
    {
    	double input2 = 0.0;
    	long long modifier = (long long)pow(10.0, (double)places);
    	if (sscanf(input, "%lf", &input2) == 1) {
    		long long input3 = input2 * modifier;
    		*ints = input3 / modifier;
    		*decs = input3 % modifier;
    		return 0;
    	} else
    		return -1;
    }
    
    
    #define split_freq(mhz, decimal, freq)	split_decimal(freq, mhz, decimal, 5)
    
    Jim Dixon's avatar
    Jim Dixon committed
    /*
    * Split ctcss frequency into hertz and decimal
    */
     
    
    #define split_ctcss_freq(hertz, decimal, freq)	split_decimal(freq, hertz, decimal, 1)
    
    /*
    * FT-897 I/O handlers
    */
    
    /* Check to see that the frequency is valid */
    /* Hard coded limits now, configurable later, maybe? */
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    static int check_freq_ft897(int m, int d, int *defmode)
    
    Jim Dixon's avatar
    Jim Dixon committed
    	int dflmd = REM_MODE_FM;
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd =	REM_MODE_LSB; 
    
    	} else if (m == 3) { /* 80 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_LSB;
    
    	} else if (m == 7) { /* 40 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_LSB;
    
    	} else if (m == 14) { /* 20 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_USB;
    
    	} else if (m == 18) { /* 17 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_USB;
    
    	} else if (m == 21) { /* 15 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_USB;
    
    	} else if (m == 24) { /* 12 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_USB;
    
    	} else if (m == 28) { /* 10 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_USB;
    
    Jim Dixon's avatar
    Jim Dixon committed
    			dflmd = REM_MODE_FM;
    		else
    			dflmd = REM_MODE_USB;
    
    	} else if (m == 50) { /* 6 meters */
    		if (d < 10100)
    
    Jim Dixon's avatar
    Jim Dixon committed
    			dflmd = REM_MODE_FM;
    		else
    			dflmd = REM_MODE_USB;
    
    	} else if ((m >= 51) && ( m < 54)) {
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_FM;
    
    	} else if (m == 144) { /* 2 meters */
    		if (d < 10100)
    
    Jim Dixon's avatar
    Jim Dixon committed
    			dflmd = REM_MODE_FM;
    		else
    			dflmd = REM_MODE_USB;
    
    	} else if ((m >= 145) && (m < 148)) {
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_FM;
    
    	} else if ((m >= 430) && (m < 450)) { /* 70 centimeters */
    		if (m  < 438)
    
    Jim Dixon's avatar
    Jim Dixon committed
    			dflmd = REM_MODE_USB;
    		else
    			dflmd = REM_MODE_FM;
    
    Jim Dixon's avatar
    Jim Dixon committed
    		*defmode = dflmd;
    
    
    	return 0;
    }
    
    /*
    * Set a new frequency for the FT897
    */
    
    static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
    {
    	unsigned char cmdstr[5];
    
    	if (debug) 
    		ast_log(LOG_DEBUG, "New frequency: %s\n", newfreq);
    
    		return -1; 
    
    	/* 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] = { 0, 0, 0, 0, command };
    
    
    	return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
    }
    
    /* ft-897 offset */
    
    static int set_offset_ft897(struct rpt *myrpt, char offset)
    {
    
    	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] = { 0, 0, 0, 0, 0x07 };
    
    	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;
    
    	}
    
    	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] = { 0, 0, 0, 0, 0x0A };
    
    	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 */
    
    	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] = { 0, 0, 0, 0, 0x0B };
    	int hertz, decimal;
    
    	if (split_ctcss_freq(&hertz, &decimal, txtone))
    
    	cmdstr[0] = ((hertz / 100) << 4) + (hertz % 100) / 10;
    	cmdstr[1] = ((hertz % 10) << 4) + (decimal % 10);
    
    	if (rxtone) {
    		if (split_ctcss_freq(&hertz, &decimal, rxtone))
    
    		cmdstr[2] = ((hertz / 100) << 4) + (hertz % 100)/ 10;
    		cmdstr[3] = ((hertz % 10) << 4) + (decimal % 10);
    
    	}
    
    	return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
    }	
    
    
    
    static int set_ft897(struct rpt *myrpt)
    {
    	int res;
    	
    
    	if (debug)
    		ast_log(LOG_DEBUG, "@@@@ lock on\n");
    
    
    	res = simple_command_ft897(myrpt, 0x00);				/* LOCK on */	
    
    
    	if (debug)
    		ast_log(LOG_DEBUG, "@@@@ ptt off\n");
    
    		res = simple_command_ft897(myrpt, 0x88);		/* PTT off */
    
    
    	if (debug)
    		ast_log(LOG_DEBUG, "Modulation mode\n");
    
    		res = set_mode_ft897(myrpt, myrpt->remmode);		/* Modulation mode */
    
    
    	if (debug)
    		ast_log(LOG_DEBUG, "Split off\n");
    
    		simple_command_ft897(myrpt, 0x82);			/* Split off */
    
    
    	if (debug)
    		ast_log(LOG_DEBUG, "Frequency\n");
    
    		res = set_freq_ft897(myrpt, myrpt->freq);		/* Frequency */
    
    	if ((myrpt->remmode == REM_MODE_FM)) {
    		if (debug)
    			ast_log(LOG_DEBUG, "Offset\n");
    		if (!res)
    
    			res = set_offset_ft897(myrpt, myrpt->offset);	/* Offset if FM */
    
    		if ((!res)&&(myrpt->rxplon || myrpt->txplon)) {
    			if (debug)
    				ast_log(LOG_DEBUG, "CTCSS tone freqs.\n");
    
    			res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl); /* CTCSS freqs if CTCSS is enabled */
    		}
    
    		if (!res) {
    			if (debug)
    				ast_log(LOG_DEBUG, "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)
    			ast_log(LOG_DEBUG, "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)
    {
    
    	if (debug)
    		ast_log(LOG_DEBUG, "Before bump: %s\n", myrpt->freq);
    
    	if (split_freq(&m, &d, myrpt->freq))
    
    		return -1;
    	
    	d += (interval / 10); /* 10Hz resolution */
    
    	if (check_freq_ft897(m, d, NULL)) {
    		if (debug)
    			ast_log(LOG_DEBUG, "Bump freq invalid\n");
    
    		return -1;
    	}
    
    	snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
    
    
    	if (debug)
    		ast_log(LOG_DEBUG, "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))
    
    	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
    */
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
    
    	if (!strcmp(myrpt->remote, remote_rig_ft897))
    
    Jim Dixon's avatar
    Jim Dixon committed
    		return check_freq_ft897(m, d, defmode);
    
    	else if (!strcmp(myrpt->remote, remote_rig_rbi))
    
    Jim Dixon's avatar
    Jim Dixon committed
    		return check_freq_rbi(m, d, defmode);
    
    	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, mhz, decimals;
    	char k10=0, k100=0;
    
    	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 / 10000;
    		k10 = (decimals / 1000) % 10;
    
    		res = multimode_bump_freq(myrpt, interval);
    	}
    
    
    	if (!res)
    		res = split_freq(&mhz, &decimals, myrpt->freq);
    
    	if (k10 != (decimals / 1000) % 10) {
    		int myhund = (interval < 0) ? k100 : decimals / 10000;
    		int myten = (interval < 0) ? k10 : (decimals / 1000) % 10;
    		myrpt->hfscanstatus = (myten == 0) ? (myhund) * 100 : (myten) * 10;
    
    Jim Dixon's avatar
    Jim Dixon committed
    static int rmt_telem_start(struct rpt *myrpt, struct ast_channel *chan, int delay)
    {
    
    	myrpt->remotetx = 0;
    	ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
    	if (!myrpt->remoterx)
    		ast_indicate(chan, AST_CONTROL_RADIO_KEY);
    	if (ast_safe_sleep(chan, delay) == -1)
    			return -1;
    	return 0;
    
    Jim Dixon's avatar
    Jim Dixon committed
    }
    
    
    static int rmt_telem_finish(struct rpt *myrpt, struct ast_channel *chan)
    {
    
    	if (ioctl(myrpt->txchannel->fds[0], ZT_GET_PARAMS, &par) == -1) {
    
    	if (!par.rxisoffhook) {
    		ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_UNKEY);
    
    Jim Dixon's avatar
    Jim Dixon committed
    		myrpt->remoterx = 0;
    
    Jim Dixon's avatar
    Jim Dixon committed
    		myrpt->remoterx = 1;
    	}
    	return 0;
    }
    
    
    static int rmt_sayfile(struct rpt *myrpt, struct ast_channel *chan, int delay, char *filename)
    {
    	int res;
    
    	res = rmt_telem_start(myrpt, chan, delay);
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    		res = sayfile(chan, filename);
    	
    
    Jim Dixon's avatar
    Jim Dixon committed
    		res = rmt_telem_finish(myrpt, chan);
    	return res;
    }
    
    static int rmt_saycharstr(struct rpt *myrpt, struct ast_channel *chan, int delay, char *charstr)
    {
    	int res;
    
    	res = rmt_telem_start(myrpt, chan, delay);
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    		res = saycharstr(chan, charstr);
    	
    
    Jim Dixon's avatar
    Jim Dixon committed
    		res = rmt_telem_finish(myrpt, chan);
    	return res;
    }
    
    
    static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
    
    	int i, j, ht, k, l, ls2, res, offset, offsave, modesave, defmode;
    
    	char multimode = 0;
    	char oc;
    	char tmp[20], freq[20] = "", savestr[20] = "";
    
    	AST_DECLARE_APP_ARGS(args1,
    		AST_APP_ARG(freq);
    		AST_APP_ARG(xpl);
    		AST_APP_ARG(mode);
    	);
    	AST_DECLARE_APP_ARGS(args,
    		AST_APP_ARG(s1);
    		AST_APP_ARG(s2);
    	);
    
    	if ((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
    
    		return DC_ERROR;
    		
    	multimode = multimode_capable(myrpt);
    	mychannel = myrpt->remchannel;
    
    
    	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'))
    
    		}
    
    		val = ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, digitbuf);
    		if (!val) {
    			if (ast_safe_sleep(mychannel, 1000) == -1)
    
    			sayfile(mychannel, "rpt/memory_notfound");
    			return DC_COMPLETE;
    		}
    		s = ast_strdupa(val);
    		AST_NONSTANDARD_APP_ARGS(args1, s, ',');
    		if (args1.argc < 3)
    			return DC_ERROR;
    		ast_copy_string(myrpt->freq, args1.freq, sizeof(myrpt->freq));
    		ast_copy_string(myrpt->rxpl, args1.xpl, sizeof(myrpt->rxpl));
    		ast_copy_string(myrpt->txpl, args1.xpl, sizeof(myrpt->rxpl));
    		myrpt->remmode = REM_MODE_FM;
    		myrpt->offset = REM_SIMPLEX;
    		myrpt->powerlevel = REM_MEDPWR;
    		myrpt->txplon = myrpt->rxplon = 0;
    		modestr = args1.mode;
    		while (*modestr) {
    			switch (*modestr++) {
    			case 'A':
    			case 'a':
    				strcpy(myrpt->rxpl, "100.0");
    				strcpy(myrpt->txpl, "100.0");
    				myrpt->remmode = REM_MODE_AM;	
    				break;
    
    			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 */
    		for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for M+*K+*O or M+*H+* depending on mode */
    			if (digitbuf[i] == '*') {
    				j++;
    				continue;
    
    			if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
    				goto invalid_freq;
    			else {
    				if (j == 0)
    					l++; /* # of digits before first * */
    				if (j == 1)
    					k++; /* # of digits after first * */
    
    		i = strlen(digitbuf) - 1;
    		if (multimode) {
    			if ((j > 2) || (l > 3) || (k > 6))
    				goto invalid_freq; /* &^@#! */
     		} else {
    			if ((j > 2) || (l > 4) || (k > 3))
    				goto invalid_freq; /* &^@#! */
    		}
    
    		s = ast_strdupa(digitbuf);
    		AST_NONSTANDARD_APP_ARGS(args, s, '*');
    		ls2 = strlen(args.s2);	
    
    		switch (ls2) { /* Allow partial entry of khz and hz digits for laziness support */
    		case 1:
    			ht = 0;
    			k = 100 * atoi(args.s2);
    			break;
    		case 2:
    			ht = 0;
    			k = 10 * atoi(args.s2);
    			break;
    		case 3:
    			if (!multimode) {
    				if ((args.s2[2] != '0') && (args.s2[2] != '5'))
    
    Jim Dixon's avatar
    Jim Dixon committed
    					goto invalid_freq;
    
    			ht = 0;
    			k = atoi(args.s2);
    				break;
    		case 4:
    			k = atoi(args.s2) / 10;
    			ht = 10 * (atoi(args.s2 + (ls2 - 1)));
    			break;
    		case 5:
    			k = atoi(args.s2) / 100;
    			ht = (atoi(args.s2 + (ls2 - 2)));
    			break;
    		default:
    			goto invalid_freq;
    		}
    
    		/* Check frequency for validity and establish a default mode */
    
    		snprintf(freq, sizeof(freq), "%s.%03d%02d", args.s1, k, ht);
    
    		if (debug)
    			ast_log(LOG_DEBUG, "New frequency: %s\n", freq);		
    
    		if (check_freq(myrpt, mhz, decimals, &defmode)) /* Check to see if frequency entered is legit */
    			goto invalid_freq;
    
    		if ((defmode == REM_MODE_FM) && (digitbuf[i] == '*')) /* If FM, user must enter and additional offset digit */
    			break; /* Not yet */
    
    		offset = REM_SIMPLEX; /* Assume simplex */
    
    		if (defmode == REM_MODE_FM) {
    			oc = *s; /* Pick off offset */
    			if (oc) {
    				switch (oc) {
    				case '1':
    					offset = REM_MINUS;
    					break;
    				case '2':
    					offset = REM_SIMPLEX;
    					break;
    				case '3':
    					offset = REM_PLUS;
    					break;
    				default:
    					goto invalid_freq;
    
    			} 
    		}	
    		offsave = myrpt->offset;
    		modesave = myrpt->remmode;
    		ast_copy_string(savestr, myrpt->freq, sizeof(savestr));
    		ast_copy_string(myrpt->freq, freq, sizeof(myrpt->freq));
    		myrpt->offset = offset;
    		myrpt->remmode = defmode;
    
    		if (setrem(myrpt) == -1) {
    			myrpt->offset = offsave;
    			myrpt->remmode = modesave;
    			ast_copy_string(myrpt->freq, savestr, sizeof(myrpt->freq));
    			goto invalid_freq;
    		}
    
    invalid_freq:
    		rmt_sayfile(myrpt, mychannel, 1000, "rpt/invalid-freq");
    
    		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'))
    
    			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)
    			ast_log(LOG_DEBUG, "PL digits entered %s\n", digitbuf);
     		
    		ast_copy_string(tmp, digitbuf, sizeof(tmp));
    		/* see if we have at least 1 */
    		s = strchr(tmp, '*');
    		if (s)
    			*s = '.';
    		ast_copy_string(savestr, myrpt->rxpl, sizeof(savestr));
    		ast_copy_string(myrpt->rxpl, tmp, sizeof(myrpt->rxpl));
    
    		if (setrem(myrpt) == -1) {
    			ast_copy_string(myrpt->rxpl, savestr, sizeof(myrpt->rxpl));
    			return DC_ERROR;
    		}
    
    		return DC_COMPLETE;
    	case 4: /* set tx PL tone */
    		for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for N+*N */
    			if (digitbuf[i] == '*') {
    				j++;
    				continue;
    
    			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)
    			ast_log(LOG_DEBUG, "PL digits entered %s\n", digitbuf);
    
    		ast_copy_string(tmp, digitbuf, sizeof(tmp));
    		/* see if we have at least 1 */
    		s = strchr(tmp, '*');
    		if (s)
    			*s = '.';
    		ast_copy_string(savestr, myrpt->txpl, sizeof(savestr));
    		ast_copy_string(myrpt->txpl, tmp, sizeof(myrpt->txpl));
    
    		if (setrem(myrpt) == -1) {
    			ast_copy_string(myrpt->txpl, savestr, sizeof(myrpt->txpl));
    			return DC_ERROR;
    		}
    
    		return DC_COMPLETE;
    
    	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); 
    			if (mhz < 29) /* No FM allowed below 29MHz! */
    
    			myrpt->remmode = REM_MODE_FM;
    			res = rmt_saycharstr(myrpt, mychannel, 1000, "FM");
    			break;
    
    Jim Dixon's avatar
    Jim Dixon committed
    
    
    		case '2':
    			myrpt->remmode = REM_MODE_USB;
    			res = rmt_saycharstr(myrpt, mychannel, 1000, "USB");
    			break;	
    
    		case '3':
    			myrpt->remmode = REM_MODE_LSB;
    			res = rmt_saycharstr(myrpt, mychannel, 1000, "LSB");
    			break;
    
    		case '4':
    			myrpt->remmode = REM_MODE_AM;
    			res = rmt_saycharstr(myrpt, mychannel, 1000, "AM");
    			break;
    
    		if (setrem(myrpt))
    			return DC_ERROR;
    		return DC_COMPLETE;
    
    	case 100: /* other stuff */
    	case 101:
    	case 102:
    	case 103:
    	case 104:
    	case 105:
    	case 106:
     		res = rmt_telem_start(myrpt, mychannel, 1000);
    		switch (myatoi(param)) { /* Quick commands requiring a setrem call */
    		case 100: /* RX PL Off */
    			myrpt->rxplon = 0;
    			if (!res)
    				res = sayfile(mychannel, "rpt/rxpl");
    			if (!res)
    				sayfile(mychannel, "rpt/off");
    			break;
    
    		case 101: /* RX PL On */
    			myrpt->rxplon = 1;
    			if (!res)
    				res = sayfile(mychannel, "rpt/rxpl");
    			if (!res)
    				sayfile(mychannel, "rpt/on");
    			break;
    
    		case 102: /* TX PL Off */
    			myrpt->txplon = 0;
    			if (!res)
    				res = sayfile(mychannel, "rpt/txpl");
    			if (!res)
    				sayfile(mychannel, "rpt/off");
    			break;
    
    		case 103: /* TX PL On */
    			myrpt->txplon = 1;
    			if (!res)
    				res = sayfile(mychannel, "rpt/txpl");
    			if (!res)
    				sayfile(mychannel, "rpt/on");
    			break;
    
    		case 104: /* Low Power */
    			myrpt->powerlevel = REM_LOWPWR;
    			if (!res)
    				res = sayfile(mychannel, "rpt/lopwr");
    			break;
    
    		case 105: /* Medium Power */
    			myrpt->powerlevel = REM_MEDPWR;
    			if (!res)
    				res = sayfile(mychannel, "rpt/medpwr");
    			break;