summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2003-10-30 23:17:02 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2003-10-30 23:17:02 +0000
commit5de5efa71b183106b059157e4024d1e7bb434857 (patch)
treef7206ab483b5077b0f9faca16c017e0cd2eab18c
parent3e29b66d03ecccd8ce6c4f95d75a47afc603aa23 (diff)
Add DACS functionality to zaptel for cross connecting channels
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@262 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rwxr-xr-xpatlooptest.c4
-rwxr-xr-xwct4xxp.c2
-rwxr-xr-xzaptel.c39
-rwxr-xr-xzaptel.conf.sample3
-rwxr-xr-xzaptel.h4
-rwxr-xr-xztcfg.c52
6 files changed, 88 insertions, 16 deletions
diff --git a/patlooptest.c b/patlooptest.c
index 405ccf8..2f3f2c7 100755
--- a/patlooptest.c
+++ b/patlooptest.c
@@ -80,7 +80,9 @@ int main(int argc, char *argv[])
res = write(fd,outbuf,bs);
if (res != bs)
{
- printf("Res is %d\n", res);
+ printf("Res is %d: %s\n", res, strerror(errno));
+ ioctl(fd, ZT_GETEVENT, &x);
+ printf("Event: %d\n", x);
exit(1);
}
diff --git a/wct4xxp.c b/wct4xxp.c
index 8e1436e..dee5fa2 100755
--- a/wct4xxp.c
+++ b/wct4xxp.c
@@ -1285,8 +1285,10 @@ static void t4_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned int status;
unsigned int status2;
+#if 0
if (wc->intcount < 20)
printk("Pre-interrupt\n");
+#endif
inirq = 1;
/* Make sure it's really for us */
diff --git a/zaptel.c b/zaptel.c
index 2e8589d..394ed23 100755
--- a/zaptel.c
+++ b/zaptel.c
@@ -398,6 +398,8 @@ static char *sigstr(int sig)
return "Slave";
case ZT_SIG_CAS:
return "CAS";
+ case ZT_SIG_DACS:
+ return "DACS";
case ZT_SIG_SF:
return "SF (ToneOnly)";
case ZT_SIG_NONE:
@@ -882,8 +884,10 @@ static void close_channel(struct zt_chan *chan)
oldconf = chan->confna;
/* initialize conference variables */
chan->_confn = 0;
- chan->confna = 0;
- chan->confmode = 0;
+ if ((chan->sig & ZT_SIG_DACS) != ZT_SIG_DACS) {
+ chan->confna = 0;
+ chan->confmode = 0;
+ }
chan->confmute = 0;
/* release conference resource, if any to release */
if (oldconf) zt_check_conf(oldconf);
@@ -1848,9 +1852,11 @@ static int initialize_channel(struct zt_chan *chan)
chan->iomask = 0;
/* release conference resource if any */
if (chan->confna) zt_check_conf(chan->confna);
- chan->confna = 0;
+ if ((chan->sig & ZT_SIG_DACS) != ZT_SIG_DACS) {
+ chan->confna = 0;
+ chan->confmode = 0;
+ }
chan->_confn = 0;
- chan->confmode = 0;
memset(chan->conflast, 0, sizeof(chan->conflast));
memset(chan->conflast1, 0, sizeof(chan->conflast1));
memset(chan->conflast2, 0, sizeof(chan->conflast2));
@@ -1957,6 +1963,8 @@ static int zt_specchan_open(struct inode *inode, struct file *file, int unit, in
res = -EBUSY;
else if (chans[unit]->master != chans[unit])
res = -EBUSY;
+ else if (chans[unit]->sig == ZT_SIG_DACS)
+ res = -EBUSY;
else {
/* Assume everything is going to be okay */
res = initialize_channel(chans[unit]);
@@ -2744,6 +2752,12 @@ static int zt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return -EINVAL;
ch.sigtype = chans[ch.master]->sig;
newmaster = chans[ch.master];
+ } else if (ch.sigtype == ZT_SIG_DACS) {
+ newmaster = chans[ch.chan];
+ if ((ch.idlebits < 1) || (ch.idlebits >= ZT_MAX_CHANNELS))
+ return -EINVAL;
+ if (!chans[ch.idlebits])
+ return -EINVAL;
} else {
newmaster = chans[ch.chan];
}
@@ -2771,7 +2785,7 @@ static int zt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd
/* If they support clear channel, then they support the HDLC and such through
us. */
if (sigcap & ZT_SIG_CLEAR)
- sigcap |= (ZT_SIG_HDLCRAW | ZT_SIG_HDLCFCS | ZT_SIG_HDLCNET);
+ sigcap |= (ZT_SIG_HDLCRAW | ZT_SIG_HDLCFCS | ZT_SIG_HDLCNET | ZT_SIG_DACS);
if ((sigcap & ch.sigtype) != ch.sigtype)
res = -EINVAL;
@@ -2812,6 +2826,11 @@ static int zt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd
/* Clear FCS flag */
chans[ch.chan]->flags &= ~ZT_FLAG_FCS;
}
+ if ((ch.sigtype & ZT_SIG_DACS) == ZT_SIG_DACS) {
+ /* Setup conference properly */
+ chans[ch.chan]->confmode = ZT_CONF_DIGITALMON;
+ chans[ch.chan]->confna = ch.idlebits;
+ }
chans[ch.chan]->master = newmaster;
/* Note new slave if we are not our own master */
if (newmaster != chans[ch.chan]) {
@@ -4262,6 +4281,12 @@ static inline void __zt_process_getaudio_chunk(struct zt_chan *ss, unsigned char
txb[x] = ZT_LIN2X(getlin[x], ms);
break;
case ZT_CONF_DIGITALMON:
+ { static int blah = 0;
+ if (blah++ < 64) {
+ printk("Got here channel %d, from %d\n",
+ ms->channo, ms->confna);
+ }
+ }
/* Real digital monitoring, but still echo cancel if desired */
if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) {
if (ms->ec) {
@@ -5386,7 +5411,7 @@ static void __zt_transmit_chunk(struct zt_chan *chan, unsigned char *buf)
buf = silly;
__zt_getbuf_chunk(chan, buf);
- if (chan->flags & ZT_FLAG_AUDIO) {
+ if ((chan->flags & ZT_FLAG_AUDIO) || (chan->confmode)) {
#ifdef CONFIG_ZAPTEL_MMX
zt_kernel_fpu_begin();
#endif
@@ -5463,7 +5488,7 @@ static void __zt_receive_chunk(struct zt_chan *chan, unsigned char *buf)
memset(waste, ZT_LIN2X(0, chan), sizeof(waste));
buf = waste;
}
- if (chan->flags & ZT_FLAG_AUDIO) {
+ if ((chan->flags & ZT_FLAG_AUDIO) || (chan->confmode)) {
#ifdef CONFIG_ZAPTEL_MMX
zt_kernel_fpu_begin();
#endif
diff --git a/zaptel.conf.sample b/zaptel.conf.sample
index f91ca3b..d2a7133 100755
--- a/zaptel.conf.sample
+++ b/zaptel.conf.sample
@@ -83,6 +83,8 @@
# "nethdlc" : The zaptel driver bundles the channels together into an
# hdlc network device, which in turn can be configured with
# sethdlc (available separately).
+# "dacs" : The zaptel driver cross connects the channels starting at
+# the channel number listed at the end, after a colon
#
# The channel list is a comma-separated list of channels or ranges, for
# example:
@@ -108,6 +110,7 @@
#clear=46
#clear=47
#fcshdlc=48
+#dacs=1-24:48
#
# Finally, you can preload some tone zones, to prevent them from getting
# overwritten by other users (if you allow non-root users to open /dev/tor*
diff --git a/zaptel.h b/zaptel.h
index 936d213..c153171 100755
--- a/zaptel.h
+++ b/zaptel.h
@@ -93,6 +93,7 @@
#define ZT_SIG_SLAVE (1 << 11) /* Slave to another channel */
#define ZT_SIG_SF (1 << 14) /* Single Freq. tone only, no sig bits */
#define ZT_SIG_CAS (1 << 15) /* Just get bits */
+#define ZT_SIG_DACS ((1 << 16) | ZT_SIG_CLEAR) /* Cross connect */
/* tone flag values */
#define ZT_REVERSE_RXTONE 1 /* reverse polarity rx tone logic */
@@ -224,7 +225,8 @@ char name[40]; /* Name of channel to use */
int sigtype; /* Signal type */
int deflaw; /* Default law (ZT_LAW_DEFAULT, ZT_LAW_MULAW, or ZT_LAW_ALAW */
int master; /* Master channel if sigtype is ZT_SLAVE */
-int idlebits; /* Idle bits (if this is a CAS channel) */
+int idlebits; /* Idle bits (if this is a CAS channel) or
+ channel to monitor (if this is DACS channel) */
} ZT_CHANCONFIG;
typedef struct zt_sfconfig
diff --git a/ztcfg.c b/ztcfg.c
index 583c4ce..3b100e7 100755
--- a/ztcfg.c
+++ b/ztcfg.c
@@ -355,17 +355,32 @@ int parse_idle(int *i, char *s)
return -1;
}
+static int parse_channel(char *channel, int *startchan)
+{
+ if (!channel || (sscanf(channel, "%i", startchan) != 1) ||
+ (*startchan < 1)) {
+ error("DACS requires a starting channel in the form ':x' where x is the channel\n");
+ return -1;
+ }
+ return 0;
+}
+
static int chanconfig(char *keyword, char *args)
{
int chans[ZT_MAX_CHANNELS];
- int res;
+ int res = 0;
int x;
int master=0;
+ int dacschan = 0;
char *idle;
bzero(chans, sizeof(chans));
strtok(args, ":");
idle = strtok(NULL, ":");
- res = apply_channels(chans, args);
+ if (!strcasecmp(keyword, "dacs")) {
+ res = parse_channel(idle, &dacschan);
+ }
+ if (!res)
+ res = apply_channels(chans, args);
if (res <= 0)
return -1;
for (x=1;x<ZT_MAX_CHANNELS;x++)
@@ -374,6 +389,14 @@ static int chanconfig(char *keyword, char *args)
error("Channel %d already configured as '%s' at line %d\n", x, sig[x], slineno[x]);
continue;
}
+ if (!strcasecmp(keyword, "dacs") && slineno[dacschan]) {
+ error("DACS Destination channel %d already configured as '%s' at line %d\n", dacschan, sig[dacschan], slineno[dacschan]);
+ continue;
+ } else {
+ cc[dacschan].chan = dacschan;
+ cc[dacschan].master = dacschan;
+ slineno[dacschan] = lineno;
+ }
cc[x].chan = x;
cc[x].master = x;
slineno[x] = lineno;
@@ -403,6 +426,16 @@ static int chanconfig(char *keyword, char *args)
return -1;
sig[x] = "CAS / User";
cc[x].sigtype = ZT_SIG_CAS;
+ } else if (!strcasecmp(keyword, "dacs")) {
+ /* Setup channel for monitor */
+ cc[x].idlebits = dacschan;
+ cc[x].sigtype = ZT_SIG_DACS;
+ sig[x] = "DACS";
+ /* Setup inverse */
+ cc[dacschan].idlebits = x;
+ cc[dacschan].sigtype = ZT_SIG_DACS;
+ sig[dacschan] = "DACS";
+ dacschan++;
} else if (!strcasecmp(keyword, "unused")) {
sig[x] = "Unused";
cc[x].sigtype = 0;
@@ -534,12 +567,16 @@ static void printconfig()
for (x=1;x<ZT_MAX_CHANNELS;x++) {
if ((cc[x].sigtype != ZT_SIG_SLAVE) && (cc[x].sigtype)) {
configs++;
- printf("Channel %02d: %s (%s)", x, sig[x], laws[cc[x].deflaw]);
ps = 0;
- for (y=1;y<ZT_MAX_CHANNELS;y++)
- if (cc[y].master == x) {
- printf("%s%02d", ps++ ? " " : " (Slaves: ", y);
- }
+ if (cc[x].sigtype == ZT_SIG_DACS)
+ printf("Channel %02d %s to %02d", x, sig[x], cc[x].idlebits);
+ else {
+ printf("Channel %02d: %s (%s)", x, sig[x], laws[cc[x].deflaw]);
+ for (y=1;y<ZT_MAX_CHANNELS;y++)
+ if (cc[y].master == x) {
+ printf("%s%02d", ps++ ? " " : " (Slaves: ", y);
+ }
+ }
if (ps) printf(")\n"); else printf("\n");
} else
if (cc[x].sigtype) configs++;
@@ -575,6 +612,7 @@ static struct handler {
{ "clear", chanconfig },
{ "unused", chanconfig },
{ "cas", chanconfig },
+ { "dacs", chanconfig },
{ "user", chanconfig },
{ "alaw", setlaw },
{ "mulaw", setlaw },