📄 zaptel.c
字号:
chan->cadencepos = 0; chan->txdialbuf[0] = 0; return res;}static int initialize_channel(struct zt_chan *chan){ int res; unsigned long flags; void *rxgain=NULL; echo_can_state_t *ec=NULL; if ((res = zt_reallocbufs(chan, ZT_DEFAULT_BLOCKSIZE, ZT_DEFAULT_NUM_BUFS))) return res; spin_lock_irqsave(&chan->lock, flags); chan->rxbufpolicy = ZT_POLICY_IMMEDIATE; chan->txbufpolicy = ZT_POLICY_IMMEDIATE; /* Free up the echo canceller if there is one */ ec = chan->ec; chan->ec = NULL; chan->echocancel = 0; chan->echostate = ECHO_STATE_IDLE; chan->echolastupdate = 0; chan->echotimer = 0; chan->txdisable = 0; chan->rxdisable = 0; chan->digitmode = DIGIT_MODE_DTMF; chan->dialing = 0; chan->afterdialingtimer = 0; chan->cadencepos = 0; chan->firstcadencepos = 0; /* By default loop back to first cadence position */ /* HDLC & FCS stuff */ fasthdlc_init(&chan->rxhdlc); fasthdlc_init(&chan->txhdlc); chan->infcs = PPP_INITFCS; /* Timings for RBS */ chan->prewinktime = ZT_DEFAULT_PREWINKTIME; chan->preflashtime = ZT_DEFAULT_PREFLASHTIME; chan->winktime = ZT_DEFAULT_WINKTIME; chan->flashtime = ZT_DEFAULT_FLASHTIME; if (chan->sig & __ZT_SIG_FXO) chan->starttime = ZT_DEFAULT_RINGTIME; else chan->starttime = ZT_DEFAULT_STARTTIME; chan->rxwinktime = ZT_DEFAULT_RXWINKTIME; chan->rxflashtime = ZT_DEFAULT_RXFLASHTIME; chan->debouncetime = ZT_DEFAULT_DEBOUNCETIME; chan->pulsemaketime = ZT_DEFAULT_PULSEMAKETIME; chan->pulsebreaktime = ZT_DEFAULT_PULSEBREAKTIME; chan->pulseaftertime = ZT_DEFAULT_PULSEAFTERTIME; /* Initialize RBS timers */ chan->itimerset = chan->itimer = chan->otimer = 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); /* Reset conferences */ reset_conf(chan); /* I/O Mask, etc */ chan->iomask = 0; /* release conference resource if any */ if (chan->confna) zt_check_conf(chan->confna); if ((chan->sig & __ZT_SIG_DACS) != __ZT_SIG_DACS) { chan->confna = 0; chan->confmode = 0; } chan->_confn = 0; memset(chan->conflast, 0, sizeof(chan->conflast)); memset(chan->conflast1, 0, sizeof(chan->conflast1)); memset(chan->conflast2, 0, sizeof(chan->conflast2)); chan->confmute = 0; chan->gotgs = 0; chan->curtone = NULL; chan->tonep = 0; chan->pdialcount = 0; set_tone_zone(chan, -1); if (chan->gainalloc && chan->rxgain) rxgain = chan->rxgain; chan->rxgain = defgain; chan->txgain = defgain; chan->gainalloc = 0; chan->eventinidx = chan->eventoutidx = 0; zt_set_law(chan,0); zt_hangup(chan); /* Make sure that the audio flag is cleared on a clear channel */ if (chan->sig & ZT_SIG_CLEAR) chan->flags &= ~ZT_FLAG_AUDIO; if (chan->sig == ZT_SIG_CLEAR) chan->flags &= ~(ZT_FLAG_PPP | ZT_FLAG_FCS | ZT_FLAG_HDLC); chan->flags &= ~ZT_FLAG_LINEAR; if (chan->curzone) { /* Take cadence from tone zone */ memcpy(chan->ringcadence, chan->curzone->ringcadence, sizeof(chan->ringcadence)); } else { /* Do a default */ memset(chan->ringcadence, 0, sizeof(chan->ringcadence)); chan->ringcadence[0] = chan->starttime; chan->ringcadence[1] = ZT_RINGOFFTIME; } spin_unlock_irqrestore(&chan->lock, flags); if (rxgain) kfree(rxgain); if (ec) echo_can_free(ec); return 0;}static int zt_timing_open(struct inode *inode, struct file *file){ struct zt_timer *t; unsigned long flags; t = kmalloc(sizeof(struct zt_timer), GFP_KERNEL); if (!t) return -ENOMEM; /* Allocate a new timer */ memset(t, 0, sizeof(struct zt_timer)); init_waitqueue_head(&t->sel); file->private_data = t;#ifndef LINUX26 MOD_INC_USE_COUNT;#endif spin_lock_irqsave(&zaptimerlock, flags); t->next = zaptimers; zaptimers = t; spin_unlock_irqrestore(&zaptimerlock, flags); return 0;}static int zt_timer_release(struct inode *inode, struct file *file){ struct zt_timer *t, *cur, *prev; unsigned long flags; t = file->private_data; if (t) { spin_lock_irqsave(&zaptimerlock, flags); prev = NULL; cur = zaptimers; while(cur) { if (t == cur) break; prev = cur; cur = cur->next; } if (cur) { if (prev) prev->next = cur->next; else zaptimers = cur->next; } spin_unlock_irqrestore(&zaptimerlock, flags); if (!cur) { printk("Zap Timer: Not on list??\n"); return 0; } kfree(t);#ifndef LINUX26 MOD_DEC_USE_COUNT;#endif } return 0;}static int zt_specchan_open(struct inode *inode, struct file *file, int unit, int inc){ int res = 0; if (chans[unit] && chans[unit]->sig) { /* Make sure we're not already open, a net device, or a slave device */ if (chans[unit]->flags & ZT_FLAG_OPEN) res = -EBUSY; else if (chans[unit]->flags & ZT_FLAG_NETDEV) res = -EBUSY; else if (chans[unit]->master != chans[unit]) res = -EBUSY; else if ((chans[unit]->sig & __ZT_SIG_DACS) == __ZT_SIG_DACS) res = -EBUSY; else { /* Assume everything is going to be okay */ res = initialize_channel(chans[unit]); if (chans[unit]->flags & ZT_FLAG_PSEUDO) chans[unit]->flags |= ZT_FLAG_AUDIO; if (chans[unit]->span && chans[unit]->span->open) res = chans[unit]->span->open(chans[unit]); if (!res) { chans[unit]->file = file;#ifndef LINUX26 if (inc) MOD_INC_USE_COUNT;#endif chans[unit]->flags |= ZT_FLAG_OPEN; } else { close_channel(chans[unit]); } } } else res = -ENXIO; return res;}static int zt_specchan_release(struct inode *node, struct file *file, int unit){ int res=0; if (chans[unit]) { chans[unit]->flags &= ~ZT_FLAG_OPEN; chans[unit]->file = NULL; close_channel(chans[unit]); if (chans[unit]->span && chans[unit]->span->close) res = chans[unit]->span->close(chans[unit]); } else res = -ENXIO;#ifndef LINUX26 MOD_DEC_USE_COUNT;#endif return res;}static struct zt_chan *zt_alloc_pseudo(void){ struct zt_chan *pseudo; unsigned long flags; /* Don't allow /dev/zap/pseudo to open if there are no spans */ if (maxspans < 1) return NULL; pseudo = kmalloc(sizeof(struct zt_chan), GFP_KERNEL); if (!pseudo) return NULL; memset(pseudo, 0, sizeof(struct zt_chan)); pseudo->sig = ZT_SIG_CLEAR; pseudo->sigcap = ZT_SIG_CLEAR; pseudo->flags = ZT_FLAG_PSEUDO | ZT_FLAG_AUDIO; spin_lock_irqsave(&bigzaplock, flags); if (zt_chan_reg(pseudo)) { kfree(pseudo); pseudo = NULL; } else sprintf(pseudo->name, "Pseudo/%d", pseudo->channo); spin_unlock_irqrestore(&bigzaplock, flags); return pseudo; }static void zt_free_pseudo(struct zt_chan *pseudo){ unsigned long flags; if (pseudo) { spin_lock_irqsave(&bigzaplock, flags); zt_chan_unreg(pseudo); spin_unlock_irqrestore(&bigzaplock, flags); kfree(pseudo); }}static int zt_open(struct inode *inode, struct file *file){ int unit = UNIT(file); struct zt_chan *chan; /* Minor 0: Special "control" descriptor */ if (!unit) return zt_ctl_open(inode, file); if (unit == 253) { if (maxspans) { return zt_timing_open(inode, file); } else { return -ENXIO; } } if (unit == 254) return zt_chan_open(inode, file); if (unit == 255) { if (maxspans) { chan = zt_alloc_pseudo(); if (chan) { file->private_data = chan; return zt_specchan_open(inode, file, chan->channo, 1); } else { return -ENXIO; } } else return -ENXIO; } return zt_specchan_open(inode, file, unit, 1);}#if 0static int zt_open(struct inode *inode, struct file *file){ int res; unsigned long flags; spin_lock_irqsave(&bigzaplock, flags); res = __zt_open(inode, file); spin_unlock_irqrestore(&bigzaplock, flags); return res;}#endifstatic ssize_t zt_read(struct file *file, char *usrbuf, size_t count, loff_t *ppos){ int unit = UNIT(file); struct zt_chan *chan; /* Can't read from control */ if (!unit) { return -EINVAL; } if (unit == 253) return -EINVAL; if (unit == 254) { chan = file->private_data; if (!chan) return -EINVAL; return zt_chan_read(file, usrbuf, count, chan->channo); } if (unit == 255) { chan = file->private_data; if (!chan) { printk("No pseudo channel structure to read?\n"); return -EINVAL; } return zt_chan_read(file, usrbuf, count, chan->channo); } if (count < 0) return -EINVAL; return zt_chan_read(file, usrbuf, count, unit);}static ssize_t zt_write(struct file *file, const char *usrbuf, size_t count, loff_t *ppos){ int unit = UNIT(file); struct zt_chan *chan; /* Can't read from control */ if (!unit) return -EINVAL; if (count < 0) return -EINVAL; if (unit == 253) return -EINVAL; if (unit == 254) { chan = file->private_data; if (!chan) return -EINVAL; return zt_chan_write(file, usrbuf, count, chan->channo); } if (unit == 255) { chan = file->private_data; if (!chan) { printk("No pseudo channel structure to read?\n"); return -EINVAL; } return zt_chan_write(file, usrbuf, count, chan->channo); } return zt_chan_write(file, usrbuf, count, unit); }/* No bigger than 32k for everything per tone zone */#define MAX_SIZE 32768/* No more than 64 subtones */#define MAX_TONES 64static intioctl_load_zone(unsigned long data){ struct zt_tone *samples[MAX_TONES]; short next[MAX_TONES]; struct zt_tone_def_header th; void *slab, *ptr; long size; struct zt_zone *z; struct zt_tone_def td; struct zt_tone *t; int x; int space; int res; /* XXX Unnecessary XXX */ memset(samples, 0, sizeof(samples)); /* XXX Unnecessary XXX */ memset(next, 0, sizeof(next)); copy_from_user(&th, (struct zt_tone_def_header *)data, sizeof(th)); if ((th.count < 0) || (th.count > MAX_TONES)) { printk("Too many tones included\n"); return -EINVAL; } space = size = sizeof(struct zt_zone) + th.count * sizeof(struct zt_tone); if ((size > MAX_SIZE) || (size < 0)) return -E2BIG; ptr = slab = (char *)kmalloc(size, GFP_KERNEL); if (!slab) return -ENOMEM; /* Zero it out for simplicity */ memset(slab, 0, size); /* Grab the zone */ z = (struct zt_zone *)slab; strncpy(z->name, th.name, sizeof(z->name) - 1); for (x=0;x<ZT_MAX_CADENCE;x++) z->ringcadence[x] = th.ringcadence[x]; data += sizeof(struct zt_tone_def_header); ptr += sizeof(struct zt_zone); space -= sizeof(struct zt_zone); for (x=0;x<th.count;x++) { if (space < sizeof(struct zt_tone)) { /* Check space for zt_tone struct */ kfree(slab); printk("Insufficient tone zone space\n"); return -EINVAL; } if (copy_from_user(&td, (struct zt_tone_def *)data, sizeof(struct zt_tone_def))) { kfree(slab); return -EIO; } /* Index the current sample */ samples[x] = t = (struct zt_tone *)ptr; /* Remember which sample is next */ next[x] = td.next; /* Make sure the "next" one is sane */ if ((next[x] >= th.count) || (next[x] < 0)) { printk("Invalid 'next' pointer\n"); kfree(slab); return -EINVAL; } if (td.tone >= ZT_TONE_MAX) { printk("Too many tones defined\n"); /* Make sure it's sane */ kfree(slab); return -EINVAL; } /* Update pointers to account for zt_tone header */ space -= sizeof(struct zt_tone); ptr += sizeof(struct zt_tone); data += sizeof(struct zt_tone_def); /* Fill in tonedata, datalen, and tonesamples fields */ t->tonesamples = td.samples; t->fac1 = td.fac1; t->init_v2_1 = td.init_v2_1; t->init_v3_1 = td.init_v3_1; t->fac2 = td.fac2; t->init_v2_2 = td.init_v2_2; t->init_v3_2 = td.init_v3_2; t->modulate = td.modulate; t->next = NULL; /* XXX Unnecessary XXX */ if (!z->tones[td.tone]) z->tones[td.tone] = t; } for (x=0;x<th.count;x++) /* Set "next" pointers */ samples[x]->next = samples[next[x]]; /* Actually register zone */ res = zt_register_tone_zone(th.zone, z); if (res) kfree(slab); return res;}void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt){ ts->v1_1 = 0; ts->v2_1 = zt->init_v2_1; ts->v3_1 = zt->init_v3_1; ts->v1_2 = 0; ts->v2_2 = zt->init_v2_2; ts->v3_2 = zt->init_v3_2; ts->modulate = zt->modulate;}struc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -