📄 zaptel.c
字号:
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"); if (spans[span]->bpvcount) len += sprintf(page + len, "\tBPV count: %d\n", spans[span]->bpvcount); if (spans[span]->crc4count) len += sprintf(page + len, "\tCRC4 error count: %d\n", spans[span]->crc4count); if (spans[span]->ebitcount) len += sprintf(page + len, "\tE-bit error count: %d\n", spans[span]->ebitcount); if (spans[span]->fascount) len += sprintf(page + len, "\tFAS error count: %d\n", spans[span]->fascount); if (spans[span]->irqmisses) len += sprintf(page + len, "\tIRQ misses: %d\n", spans[span]->irqmisses); 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%4d %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 "); } } if ((chans[x]->flags & ZT_FLAG_OPEN)) { len += sprintf(page + len, "(In use) "); } len += sprintf(page + len, "\n"); } } } return len;}#endifstatic int zt_first_empty_alias(void){ /* Find the first conference which has no alias pointing to it */ int x; for (x=1;x<ZT_MAX_CONF;x++) { if (!confrev[x]) return x; } return -1;}static void recalc_maxconfs(void){ int x; for (x=ZT_MAX_CONF-1;x>0;x--) { if (confrev[x]) { maxconfs = x+1; return; } } maxconfs = 0;}static void recalc_maxlinks(void){ int x; for (x=ZT_MAX_CONF-1;x>0;x--) { if (conf_links[x].src || conf_links[x].dst) { maxlinks = x+1; return; } } maxlinks = 0;}static int zt_first_empty_conference(void){ /* Find the first conference which has no alias */ int x; for (x=ZT_MAX_CONF-1;x>0;x--) { if (!confalias[x]) return x; } return -1;}static int zt_get_conf_alias(int x){ int a; if (confalias[x]) { return confalias[x]; } /* Allocate an alias */ a = zt_first_empty_alias(); confalias[x] = a; confrev[a] = x; /* Highest conference may have changed */ recalc_maxconfs(); return a;}static void zt_check_conf(int x){ int y; /* return if no valid conf number */ if (x <= 0) return; /* Return if there is no alias */ if (!confalias[x]) return; for (y=0;y<maxchans;y++) { if (chans[y] && (chans[y]->confna == x) && (chans[y]->confmode & (ZT_CONF_CONF | ZT_CONF_CONFANN | ZT_CONF_CONFMON | ZT_CONF_CONFANNMON | ZT_CONF_REALANDPSEUDO))) return; } /* If we get here, nobody is in the conference anymore. Clear it out both forward and reverse */ confrev[confalias[x]] = 0; confalias[x] = 0; /* Highest conference may have changed */ recalc_maxconfs();}/* enqueue an event on a channel */static void __qevent(struct zt_chan *chan, int event){ /* if full, ignore */ if ((chan->eventoutidx == 0) && (chan->eventinidx == (ZT_MAX_EVENTSIZE - 1))) return; /* if full, ignore */ if (chan->eventinidx == (chan->eventoutidx - 1)) return; /* save the event */ chan->eventbuf[chan->eventinidx++] = event; /* wrap the index, if necessary */ if (chan->eventinidx >= ZT_MAX_EVENTSIZE) chan->eventinidx = 0; /* wake em all up */ if (chan->iomask & ZT_IOMUX_SIGEVENT) wake_up_interruptible(&chan->eventbufq); wake_up_interruptible(&chan->readbufq); wake_up_interruptible(&chan->writebufq); wake_up_interruptible(&chan->sel); return;}void zt_qevent_nolock(struct zt_chan *chan, int event){ __qevent(chan, event);}void zt_qevent_lock(struct zt_chan *chan, int event){ unsigned long flags; spin_lock_irqsave(&chan->lock, flags); __qevent(chan, event); spin_unlock_irqrestore(&chan->lock, flags);}/* sleep in user space until woken up. Equivilant of tsleep() in BSD */static int schluffen(wait_queue_head_t *q){ DECLARE_WAITQUEUE(wait, current); add_wait_queue(q, &wait); current->state = TASK_INTERRUPTIBLE; if (!signal_pending(current)) schedule(); current->state = TASK_RUNNING; remove_wait_queue(q, &wait); if (signal_pending(current)) return -ERESTARTSYS; return(0);}static inline void calc_fcs(struct zt_chan *ss){ int x; unsigned int fcs=PPP_INITFCS; unsigned char *data = ss->writebuf[ss->inwritebuf]; int len = ss->writen[ss->inwritebuf]; /* Not enough space to do FCS calculation */ if (len < 2) return; for (x=0;x<len-2;x++) fcs = PPP_FCS(fcs, data[x]); fcs ^= 0xffff; /* Send out the FCS */ data[len-2] = (fcs & 0xff); data[len-1] = (fcs >> 8) & 0xff;}static int zt_reallocbufs(struct zt_chan *ss, int j, int numbufs){ unsigned char *newbuf, *oldbuf; unsigned long flags; int x; /* Check numbufs */ if (numbufs < 2) numbufs = 2; if (numbufs > ZT_MAX_NUM_BUFS) numbufs = ZT_MAX_NUM_BUFS; /* We need to allocate our buffers now */ if (j) { newbuf = kmalloc(j * 2 * numbufs, GFP_KERNEL); if (!newbuf) return (-ENOMEM); } else newbuf = NULL; /* Now that we've allocated our new buffer, we can safely move things around... */ spin_lock_irqsave(&ss->lock, flags); ss->blocksize = j; /* set the blocksize */ oldbuf = ss->readbuf[0]; /* Keep track of the old buffer */ ss->readbuf[0] = NULL; if (newbuf) { for (x=0;x<numbufs;x++) { ss->readbuf[x] = newbuf + x * j; ss->writebuf[x] = newbuf + (numbufs + x) * j; } } else { for (x=0;x<numbufs;x++) { ss->readbuf[x] = NULL; ss->writebuf[x] = NULL; } } /* Mark all buffers as empty */ for (x=0;x<numbufs;x++) ss->writen[x] = ss->writeidx[x]= ss->readn[x]= ss->readidx[x] = 0; /* Keep track of where our data goes (if it goes anywhere at all) */ if (newbuf) { ss->inreadbuf = 0; ss->inwritebuf = 0; } else { ss->inreadbuf = -1; ss->inwritebuf = -1; } ss->outreadbuf = -1; ss->outwritebuf = -1; ss->numbufs = numbufs; if (ss->txbufpolicy == ZT_POLICY_WHEN_FULL) ss->txdisable = 1; else ss->txdisable = 0; if (ss->rxbufpolicy == ZT_POLICY_WHEN_FULL) ss->rxdisable = 1; else ss->rxdisable = 0; spin_unlock_irqrestore(&ss->lock, flags); if (oldbuf) kfree(oldbuf); return 0;}static int zt_hangup(struct zt_chan *chan);static void zt_set_law(struct zt_chan *chan, int law);/* Pull a ZT_CHUNKSIZE piece off the queue. Returns 0 on success or -1 on failure. If failed, provides silence */static int __buf_pull(struct confq *q, u_char *data, struct zt_chan *c, char *label){ int oldoutbuf = q->outbuf; /* Ain't nuffin to read */ if (q->outbuf < 0) { if (data) memset(data, ZT_LIN2X(0,c), ZT_CHUNKSIZE); return -1; } if (data) memcpy(data, q->buf[q->outbuf], ZT_CHUNKSIZE); q->outbuf = (q->outbuf + 1) % ZT_CB_SIZE; /* Won't be nuffin next time */ if (q->outbuf == q->inbuf) { q->outbuf = -1; } /* If they thought there was no space then there is now where we just read */ if (q->inbuf < 0) q->inbuf = oldoutbuf; return 0;}/* Returns a place to put stuff, or NULL if there is no room */static u_char *__buf_pushpeek(struct confq *q){ if (q->inbuf < 0) return NULL; return q->buf[q->inbuf];}static u_char *__buf_peek(struct confq *q){ if (q->outbuf < 0) return NULL; return q->buf[q->outbuf];}#ifdef BUF_MUNGEstatic u_char *__buf_cpush(struct confq *q){ int pos; /* If we have no space, return where the last space that we *did* have was */ if (q->inbuf > -1) return NULL; pos = q->outbuf - 1; if (pos < 0) pos += ZT_CB_SIZE; return q->buf[pos];}static void __buf_munge(struct zt_chan *chan, u_char *old, u_char *new){ /* Run a weighted average of the old and new, in order to mask a missing sample */ int x; int val; for (x=0;x<ZT_CHUNKSIZE;x++) { val = x * ZT_XLAW(new[x], chan) + (ZT_CHUNKSIZE - x - 1) * ZT_XLAW(old[x], chan); val = val / (ZT_CHUNKSIZE - 1); old[x] = ZT_LIN2X(val, chan); }}#endif/* Push something onto the queue, or assume what is there is valid if data is NULL */static int __buf_push(struct confq *q, u_char *data, char *label){ int oldinbuf = q->inbuf; if (q->inbuf < 0) { return -1; } if (data) /* Copy in the data */ memcpy(q->buf[q->inbuf], data, ZT_CHUNKSIZE); /* Advance the inbuf pointer */ q->inbuf = (q->inbuf + 1) % ZT_CB_SIZE; if (q->inbuf == q->outbuf) { /* No space anymore... */ q->inbuf = -1; } /* If they don't think data is ready, let them know it is now */ if (q->outbuf < 0) { q->outbuf = oldinbuf; } return 0;}static void reset_conf(struct zt_chan *chan){ int x; /* Empty out buffers and reset to initialization */ for (x=0;x<ZT_CB_SIZE;x++) chan->confin.buf[x] = chan->confin.buffer + ZT_CHUNKSIZE * x; chan->confin.inbuf = 0; chan->confin.outbuf = -1; for (x=0;x<ZT_CB_SIZE;x++) chan->confout.buf[x] = chan->confout.buffer + ZT_CHUNKSIZE * x; chan->confout.inbuf = 0; chan->confout.outbuf = -1;}static void close_channel(struct zt_chan *chan){ unsigned long flags; void *rxgain = NULL; echo_can_state_t *ec = NULL; int oldconf;#ifdef CONFIG_ZAPATA_PPP struct ppp_channel *ppp;#endif zt_reallocbufs(chan, 0, 0); spin_lock_irqsave(&chan->lock, flags);#ifdef CONFIG_ZAPATA_PPP ppp = chan->ppp; chan->ppp = NULL;#endif ec = chan->ec; chan->ec = NULL; chan->curtone = NULL; chan->curzone = NULL; chan->cadencepos = 0; chan->pdialcount = 0; zt_hangup(chan); chan->itimerset = chan->itimer = 0; chan->pulsecount = 0; chan->pulsetimer = 0; chan->ringdebtimer = 0; init_waitqueue_head(&chan->sel); init_waitqueue_head(&chan->readbufq); init_waitqueue_head(&chan->writebufq); init_waitqueue_head(&chan->eventbufq); init_waitqueue_head(&chan->txstateq); chan->txdialbuf[0] = '\0'; chan->digitmode = DIGIT_MODE_DTMF; chan->dialing = 0; chan->afterdialingtimer = 0; /* initialize IO MUX mask */ chan->iomask = 0; /* save old conf number, if any */ oldconf = chan->confna; /* initialize conference variables */ chan->_confn = 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); chan->gotgs = 0; reset_conf(chan); if (chan->gainalloc && chan->rxgain) rxgain = chan->rxgain; chan->rxgain = defgain; chan->txgain = defgain; chan->gainalloc = 0; chan->eventinidx = chan->eventoutidx = 0; chan->flags &= ~(ZT_FLAG_LINEAR | ZT_FLAG_PPP | ZT_FLAG_SIGFREEZE); zt_set_law(chan,0); memset(chan->conflast, 0, sizeof(chan->conflast)); memset(chan->conflast1, 0, sizeof(chan->conflast1)); memset(chan->conflast2, 0, sizeof(chan->conflast2)); spin_unlock_irqrestore(&chan->lock, flags); if (rxgain) kfree(rxgain); if (ec) echo_can_free(ec);#ifdef CONFIG_ZAPATA_PPP if (ppp) { tasklet_kill(&chan->ppp_calls); skb_queue_purge(&chan->ppp_rq); ppp_unregister_channel(ppp); kfree(ppp); }#endif}static int tone_zone_init(void){ int x; for (x=0;x<ZT_TONE_ZONE_MAX;x++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -