diff options
-rwxr-xr-x | patlooptest.c | 4 | ||||
-rwxr-xr-x | wct4xxp.c | 2 | ||||
-rwxr-xr-x | zaptel.c | 39 | ||||
-rwxr-xr-x | zaptel.conf.sample | 3 | ||||
-rwxr-xr-x | zaptel.h | 4 | ||||
-rwxr-xr-x | ztcfg.c | 52 |
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); } @@ -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 */ @@ -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* @@ -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 @@ -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 }, |