summaryrefslogtreecommitdiff
path: root/ztcfg.c
diff options
context:
space:
mode:
authorjim <jim@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-11-04 20:04:53 +0000
committerjim <jim@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2004-11-04 20:04:53 +0000
commit7e99207e834bd395443af5f88453b0aea65d3315 (patch)
tree37bdd5563db7c329733f31693fa75e7b634a8529 /ztcfg.c
parentb420103c9e0c8eaf5bf9c0b040642f08539a487f (diff)
Added support for Zapata Telephony Quad PCI Radio Interface card.
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@489 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'ztcfg.c')
-rwxr-xr-xztcfg.c429
1 files changed, 425 insertions, 4 deletions
diff --git a/ztcfg.c b/ztcfg.c
index b85cd56..0bc6cf3 100755
--- a/ztcfg.c
+++ b/ztcfg.c
@@ -25,7 +25,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Primary Author: Mark Spencer <markster@linux-support.net>
- *
+ * Radio Support by Jim Dixon <jim@lambdatel.com>
*/
#include <stdio.h>
@@ -43,6 +43,8 @@
#define NUM_SPANS ZT_MAX_SPANS
+#define NUM_TONES 15
+
/* Assume no more than 1024 dynamics */
#define NUM_DYNAMIC 1024
@@ -52,6 +54,13 @@ static FILE *cf;
static char *filename=CONFIG_FILENAME;
+int rxtones[NUM_TONES + 1],rxtags[NUM_TONES + 1],txtones[NUM_TONES + 1];
+int bursttime = 0, debouncetime = 0, invertcor = 0, exttone = 0, corthresh = 0;
+
+int corthreshes[] = {3125,6250,9375,12500,15625,18750,21875,25000,0} ;
+
+static int toneindex = 1;
+
#define DEBUG_READER (1 << 0)
#define DEBUG_PARSER (1 << 1)
#define DEBUG_APPLY (1 << 2)
@@ -85,6 +94,8 @@ static char zonestoload[ZT_TONE_ZONE_MAX][10];
static int numzones = 0;
+static int fd = -1;
+
static char *lbostr[] = {
"0 db (CSU)/0-133 feet (DSX-1)",
"133-266 feet (DSX-1)",
@@ -102,6 +113,28 @@ static char *laws[] = {
"A-law"
};
+int ind_ioctl(int channo, int fd, int op, void *data)
+{
+ZT_INDIRECT_DATA ind;
+
+ ind.chan = channo;
+ ind.op = op;
+ ind.data = data;
+ return ioctl(fd,ZT_INDIRECT,&ind);
+}
+
+static void clear_fields()
+{
+
+ memset(rxtones,0,sizeof(rxtones));
+ memset(rxtags,0,sizeof(rxtags));
+ memset(txtones,0,sizeof(txtones));
+ bursttime = 0;
+ debouncetime = 0;
+ invertcor = 0;
+ exttone = 0;
+}
+
static int error(char *fmt, ...)
{
int res;
@@ -558,6 +591,382 @@ static int unimplemented(char *keyword, char *args)
}
#endif
+
+/* Radio functions */
+
+int ctcss(char *keyword, char *args)
+{
+ static char *realargs[10];
+ int argc;
+ int res;
+ int rxtone;
+ int rxtag;
+ int txtone;
+ int isdcs = 0;
+ argc = res = parseargs(args, realargs, 3, ',');
+ if (res != 3) {
+ error("Incorrect number of arguments to 'ctcss' (should be <rxtone>,<rxtag>,<txtone>)\n");
+ }
+ res = sscanf(realargs[0], "%d", &rxtone);
+ if ((res == 1) && (rxtone < 1))
+ res = -1;
+ if (res != 1) {
+ error("Invalid rxtone '%s', should be a number > 0.\n", realargs[0]);
+ }
+ res = sscanf(realargs[1], "%i", &rxtag);
+ if ((res == 1) && (rxtag < 0))
+ res = -1;
+ if (res != 1) {
+ error("Invalid rxtag '%s', should be a number > 0.\n", realargs[1]);
+ }
+ if ((*realargs[2] == 'D') || (*realargs[2] == 'd'))
+ {
+ realargs[2]++;
+ isdcs = 0x8000;
+ }
+ res = sscanf(realargs[2], "%d", &txtone);
+ if ((res == 1) && (rxtag < 0))
+ res = -1;
+ if (res != 1) {
+ error("Invalid txtone '%s', should be a number > 0.\n", realargs[2]);
+ }
+
+ if (toneindex >= NUM_TONES)
+ {
+ error("Cannot specify more then %d CTCSS tones\n",NUM_TONES);
+ }
+ rxtones[toneindex] = rxtone;
+ rxtags[toneindex] = rxtag;
+ txtones[toneindex] = txtone | isdcs;
+ toneindex++;
+ return 0;
+}
+
+int dcsrx(char *keyword, char *args)
+{
+ static char *realargs[10];
+ int argc;
+ int res;
+ int rxtone;
+ argc = res = parseargs(args, realargs, 1, ',');
+ if (res != 1) {
+ error("Incorrect number of arguments to 'dcsrx' (should be <rxtone>)\n");
+ }
+ res = sscanf(realargs[0], "%d", &rxtone);
+ if ((res == 1) && (rxtone < 1))
+ res = -1;
+ if (res != 1) {
+ error("Invalid rxtone '%s', should be a number > 0.\n", realargs[0]);
+ }
+
+ rxtones[0] = rxtone;
+ return 0;
+}
+
+int tx(char *keyword, char *args)
+{
+ static char *realargs[10];
+ int argc;
+ int res;
+ int txtone;
+ int isdcs = 0;
+ argc = res = parseargs(args, realargs, 1, ',');
+ if (res != 1) {
+ error("Incorrect number of arguments to 'tx' (should be <txtone>)\n");
+ }
+ if ((*realargs[0] == 'D') || (*realargs[0] == 'd'))
+ {
+ realargs[0]++;
+ isdcs = 0x8000;
+ }
+ res = sscanf(realargs[0], "%d", &txtone);
+ if ((res == 1) && (txtone < 1))
+ res = -1;
+ if (res != 1) {
+ error("Invalid tx (tone) '%s', should be a number > 0.\n", realargs[0]);
+ }
+
+ txtones[0] = txtone | isdcs;
+ return 0;
+}
+
+int debounce_time(char *keyword, char *args)
+{
+ static char *realargs[10];
+ int argc;
+ int res;
+ int val;
+ argc = res = parseargs(args, realargs, 1, ',');
+ if (res != 1) {
+ error("Incorrect number of arguments to 'debouncetime' (should be <value>)\n");
+ }
+ res = sscanf(realargs[0], "%d", &val);
+ if ((res == 1) && (val < 1))
+ res = -1;
+ if (res != 1) {
+ error("Invalid value '%s', should be a number > 0.\n", realargs[0]);
+ }
+
+ debouncetime = val;
+ return 0;
+}
+
+int burst_time(char *keyword, char *args)
+{
+ static char *realargs[10];
+ int argc;
+ int res;
+ int val;
+ argc = res = parseargs(args, realargs, 1, ',');
+ if (res != 1) {
+ error("Incorrect number of arguments to 'bursttime' (should be <value>)\n");
+ }
+ res = sscanf(realargs[0], "%d", &val);
+ if ((res == 1) && (val < 1))
+ res = -1;
+ if (res != 1) {
+ error("Invalid value '%s', should be a number > 0.\n", realargs[0]);
+ }
+
+ bursttime = val;
+ return 0;
+}
+
+int invert_cor(char *keyword, char *args)
+{
+ static char *realargs[10];
+ int argc;
+ int res;
+ int val;
+ argc = res = parseargs(args, realargs, 1, ',');
+ if (res != 1) {
+ error("Incorrect number of arguments to 'invertcor' (should be <value>)\n");
+ }
+ if ((*realargs[0] == 'y') || (*realargs[0] == 'Y')) val = 1;
+ else if ((*realargs[0] == 'n') || (*realargs[0] == 'N')) val = 0;
+ else
+ {
+ res = sscanf(realargs[0], "%d", &val);
+ if ((res == 1) && (val < 0))
+ res = -1;
+ if (res != 1) {
+ error("Invalid value '%s', should be a number > 0.\n", realargs[0]);
+ }
+ }
+ invertcor = (val > 0);
+ return 0;
+}
+
+int ext_tone(char *keyword, char *args)
+{
+ static char *realargs[10];
+ int argc;
+ int res;
+ int val;
+ argc = res = parseargs(args, realargs, 1, ',');
+ if (res != 1) {
+ error("Incorrect number of arguments to 'exttone' (should be <value>)\n");
+ }
+ if ((*realargs[0] == 'y') || (*realargs[0] == 'Y')) val = 1;
+ else if ((*realargs[0] == 'n') || (*realargs[0] == 'N')) val = 0;
+ else if ((*realargs[0] == 'i') || (*realargs[0] == 'I')) val = 2;
+ else
+ {
+ res = sscanf(realargs[0], "%d", &val);
+ if ((res == 1) && (val < 0))
+ res = -1;
+ if (val > 2) res = -1;
+ if (res != 1) {
+ error("Invalid value '%s', should be a number > 0.\n", realargs[0]);
+ }
+ }
+ exttone = val;
+ return 0;
+}
+
+int cor_thresh(char *keyword, char *args)
+{
+ static char *realargs[10];
+ int argc;
+ int res;
+ int val;
+ int x = 0;
+ argc = res = parseargs(args, realargs, 1, ',');
+ if (res != 1) {
+ error("Incorrect number of arguments to 'corthresh' (should be <value>)\n");
+ }
+ res = sscanf(realargs[0], "%d", &val);
+ if ((res == 1) && (val < 1))
+ res = -1;
+ for(x = 0; corthreshes[x]; x++)
+ {
+ if (corthreshes[x] == val) break;
+ }
+ if (!corthreshes[x]) res = -1;
+ if (res != 1) {
+ error("Invalid value '%s', should be a number > 0.\n", realargs[0]);
+ }
+ corthresh = x;
+ return 0;
+}
+
+int rad_apply_channels(int chans[], char *argstr)
+{
+ char *args[ZT_MAX_CHANNELS+1];
+ char *range[3];
+ int res,x, res2,y;
+ int chan;
+ int start, finish;
+ char argcopy[256];
+ res = parseargs(argstr, args, ZT_MAX_CHANNELS, ',');
+ if (res < 0)
+ error("Too many arguments... Max is %d\n", ZT_MAX_CHANNELS);
+ for (x=0;x<res;x++) {
+ if (strchr(args[x], '-')) {
+ /* It's a range */
+ strncpy(argcopy, args[x], sizeof(argcopy));
+ res2 = parseargs(argcopy, range, 2, '-');
+ if (res2 != 2) {
+ error("Syntax error in range '%s'. Should be <val1>-<val2>.\n", args[x]);
+ return -1;
+ }
+ res2 =sscanf(range[0], "%i", &start);
+ if (res2 != 1) {
+ error("Syntax error. Start of range '%s' should be a number from 1 to %d\n", args[x], ZT_MAX_CHANNELS - 1);
+ return -1;
+ } else if ((start < 1) || (start >= ZT_MAX_CHANNELS)) {
+ error("Start of range '%s' must be between 1 and %d (not '%d')\n", args[x], ZT_MAX_CHANNELS - 1, start);
+ return -1;
+ }
+ res2 =sscanf(range[1], "%i", &finish);
+ if (res2 != 1) {
+ error("Syntax error. End of range '%s' should be a number from 1 to %d\n", args[x], ZT_MAX_CHANNELS - 1);
+ return -1;
+ } else if ((finish < 1) || (finish >= ZT_MAX_CHANNELS)) {
+ error("end of range '%s' must be between 1 and %d (not '%d')\n", args[x], ZT_MAX_CHANNELS - 1, finish);
+ return -1;
+ }
+ if (start > finish) {
+ error("Range '%s' should start before it ends\n", args[x]);
+ return -1;
+ }
+ for (y=start;y<=finish;y++)
+ chans[y]=1;
+ } else {
+ /* It's a single channel */
+ res2 =sscanf(args[x], "%i", &chan);
+ if (res2 != 1) {
+ error("Syntax error. Channel should be a number from 1 to %d, not '%s'\n", ZT_MAX_CHANNELS - 1, args[x]);
+ return -1;
+ } else if ((chan < 1) || (chan >= ZT_MAX_CHANNELS)) {
+ error("Channel must be between 1 and %d (not '%d')\n", ZT_MAX_CHANNELS - 1, chan);
+ return -1;
+ }
+ chans[chan]=1;
+ }
+ }
+ return res;
+}
+
+static int rad_chanconfig(char *keyword, char *args)
+{
+ int chans[ZT_MAX_CHANNELS];
+ int res = 0;
+ int x,i,n;
+ struct zt_radio_param p;
+
+ bzero(chans, sizeof(chans));
+ res = rad_apply_channels(chans, args);
+ if (res <= 0)
+ return -1;
+ for (x=1;x<ZT_MAX_CHANNELS;x++) {
+ if (chans[x]) {
+
+ p.radpar = ZT_RADPAR_NUMTONES;
+ if (ind_ioctl(x,fd,ZT_RADIO_GETPARAM,&p) == -1)
+ error("Cannot get number of tones chanel %d\n",x);
+ n = p.data;
+ if (!rxtones[0]) for(i = 1; i <= n; i++)
+ {
+ if (rxtones[i])
+ {
+ p.radpar = ZT_RADPAR_RXTONE;
+ p.index = i;
+ p.data = rxtones[i];
+ if (ind_ioctl(x,fd,ZT_RADIO_SETPARAM,&p) == -1)
+ error("Cannot set rxtone on channel %d\n",x);
+ }
+ if (rxtags[i])
+ {
+ p.radpar = ZT_RADPAR_RXTONECLASS;
+ p.index = i;
+ p.data = rxtags[i];
+ if (ind_ioctl(x,fd,ZT_RADIO_SETPARAM,&p) == -1)
+ error("Cannot set rxtag on channel %d\n",x);
+ }
+ if (txtones[i])
+ {
+ p.radpar = ZT_RADPAR_RXTONE;
+ p.index = i;
+ p.data = txtones[i];
+ if (ind_ioctl(x,fd,ZT_RADIO_SETPARAM,&p) == -1)
+ error("Cannot set txtone on channel %d\n",x);
+ }
+ } else { /* if we have DCS receive */
+ p.radpar = ZT_RADPAR_RXTONE;
+ p.index = 0;
+ p.data = rxtones[0];
+ if (ind_ioctl(x,fd,ZT_RADIO_SETPARAM,&p) == -1)
+ error("Cannot set DCS rxtone on channel %d\n",x);
+ }
+ if (txtones[0])
+ {
+ p.radpar = ZT_RADPAR_TXTONE;
+ p.index = 0;
+ p.data = txtones[0];
+ if (ind_ioctl(x,fd,ZT_RADIO_SETPARAM,&p) == -1)
+ error("Cannot set default txtone on channel %d\n",x);
+ }
+ if (debouncetime)
+ {
+ p.radpar = ZT_RADPAR_DEBOUNCETIME;
+ p.data = debouncetime;
+ if (ind_ioctl(x,fd,ZT_RADIO_SETPARAM,&p) == -1)
+ error("Cannot set debouncetime on channel %d\n",x);
+ }
+ if (bursttime)
+ {
+ p.radpar = ZT_RADPAR_BURSTTIME;
+ p.data = bursttime;
+ if (ind_ioctl(x,fd,ZT_RADIO_SETPARAM,&p) == -1)
+ error("Cannot set bursttime on channel %d\n",x);
+ }
+ if (invertcor)
+ {
+ p.radpar = ZT_RADPAR_INVERTCOR;
+ p.data = invertcor;
+ if (ind_ioctl(x,fd,ZT_RADIO_SETPARAM,&p) == -1)
+ error("Cannot set invertcor on channel %d\n",x);
+ }
+ if (exttone)
+ {
+ p.radpar = ZT_RADPAR_EXTRXTONE;
+ p.data = exttone;
+ if (ind_ioctl(x,fd,ZT_RADIO_SETPARAM,&p) == -1)
+ error("Cannot set exttone on channel %d\n",x);
+ }
+ p.radpar = ZT_RADPAR_CORTHRESH;
+ p.data = corthresh;
+ if (ind_ioctl(x,fd,ZT_RADIO_SETPARAM,&p) == -1)
+ error("Cannot set corthresh on channel %d\n",x);
+ }
+ }
+ clear_fields();
+ return 0;
+}
+
+/* End Radio functions */
+
static void printconfig()
{
int x,y;
@@ -635,6 +1044,17 @@ static struct handler {
{ "alaw", setlaw },
{ "mulaw", setlaw },
{ "deflaw", setlaw },
+ { "ctcss", ctcss },
+ { "dcsrx", dcsrx },
+ { "rxdcs", dcsrx },
+ { "tx", tx },
+ { "debouncetime", debounce_time },
+ { "bursttime", burst_time },
+ { "exttone", ext_tone },
+ { "invertcor", invert_cor },
+ { "corthresh", cor_thresh },
+ { "channel", rad_chanconfig },
+ { "channels", rad_chanconfig },
};
static char *readline()
@@ -680,7 +1100,6 @@ int main(int argc, char *argv[])
char *buf;
char *key, *value;
int x,found;
- int fd;
while((c = getopt(argc, argv, "thc:vs")) != -1) {
switch(c) {
case 'c':
@@ -703,6 +1122,9 @@ int main(int argc, char *argv[])
break;
}
}
+ if (fd == -1) fd = open(MASTER_DEVICE, O_RDWR);
+ if (fd < 0)
+ error("Unable to open master device '%s'\n", MASTER_DEVICE);
cf = fopen(filename, "r");
if (cf) {
while((buf = readline())) {
@@ -748,7 +1170,7 @@ int main(int argc, char *argv[])
printf("About to open Master device\n");
fflush(stdout);
}
- fd = open(MASTER_DEVICE, O_RDWR);
+ if (fd == -1) fd = open(MASTER_DEVICE, O_RDWR);
if (fd < 0)
error("Unable to open master device '%s'\n", MASTER_DEVICE);
else {
@@ -821,7 +1243,6 @@ int main(int argc, char *argv[])
}
}
}
- close(fd);
}
}
} else {