summaryrefslogtreecommitdiff
path: root/zaptel.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-11-19 17:53:11 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-11-19 17:53:11 +0000
commit70c27a0518c63a604b3e4ab78ebc717b009d1b52 (patch)
tree7fa4eb21d3cf380e980a5a3777dbd252cbc6aaa9 /zaptel.c
parent80dc858648497bb683ccee5157e9f62dbdf99ddb (diff)
Version 0.3.3 from FTP
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@132 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'zaptel.c')
-rwxr-xr-xzaptel.c314
1 files changed, 182 insertions, 132 deletions
diff --git a/zaptel.c b/zaptel.c
index 273cf46..4bd7c45 100755
--- a/zaptel.c
+++ b/zaptel.c
@@ -110,7 +110,7 @@ EXPORT_SYMBOL(zt_set_dynamic_ioctl);
EXPORT_SYMBOL(zt_ec_chunk);
#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *zaptel_proc_entry;
+static struct proc_dir_entry *proc_entries[ZT_MAX_SPANS];
#endif
/* Here are a couple important little additions for devfs */
@@ -346,6 +346,131 @@ static unsigned int in_sig[NUM_SIGS][2] = {
} return(-1); /* not found -- error */
}
+#ifdef CONFIG_PROC_FS
+static char *sigstr(int sig)
+{
+ switch (sig) {
+ case ZT_SIG_FXSLS:
+ return "FXSLS";
+ case ZT_SIG_FXSKS:
+ return "FXSKS";
+ case ZT_SIG_FXSGS:
+ return "FXSGS";
+ case ZT_SIG_FXOLS:
+ return "FXOLS";
+ case ZT_SIG_FXOKS:
+ return "FXOKS";
+ case ZT_SIG_FXOGS:
+ return "FXOGS";
+ case ZT_SIG_EM:
+ return "E&M";
+ case ZT_SIG_CLEAR:
+ return "ClearChannel";
+ case ZT_SIG_HDLCRAW:
+ return "HDLCRAW";
+ case ZT_SIG_HDLCFCS:
+ return "HDLCFCS";
+ case ZT_SIG_HDLCNET:
+ return "HDLCNET";
+ case ZT_SIG_SLAVE:
+ return "Slave";
+ case ZT_SIG_CAS:
+ return "CAS";
+ case ZT_SIG_NONE:
+ default:
+ return "Unconfigured";
+ }
+
+}
+
+static int zaptel_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int x, span, len = 0;
+
+ if (off > 0)
+ return 0;
+
+ (int *)span = data;
+
+ if (!span)
+ return 0;
+
+ if (spans[span]->name)
+ len += sprintf(page + len, "Span %d: %s ", span, spans[span]->name);
+ if (spans[span]->desc)
+ len += sprintf(page + len, "\"%s\"", spans[span]->desc);
+ else
+ len += sprintf(page + len, "\"\"");
+
+ if (spans[span]->lineconfig) {
+ /* framing first */
+ if (spans[span]->lineconfig & ZT_CONFIG_B8ZS)
+ len += sprintf(page + len, " B8ZS/");
+ else if (spans[span]->lineconfig & ZT_CONFIG_AMI)
+ len += sprintf(page + len, " AMI/");
+ else if (spans[span]->lineconfig & ZT_CONFIG_HDB3)
+ len += sprintf(page + len, " HDB3/");
+ /* then coding */
+ if (spans[span]->lineconfig & ZT_CONFIG_ESF)
+ len += sprintf(page + len, "ESF");
+ else if (spans[span]->lineconfig & ZT_CONFIG_D4)
+ len += sprintf(page + len, "D4");
+ else if (spans[span]->lineconfig & ZT_CONFIG_CCS)
+ len += sprintf(page + len, "CCS");
+ /* E1's can enable CRC checking */
+ if (spans[span]->lineconfig & ZT_CONFIG_CRC4)
+ len += sprintf(page + len, "/CRC4");
+ }
+
+ len += sprintf(page + len, " ");
+
+ /* list alarms */
+ if (spans[span]->alarms && (spans[span]->alarms > 0)) {
+ if (spans[span]->alarms & ZT_ALARM_BLUE)
+ len += sprintf(page + len, "BLUE ");
+ if (spans[span]->alarms & ZT_ALARM_YELLOW)
+ len += sprintf(page + len, "YELLOW ");
+ if (spans[span]->alarms & ZT_ALARM_RED)
+ len += sprintf(page + len, "RED ");
+ if (spans[span]->alarms & ZT_ALARM_LOOPBACK)
+ len += sprintf(page + len, "LOOP ");
+ if (spans[span]->alarms & ZT_ALARM_RECOVER)
+ len += sprintf(page + len, "RECOVERING ");
+ if (spans[span]->alarms & ZT_ALARM_NOTOPEN)
+ len += sprintf(page + len, "NOTOPEN ");
+
+ }
+ if (spans[span]->syncsrc && (spans[span]->syncsrc == spans[span]->spanno))
+ len += sprintf(page + len, "ClockSource ");
+ len += sprintf(page + len, "\n");
+
+
+ for (x=1;x<ZT_MAX_CHANNELS;x++) {
+ if (chans[x]) {
+ if (chans[x]->span && (chans[x]->span->spanno == span)) {
+
+ if (chans[x]->name)
+ len += sprintf(page + len, "\t%d %s ", x, chans[x]->name );
+
+ if (chans[x]->sig) {
+ if (chans[x]->sig == ZT_SIG_SLAVE)
+ len += sprintf(page + len, "%s", sigstr(chans[x]->master->sig));
+ else {
+ len += sprintf(page + len, "%s", sigstr(chans[x]->sig));
+ if (chans[x]->nextslave && chans[x]->master->channo == x)
+ len += sprintf(page + len, "Master ");
+ }
+ }
+ len += sprintf(page + len, "\n");
+
+ }
+
+ }
+ }
+ return len;
+}
+#endif
+
static int zt_first_empty_alias(void)
{
/* Find the first conference which has no alias pointing to it */
@@ -696,6 +821,7 @@ static void close_channel(struct zt_chan *chan)
chan->cadencepos = 0;
zt_hangup(chan);
chan->itimer = 0;
+ chan->ringdebtimer = 0;
init_waitqueue_head(&chan->sel);
init_waitqueue_head(&chan->readbufq);
init_waitqueue_head(&chan->writebufq);
@@ -1513,6 +1639,11 @@ static int zt_hangup(struct zt_chan *chan)
return -EINVAL;
chan->kewlonhook = 0;
+
+
+ if ((chan->sig == ZT_SIG_FXSLS) || (chan->sig == ZT_SIG_FXSKS) ||
+ (chan->sig == ZT_SIG_FXSGS)) chan->ringdebtimer = RING_DEBOUNCE_TIME;
+
if (chan->span->flags & ZT_FLAG_RBS) {
if (chan->sig == ZT_SIG_CAS) {
zt_cas_setbits(chan, chan->idlebits);
@@ -1596,7 +1727,8 @@ static int initialize_channel(struct zt_chan *chan)
/* Initialize RBS timers */
chan->itimer = chan->otimer = 0;
-
+ chan->ringdebtimer = 0;
+
init_waitqueue_head(&chan->sel);
init_waitqueue_head(&chan->readbufq);
init_waitqueue_head(&chan->writebufq);
@@ -2283,8 +2415,8 @@ static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int c
mychan.confna, mychan._confn, mychan.confmode, mychan.confmute);
printk("ec: %08x, echocancel: %d, deflaw: %d, xlaw: %08x\n",
(int) mychan.ec, mychan.echocancel, mychan.deflaw, (int) mychan.xlaw);
- printk("itimer: %d, otimer: %d\n\n",
- mychan.itimer,mychan.otimer);
+ printk("itimer: %d, otimer: %d, ringdebtimer: %d\n\n",
+ mychan.itimer,mychan.otimer,mychan.ringdebtimer);
#if 0
if (mychan.ec) {
int x;
@@ -2810,6 +2942,21 @@ static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsign
/* clear IO MUX mask */
chan->iomask = 0;
break;
+ case ZT_GETEVENT: /* Get event on queue */
+ spin_lock_irqsave(&chan->lock, flags);
+ /* set up for no event */
+ put_user(ZT_EVENT_NONE,(int *)data);
+ /* if some event in queue */
+ if (chan->eventinidx != chan->eventoutidx)
+ {
+ /* get the data, bump index */
+ put_user(chan->eventbuf[chan->eventoutidx++],(int *)data);
+ /* if index overflow, set to beginning */
+ if (chan->eventoutidx >= ZT_MAX_EVENTSIZE)
+ chan->eventoutidx = 0;
+ }
+ spin_unlock_irqrestore(&chan->lock, flags);
+ break;
case ZT_CONFMUTE: /* set confmute flag */
if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL);
get_user(j,(int *)data); /* get conf # */
@@ -3146,21 +3293,6 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm
fasthdlc_init(&chan->txhdlc);
}
break;
- case ZT_GETEVENT: /* Get event on queue */
- spin_lock_irqsave(&chan->lock, flags);
- /* set up for no event */
- put_user(ZT_EVENT_NONE,(int *)data);
- /* if some event in queue */
- if (chan->eventinidx != chan->eventoutidx)
- {
- /* get the data, bump index */
- put_user(chan->eventbuf[chan->eventoutidx++],(int *)data);
- /* if index overflow, set to beginning */
- if (chan->eventoutidx >= ZT_MAX_EVENTSIZE)
- chan->eventoutidx = 0;
- }
- spin_unlock_irqrestore(&chan->lock, flags);
- break;
case ZT_ECHOCANCEL:
if (!(chan->flags & ZT_FLAG_AUDIO))
return -EINVAL;
@@ -3204,6 +3336,10 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm
zt_cas_setbits(chan, j);
rv = 0;
break;
+ case ZT_GETRXBITS:
+ put_user(chan->rxsig, (int *)data);
+ rv = 0;
+ break;
case ZT_HOOK:
if (chan->flags & ZT_FLAG_CLEAR)
return -EINVAL;
@@ -3371,6 +3507,9 @@ int zt_register(struct zt_span *span, int prefmaster)
{
int x;
+#ifdef CONFIG_PROC_FS
+ char tempfile[17];
+#endif
if (!span)
return -EINVAL;
if (span->flags & ZT_FLAG_REGISTERED) {
@@ -3405,6 +3544,11 @@ int zt_register(struct zt_span *span, int prefmaster)
zt_chan_reg(&span->chans[x]);
}
+#ifdef CONFIG_PROC_FS
+ sprintf(tempfile, "zaptel/%d", span->spanno);
+ proc_entries[span->spanno] = create_proc_read_entry(tempfile, 0444, NULL , zaptel_proc_read, (int *)span->spanno);
+#endif
+
#ifdef CONFIG_DEVFS_FS
{
char span_name[50];
@@ -3430,6 +3574,9 @@ int zt_register(struct zt_span *span, int prefmaster)
int zt_unregister(struct zt_span *span)
{
int x;
+#ifdef CONFIG_PROC_FS
+ char tempfile[17];
+#endif /* CONFIG_PROC_FS */
if (!(span->flags & ZT_FLAG_REGISTERED)) {
printk(KERN_ERR "Span %s does not appear to be registered\n", span->name);
@@ -3446,6 +3593,10 @@ int zt_unregister(struct zt_span *span)
}
if (debug)
printk("Unregistering Span '%s' with %d channels\n", span->name, span->channels);
+#ifdef CONFIG_PROC_FS
+ sprintf(tempfile, "zaptel/%d", span->spanno);
+ remove_proc_entry(tempfile, NULL);
+#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_DEVFS_FS
for (x = 0; x < span->channels; x++) {
devfs_unregister(span->chans[x].fhandle);
@@ -3650,7 +3801,7 @@ static inline void zt_process_getaudio_chunk(struct zt_chan *ss, unsigned char *
}
}
}
- if (!ms->confmute && !ms->dialing) {
+ if ((!ms->confmute && !ms->dialing) || (ms->flags & ZT_FLAG_PSEUDO)) {
/* Handle conferencing on non-clear channel and non-HDLC channels */
switch(ms->confmode & ZT_CONF_MODE_MASK) {
case ZT_CONF_NORMAL:
@@ -4067,13 +4218,13 @@ static void zt_hooksig_pvt(struct zt_chan *chan, zt_rxsig_t rxsig)
case ZT_SIG_FXSLS: /* FXS loopstart */
if ((oldrxsig == ZT_RXSIG_RING) &&
(rxsig == ZT_RXSIG_OFFHOOK)) {
- qevent(chan,ZT_EVENT_RINGOFFHOOK);
+ if (!chan->ringdebtimer) qevent(chan,ZT_EVENT_RINGOFFHOOK);
}
break;
case ZT_SIG_FXSKS: /* FXS Kewlstart */
if ((oldrxsig == ZT_RXSIG_RING) &&
(rxsig == ZT_RXSIG_OFFHOOK)) {
- qevent(chan,ZT_EVENT_RINGOFFHOOK);
+ if (!chan->ringdebtimer) qevent(chan,ZT_EVENT_RINGOFFHOOK);
break;
}
/* ignore a bit poopy if loop not closed and stable */
@@ -4082,10 +4233,11 @@ static void zt_hooksig_pvt(struct zt_chan *chan, zt_rxsig_t rxsig)
case ZT_SIG_FXSGS: /* FXS Groundstart */
if ((oldrxsig == ZT_RXSIG_RING) &&
(rxsig == ZT_RXSIG_OFFHOOK)) {
- qevent(chan,ZT_EVENT_RINGOFFHOOK);
+ if (!chan->ringdebtimer) qevent(chan,ZT_EVENT_RINGOFFHOOK);
break;
}
if (rxsig == ZT_RXSIG_ONHOOK) {
+ chan->ringdebtimer = RING_DEBOUNCE_TIME;
if (chan->txstate != ZT_TXSTATE_DEBOUNCE) {
chan->gotgs = 0;
qevent(chan,ZT_EVENT_ONHOOK);
@@ -4208,7 +4360,7 @@ void zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char
/* Perform echo cancellation on a chunk if necessary */
if (ss->ec) {
#ifdef CONFIG_ZAPTEL_MMX
- kernel_fpu_begin();
+ zt_kernel_fpu_begin();
#endif
for (x=0;x<ZT_CHUNKSIZE;x++) {
rxlin = ZT_XLAW(rxchunk[x], ss);
@@ -4232,7 +4384,7 @@ static inline void zt_process_putaudio_chunk(struct zt_chan *ss, unsigned char *
if (ms->dialing) ms->afterdialingtimer = 50;
else if (ms->afterdialingtimer) ms->afterdialingtimer--;
- if (ms->afterdialingtimer) {
+ if (ms->afterdialingtimer && (!(ms->flags & ZT_FLAG_PSEUDO))) {
/* Be careful since memset is likely a macro */
rxb[0] = ZT_LIN2X(0, ms);
memset(&rxb[1], rxb[0], ZT_CHUNKSIZE - 1); /* receive as silence if dialing */
@@ -4260,7 +4412,8 @@ static inline void zt_process_putaudio_chunk(struct zt_chan *ss, unsigned char *
/* Take the rxc, twiddle it for conferencing if appropriate and put it
back */
- if (!ms->confmute && !ms->afterdialingtimer) {
+ if ((!ms->confmute && !ms->afterdialingtimer) ||
+ (ms->flags & ZT_FLAG_PSEUDO)) {
switch(ms->confmode & ZT_CONF_MODE_MASK) {
case ZT_CONF_NORMAL: /* Normal mode */
/* Do nothing. rx goes output */
@@ -4858,6 +5011,8 @@ int zt_receive(struct zt_span *span)
rbs_itimer_expire(&span->chans[x]);
}
}
+ if (span->chans[x].ringdebtimer)
+ span->chans[x].ringdebtimer--;
spin_unlock_irqrestore(&span->chans[x].lock, flags);
}
}
@@ -4928,111 +5083,6 @@ int zt_receive(struct zt_span *span)
return 0;
}
-#ifdef CONFIG_PROC_FS
-static char *sigstr(int sig)
-{
- switch (sig) {
- case ZT_SIG_FXSLS:
- return "FXSLS";
- case ZT_SIG_FXSKS:
- return "FXSKS";
- case ZT_SIG_FXSGS:
- return "FXSGS";
- case ZT_SIG_FXOLS:
- return "FXOLS";
- case ZT_SIG_FXOKS:
- return "FXOKS";
- case ZT_SIG_FXOGS:
- return "FXOGS";
- case ZT_SIG_EM:
- return "E&M";
- case ZT_SIG_CLEAR:
- return "ClearChannel";
- case ZT_SIG_HDLCRAW:
- return "HDLCRAW";
- case ZT_SIG_HDLCFCS:
- return "HDLCFCS";
- case ZT_SIG_HDLCNET:
- return "HDLCNET";
- case ZT_SIG_SLAVE:
- return "Slave";
- case ZT_SIG_CAS:
- return "CAS";
- case ZT_SIG_NONE:
- default:
- return "Unconfigured";
- }
-
-}
-
-static int zaptel_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- int x, oldspan = 0, len = 0;
-
- for (x=1;x<ZT_MAX_CHANNELS;x++) {
- if (chans[x]) {
- if (chans[x]->span->spanno != oldspan) {
- len += sprintf(page + len, "Span %d: %s \"%s\"", x, spans[x]->name, spans[x]->desc);
- /* framing first */
- if (chans[x]->span->lineconfig & ZT_CONFIG_B8ZS)
- len += sprintf(page + len, " B8ZS/");
- else if (chans[x]->span->lineconfig & ZT_CONFIG_AMI)
- len += sprintf(page + len, " AMI/");
- else if (chans[x]->span->lineconfig & ZT_CONFIG_HDB3)
- len += sprintf(page + len, " HDB3/");
- /* then coding */
- if (chans[x]->span->lineconfig & ZT_CONFIG_ESF)
- len += sprintf(page + len, "ESF");
- else if (chans[x]->span->lineconfig & ZT_CONFIG_D4)
- len += sprintf(page + len, "D4");
- else if (chans[x]->span->lineconfig & ZT_CONFIG_CCS)
- len += sprintf(page + len, "CCS");
- /* E1's can enable CRC checking */
- if (chans[x]->span->lineconfig & ZT_CONFIG_CRC4)
- len += sprintf(page + len, "/CRC4");
-
- len += sprintf(page + len, " ");
-
- /* list alarms */
- if (chans[x]->span->alarms > 0) {
- if (chans[x]->span->alarms & ZT_ALARM_BLUE)
- len += sprintf(page + len, "BLUE ");
- if (chans[x]->span->alarms & ZT_ALARM_YELLOW)
- len += sprintf(page + len, "YELLOW ");
- if (chans[x]->span->alarms & ZT_ALARM_RED)
- len += sprintf(page + len, "RED ");
- if (chans[x]->span->alarms & ZT_ALARM_LOOPBACK)
- len += sprintf(page + len, "LOOP ");
- if (chans[x]->span->alarms & ZT_ALARM_RECOVER)
- len += sprintf(page + len, "RECOVERING ");
- if (chans[x]->span->alarms & ZT_ALARM_NOTOPEN)
- len += sprintf(page + len, "NOTOPEN ");
-
- }
-
- if (chans[x]->span->syncsrc == chans[x]->span->spanno)
- len += sprintf(page + len, "ClockSource ");
- len += sprintf(page + len, "\n");
- oldspan = chans[x]->span->spanno;
- }
-
- len += sprintf(page + len, "\t%d %s ", x, chans[x]->name );
- if (chans[x]->sig == ZT_SIG_SLAVE)
- len += sprintf(page + len, "%s", sigstr(chans[x]->master->sig));
- else {
- len += sprintf(page + len, "%s", sigstr(chans[x]->sig));
- if (chans[x]->nextslave && chans[x]->master->channo == x)
- len += sprintf(page + len, "Master ");
- }
- len += sprintf(page + len, "\n");
-
- }
- }
-
- return len;
-}
-#endif
-
MODULE_AUTHOR("Mark Spencer <markster@linux-support.net>");
MODULE_DESCRIPTION("Zapata Telephony Interface");
#ifdef MODULE_LICENSE
@@ -5060,7 +5110,7 @@ static int __init zt_init(void) {
int res = 0;
#ifdef CONFIG_PROC_FS
- zaptel_proc_entry = create_proc_read_entry("zaptel", 0444, NULL , zaptel_proc_read, NULL);
+ proc_entries[0] = proc_mkdir("zaptel", NULL);
#endif
#ifdef CONFIG_DEVFS_FS
{