⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zaptel.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 5 页
字号:
		data[0] = (fcs & 0xff);		data[1] = (fcs >> 8) & 0xff;		/* Account for FCS length */		ss->writen[ss->inwritebuf]+=2;		/* Advance to next window */		oldbuf = ss->inwritebuf;		ss->inwritebuf = (ss->inwritebuf + 1) % ss->numbufs;		if (ss->inwritebuf == ss->outwritebuf) {			/* Whoops, no more space.  */			ss->inwritebuf = -1;		}		if (ss->outwritebuf < 0) {			/* Let the interrupt handler know there's			   some space for us */			ss->outwritebuf = oldbuf;		}#if CONFIG_ZAPATA_DEBUG		printk("Buffered %d bytes (skblen = %d) to go out in buffer %d\n", ss->writen[oldbuf], skb->len, oldbuf);		for (x=0;x<ss->writen[oldbuf];x++)		     printk("%02x ", ss->writebuf[oldbuf][x]);		printk("\n");#endif		retval = 1;	}	spin_unlock_irqrestore(&ss->lock, flags);	if (retval) {		/* Get rid of the SKB if we're returning non-zero */		/* N.B. this is called in process or BH context so		   dev_kfree_skb is OK. */		dev_kfree_skb(skb);	}	return retval;}static int zt_ppp_ioctl(struct ppp_channel *ppp, unsigned int cmd, unsigned long flags){	return -EIO;}static struct ppp_channel_ops ztppp_ops ={	start_xmit: zt_ppp_xmit,	ioctl: zt_ppp_ioctl,};#endifstatic void zt_chan_unreg(struct zt_chan *chan){	int x;	unsigned long flags;#ifdef CONFIG_ZAPATA_NET	if (chan->flags & ZT_FLAG_NETDEV) {#ifdef LINUX26		unregister_hdlc_device(chan->hdlcnetdev->netdev);		free_netdev(chan->hdlcnetdev->netdev);#else		unregister_hdlc_device(&chan->hdlcnetdev->netdev);#endif		kfree(chan->hdlcnetdev);		chan->hdlcnetdev = NULL;	}#endif	write_lock_irqsave(&chan_lock, flags);	if (chan->flags & ZT_FLAG_REGISTERED) {		chans[chan->channo] = NULL;		chan->flags &= ~ZT_FLAG_REGISTERED;	}#ifdef CONFIG_ZAPATA_PPP	if (chan->ppp) {		printk("HUH???  PPP still attached??\n");	}#endif	maxchans = 0;	for (x=1;x<ZT_MAX_CHANNELS;x++) 		if (chans[x]) {			maxchans = x + 1;			/* Remove anyone pointing to us as master			   and make them their own thing */			if (chans[x]->master == chan) {				chans[x]->master = chans[x];			}			if ((chans[x]->confna == chan->channo) &&				(((chans[x]->confmode >= ZT_CONF_MONITOR) &&				(chans[x]->confmode <= ZT_CONF_MONITORBOTH)) ||				(chans[x]->confmode == ZT_CONF_DIGITALMON))) {				/* Take them out of conference with us */				/* release conference resource if any */				if (chans[x]->confna)					zt_check_conf(chans[x]->confna);				chans[x]->confna = 0;				chans[x]->_confn = 0;				chans[x]->confmode = 0;			}		}	chan->channo = -1;	write_unlock_irqrestore(&chan_lock, flags);}static ssize_t zt_chan_read(struct file *file, char *usrbuf, size_t count, int unit){	struct zt_chan *chan = chans[unit];	int amnt;	int res, rv;	int oldbuf,x;	unsigned long flags;	/* Make sure count never exceeds 65k, and make sure it's unsigned */	count &= 0xffff;	if (!chan) 		return -EINVAL;	if (count < 1)		return -EINVAL;	for(;;) {		spin_lock_irqsave(&chan->lock, flags);		if (chan->eventinidx != chan->eventoutidx) {			spin_unlock_irqrestore(&chan->lock, flags);			return -ELAST;		}		res = chan->outreadbuf;		if (chan->rxdisable)			res = -1;		spin_unlock_irqrestore(&chan->lock, flags);		if (res >= 0) break;		if (file->f_flags & O_NONBLOCK)			return -EAGAIN;		rv = schluffen(&chan->readbufq);		if (rv) return (rv);	}	amnt = count;	if (chan->flags & ZT_FLAG_LINEAR) {		if (amnt > (chan->readn[chan->outreadbuf] << 1)) 			amnt = chan->readn[chan->outreadbuf] << 1;		if (amnt) {			/* There seems to be a max stack size, so we have			   to do this in smaller pieces */			short lindata[128];			int left = amnt >> 1; /* amnt is in bytes */			int pos = 0;			int pass;			while(left) {				pass = left;				if (pass > 128)					pass = 128;				for (x=0;x<pass;x++)					lindata[x] = ZT_XLAW(chan->readbuf[chan->outreadbuf][x + pos], chan);				if (copy_to_user(usrbuf + (pos << 1), lindata, pass << 1))					return -EFAULT;				left -= pass;				pos += pass;			}		}	} else {		if (amnt > chan->readn[chan->outreadbuf]) 			amnt = chan->readn[chan->outreadbuf];		if (amnt) {			if (copy_to_user(usrbuf, chan->readbuf[chan->outreadbuf], amnt))				return -EFAULT;		}	}	spin_lock_irqsave(&chan->lock, flags);	chan->readidx[chan->outreadbuf] = 0;	chan->readn[chan->outreadbuf] = 0;	oldbuf = chan->outreadbuf;	chan->outreadbuf = (chan->outreadbuf + 1) % chan->numbufs;	if (chan->outreadbuf == chan->inreadbuf) {		/* Out of stuff */		chan->outreadbuf = -1;		if (chan->rxbufpolicy == ZT_POLICY_WHEN_FULL)			chan->rxdisable = 1;	}	if (chan->inreadbuf < 0) {		/* Notify interrupt handler that we have some space now */		chan->inreadbuf = oldbuf;	}	spin_unlock_irqrestore(&chan->lock, flags);		return amnt;}static ssize_t zt_chan_write(struct file *file, const char *usrbuf, size_t count, int unit){	unsigned long flags;	struct zt_chan *chan = chans[unit];	int res, amnt, oldbuf, rv,x;	/* Make sure count never exceeds 65k, and make sure it's unsigned */	count &= 0xffff;	if (!chan) 		return -EINVAL;	if (count < 1)		return -EINVAL;	for(;;) {		spin_lock_irqsave(&chan->lock, flags);		if ((chan->curtone || chan->pdialcount) && !(chan->flags & ZT_FLAG_PSEUDO)) {			chan->curtone = NULL;			chan->tonep = 0;			chan->dialing = 0;			chan->txdialbuf[0] = '\0';			chan->pdialcount = 0;		}		if (chan->eventinidx != chan->eventoutidx) {			spin_unlock_irqrestore(&chan->lock, flags);			return -ELAST;		}		res = chan->inwritebuf;		spin_unlock_irqrestore(&chan->lock, flags);		if (res >= 0) 			break;		if (file->f_flags & O_NONBLOCK)			return -EAGAIN;		/* Wait for something to be available */		rv = schluffen(&chan->writebufq);		if (rv)			return rv;	}	amnt = count;	if (chan->flags & ZT_FLAG_LINEAR) {		if (amnt > (chan->blocksize << 1))			amnt = chan->blocksize << 1;	} else {		if (amnt > chan->blocksize)			amnt = chan->blocksize;	}#if CONFIG_ZAPATA_DEBUG	printk("zt_chan_write(unit: %d, inwritebuf: %d, outwritebuf: %d amnt: %d\n", 		unit, chan->inwritebuf, chan->outwritebuf, amnt);#endif	if (amnt) {		if (chan->flags & ZT_FLAG_LINEAR) {			/* There seems to be a max stack size, so we have			   to do this in smaller pieces */			short lindata[128];			int left = amnt >> 1; /* amnt is in bytes */			int pos = 0;			int pass;			while(left) {				pass = left;				if (pass > 128)					pass = 128;				if (copy_from_user(lindata, usrbuf + (pos << 1), pass << 1))					return -EFAULT;				left -= pass;				for (x=0;x<pass;x++)					chan->writebuf[chan->inwritebuf][x + pos] = ZT_LIN2X(lindata[x], chan);				pos += pass;			}			chan->writen[chan->inwritebuf] = amnt >> 1;		} else {			copy_from_user(chan->writebuf[chan->inwritebuf], usrbuf, amnt);			chan->writen[chan->inwritebuf] = amnt;		}		chan->writeidx[chan->inwritebuf] = 0;		if (chan->flags & ZT_FLAG_FCS)			calc_fcs(chan);		oldbuf = chan->inwritebuf;		spin_lock_irqsave(&chan->lock, flags);		chan->inwritebuf = (chan->inwritebuf + 1) % chan->numbufs;		if (chan->inwritebuf == chan->outwritebuf) {			/* Don't stomp on the transmitter, just wait for them to 			   wake us up */			chan->inwritebuf = -1;			/* Make sure the transmitter is transmitting in case of POLICY_WHEN_FULL */			chan->txdisable = 0;		}		if (chan->outwritebuf < 0) {			/* Okay, the interrupt handler has been waiting for us.  Give them a buffer */			chan->outwritebuf = oldbuf;		}		spin_unlock_irqrestore(&chan->lock, flags);	}	return amnt;}static int zt_ctl_open(struct inode *inode, struct file *file){	/* Nothing to do, really */#ifndef LINUX26	MOD_INC_USE_COUNT;#endif	return 0;}static int zt_chan_open(struct inode *inode, struct file *file){	/* Nothing to do here for now either */#ifndef LINUX26	MOD_INC_USE_COUNT;#endif	return 0;}static int zt_ctl_release(struct inode *inode, struct file *file){	/* Nothing to do */#ifndef LINUX26	MOD_DEC_USE_COUNT;#endif	return 0;}static int zt_chan_release(struct inode *inode, struct file *file){	/* Nothing to do for now */#ifndef LINUX26	MOD_DEC_USE_COUNT;#endif	return 0;}static void set_txtone(struct zt_chan *ss,int fac, int init_v2, int init_v3){	if (fac == 0)	{		ss->v2_1 = 0;		ss->v3_1 = 0;		return;	}	ss->txtone = fac;	ss->v1_1 = 0;	ss->v2_1 = init_v2;	ss->v3_1 = init_v3;	return;}static void zt_rbs_sethook(struct zt_chan *chan, int txsig, int txstate, int timeout){static int outs[NUM_SIGS][5] = {/* We set the idle case of the ZT_SIG_NONE to this pattern to make idle E1 CASchannels happy. Should not matter with T1, since on an un-configured channel, who cares what the sig bits are as long as they are stable */	{ ZT_SIG_NONE, 		ZT_ABIT | ZT_CBIT | ZT_DBIT, 0, 0, 0 },  /* no signalling */	{ ZT_SIG_EM, 		0, ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT,		ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0 },  /* E and M */	{ ZT_SIG_FXSLS, 	ZT_BBIT | ZT_DBIT, 		ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT,			ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0 }, /* FXS Loopstart */	{ ZT_SIG_FXSGS, 	ZT_BBIT | ZT_DBIT, #ifdef CONFIG_CAC_GROUNDSTART		ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0, 0 }, /* FXS Groundstart (CAC-style) */#else		ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, ZT_ABIT | ZT_CBIT, 0 }, /* FXS Groundstart (normal) */#endif	{ ZT_SIG_FXSKS,		ZT_BBIT | ZT_DBIT, 		ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT,			ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0 }, /* FXS Kewlstart */	{ ZT_SIG_FXOLS,		ZT_BBIT | ZT_DBIT, ZT_BBIT | ZT_DBIT, 0, 0 }, /* FXO Loopstart */	{ ZT_SIG_FXOGS,		ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT,		 ZT_BBIT | ZT_DBIT, 0, 0 }, /* FXO Groundstart */	{ ZT_SIG_FXOKS,		ZT_BBIT | ZT_DBIT, ZT_BBIT | ZT_DBIT, 0, 		ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT }, /* FXO Kewlstart */	{ ZT_SIG_SF,	ZT_BBIT | ZT_CBIT | ZT_DBIT, 			ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 			ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 			ZT_BBIT | ZT_CBIT | ZT_DBIT },  /* no signalling */	{ ZT_SIG_EM_E1, 	ZT_DBIT, ZT_ABIT | ZT_BBIT | ZT_DBIT,		ZT_ABIT | ZT_BBIT | ZT_DBIT, ZT_DBIT },  /* E and M  E1 */	} ;	int x;	/* if no span, return doing nothing */	if (!chan->span) return;	if (!chan->span->flags & ZT_FLAG_RBS) {		printk("zt_rbs: Tried to set RBS hook state on non-RBS channel %s\n", chan->name);		return;	}	if ((txsig > 3) || (txsig < 0)) {		printk("zt_rbs: Tried to set RBS hook state %d (> 3) on  channel %s\n", txsig, chan->name);		return;	}	if (!chan->span->rbsbits && !chan->span->hooksig) {		printk("zt_rbs: Tried to set RBS hook state %d on channel %s while span %s lacks rbsbits or hooksig function\n",			txsig, chan->name, chan->span->name);		return;	}	/* Don't do anything for RBS */	if (chan->sig == ZT_SIG_DACS_RBS)		return;	chan->txstate = txstate;		/* if tone signalling */	if (chan->sig == ZT_SIG_SF)	{		chan->txhooksig = txsig;		if (chan->txtone) /* if set to make tone for tx */		{			if ((txsig && !(chan->toneflags & ZT_REVERSE_TXTONE)) ||			 ((!txsig) && (chan->toneflags & ZT_REVERSE_TXTONE))) 			{				set_txtone(chan,chan->txtone,chan->tx_v2,chan->tx_v3);			}			else			{				set_txtone(chan,0,0,0);			}		}		chan->otimer = timeout * 8;			/* Otimer is timer in samples */		return;	}	if (chan->span->hooksig) {		chan->txhooksig = txsig;		chan->span->hooksig(chan, txsig);		chan->otimer = timeout * 8;			/* Otimer is timer in samples */		return;	} else {		for (x=0;x<NUM_SIGS;x++) {			if (outs[x][0] == chan->sig) {#if CONFIG_ZAPATA_DEBUG				printk("Setting bits to %d for channel %s state %d in %d signalling\n", outs[x][txsig + 1], chan->name, txsig, chan->sig);#endif				chan->txhooksig = txsig;				chan->txsig = outs[x][txsig+1];				chan->span->rbsbits(chan, chan->txsig);				chan->otimer = timeout * 8;	/* Otimer is timer in samples */				return;			}		}	}	printk("zt_rbs: Don't know RBS signalling type %d on channel %s\n", chan->sig, chan->name);}static int zt_cas_setbits(struct zt_chan *chan, int bits){	/* if no span, return as error */	if (!chan->span) return -1;	if (chan->span->rbsbits) {		chan->txsig = bits;		chan->span->rbsbits(chan, bits);	} else {		printk("Huh?  CAS setbits, but no RBS bits function\n");	}	return 0;}static int zt_hangup(struct zt_chan *chan){	int x,res=0;	/* Can't hangup pseudo channels */	if (!chan->span)		return 0;	/* Can't hang up a clear channel */	if (chan->flags & ZT_FLAG_CLEAR)		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);		} else if ((chan->sig == ZT_SIG_FXOKS) && (chan->txstate != ZT_TXSTATE_ONHOOK)) {			/* Do RBS signalling on the channel's behalf */			zt_rbs_sethook(chan, ZT_TXSIG_KEWL, ZT_TXSTATE_KEWL, ZT_KEWLTIME);		} else			zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0);	} else {		/* Let the driver hang up the line if it wants to  */		if (chan->span->sethook)			res = chan->span->sethook(chan, ZT_ONHOOK);	}	/* if not registered yet, just return here */	if (!(chan->flags & ZT_FLAG_REGISTERED)) return res;	/* Mark all buffers as empty */	for (x = 0;x < chan->numbufs;x++) {		chan->writen[x] = 		chan->writeidx[x]=		chan->readn[x]=		chan->readidx[x] = 0;	}		if (chan->readbuf[0]) {		chan->inreadbuf = 0;		chan->inwritebuf = 0;	} else {		chan->inreadbuf = -1;		chan->inwritebuf = -1;	}	chan->outreadbuf = -1;	chan->outwritebuf = -1;	chan->dialing = 0;	chan->afterdialingtimer = 0;	chan->curtone = NULL;	chan->pdialcount = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -