From 70c27a0518c63a604b3e4ab78ebc717b009d1b52 Mon Sep 17 00:00:00 2001 From: markster Date: Tue, 19 Nov 2002 17:53:11 +0000 Subject: Version 0.3.3 from FTP git-svn-id: http://svn.digium.com/svn/zaptel/trunk@132 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- zaptel.c | 314 ++++++++++++++++++++++++++++++++++++--------------------------- 1 file 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;xspan && (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;xdialing) 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;xspan->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 "); 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 { -- cgit v1.2.3