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

📄 zaptel.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 5 页
字号:
		tone_zones[x] = NULL;	return 0;}static int free_tone_zone(int num){	struct zt_zone *z;	if ((num < 0) || (num >= ZT_TONE_ZONE_MAX))		return -EINVAL;	write_lock(&zone_lock);	z = tone_zones[num];	tone_zones[num] = NULL;	write_unlock(&zone_lock);	kfree(z);	return 0;}static int zt_register_tone_zone(int num, struct zt_zone *zone){	int res=0;	if ((num >= ZT_TONE_ZONE_MAX) || (num < 0))		return -EINVAL;	write_lock(&zone_lock);	if (tone_zones[num]) {		res = -EINVAL;	} else {		res = 0;		tone_zones[num] = zone;	}	write_unlock(&zone_lock);	if (!res)		printk(KERN_INFO "Registered tone zone %d (%s)\n", num, zone->name);	return res;}static int start_tone(struct zt_chan *chan, int tone){	int res = -EINVAL;	/* Stop the current tone, no matter what */	chan->tonep = 0;	chan->curtone = NULL;	chan->pdialcount = 0;	chan->txdialbuf[0] = '\0';	chan->dialing =  0;	if ((tone >= ZT_TONE_MAX) || (tone < -1)) 		return -EINVAL;	/* Just wanted to stop the tone anyway */	if (tone < 0)		return 0;	if (chan->curzone) {		/* Have a tone zone */		if (chan->curzone->tones[tone]) {			chan->curtone = chan->curzone->tones[tone];			res = 0;		} else	/* Indicate that zone is loaded but no such tone exists */			res = -ENOSYS;	} else	/* Note that no tone zone exists at the moment */		res = -ENODATA;	if (chan->curtone)		zt_init_tone_state(&chan->ts, chan->curtone);	return res;}static int set_tone_zone(struct zt_chan *chan, int zone){	int res=0;	/* Assumes channel is already locked */	if ((zone >= ZT_TONE_ZONE_MAX) || (zone < -1))		return -EINVAL;		read_lock(&zone_lock);	if (zone == -1) {		zone = default_zone;	}	if (tone_zones[zone]) {		chan->curzone = tone_zones[zone];		chan->tonezone = zone;		memcpy(chan->ringcadence, chan->curzone->ringcadence, sizeof(chan->ringcadence));	} else {		res = -ENODATA;	}		read_unlock(&zone_lock);	return res;}static void zt_set_law(struct zt_chan *chan, int law){	if (!law) {		if (chan->deflaw)			law = chan->deflaw;		else			if (chan->span) law = chan->span->deflaw;			else law = ZT_LAW_MULAW;	}	if (law == ZT_LAW_ALAW) {		chan->xlaw = __zt_alaw;#ifdef CONFIG_CALC_XLAW		chan->lineartoxlaw = __zt_lineartoalaw;#else		chan->lin2x = __zt_lin2a;#endif	} else {		chan->xlaw = __zt_mulaw;#ifdef CONFIG_CALC_XLAW		chan->lineartoxlaw = __zt_lineartoulaw;#else		chan->lin2x = __zt_lin2mu;#endif	}}#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t register_devfs_channel(struct zt_chan *chan, devfs_handle_t dir){	char path[100];	char link[100];	char buf[50];	char tmp[100];	int link_offset = 0;	int tmp_offset = 0;	int path_offset = 0;	int err = 0;	devfs_handle_t chan_dev;	umode_t mode = S_IFCHR|S_IRUGO|S_IWUGO;	unsigned int flags = DEVFS_FL_AUTO_OWNER;	sprintf(path, "%d", chan->chanpos);	chan_dev = devfs_register(dir, path, flags, ZT_MAJOR, chan->channo, mode, &zt_fops, NULL);	if (!chan_dev) {		printk("zaptel: Something really bad happened.  Unable to register devfs entry\n");		return NULL;	}	/* Set up the path of the destination of the link */	link_offset = devfs_generate_path(chan_dev, link, sizeof(link) - 1);	/* Now we need to strip off the leading "zap/".  If we don't, then we build a broken symlink */	path_offset = devfs_generate_path(zaptel_devfs_dir, path, sizeof(path) - 1); /* We'll just "borrow" path for a second */	path_offset = strlen(path+path_offset);	link_offset += path_offset; /* Taking out the "zap" */	link_offset++; /* Add one more place for the '/'.  The path generated does not contain the '/' we need to strip */		/* Set up the path of the file/link itself */	tmp_offset = devfs_generate_path(zaptel_devfs_dir, tmp, sizeof(tmp) - 1);	sprintf(buf, "/%d", chan->channo);	strncpy(path, tmp+tmp_offset, sizeof(path) - 1);	strncat(path, buf, sizeof(path) - 1);	err = devfs_mk_symlink(NULL, path, DEVFS_FL_DEFAULT, link+link_offset, &chan->fhandle_symlink, NULL);	if (err != 0) {		printk("Problem with making devfs symlink: %d\n", err);	}	return chan_dev;}#endif /* CONFIG_DEVFS_FS */static int zt_chan_reg(struct zt_chan *chan){	int x;	int res=0;	unsigned long flags;		write_lock_irqsave(&chan_lock, flags);	for (x=1;x<ZT_MAX_CHANNELS;x++) {		if (!chans[x]) {			spin_lock_init(&chan->lock);			chans[x] = chan;			if (maxchans < x + 1)				maxchans = x + 1;			chan->channo = x;			if (!chan->master)				chan->master = chan;			if (!chan->readchunk)				chan->readchunk = chan->sreadchunk;			if (!chan->writechunk)				chan->writechunk = chan->swritechunk;			zt_set_law(chan, 0);			close_channel(chan); 			/* set this AFTER running close_channel() so that				HDLC channels wont cause hangage */			chan->flags |= ZT_FLAG_REGISTERED;			res = 0;			break;		}	}	write_unlock_irqrestore(&chan_lock, flags);		if (x >= ZT_MAX_CHANNELS)		printk(KERN_ERR "No more channels available\n");	return res;}char *zt_lboname(int x){	if ((x < 0) || ( x > 7))		return "Unknown";	return zt_txlevelnames[x];}#if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP)#endif#ifdef CONFIG_ZAPATA_NET#ifdef NEW_HDLC_INTERFACEstatic int zt_net_open(struct net_device *dev){#ifdef LINUX26	int res = hdlc_open(dev);	struct zt_chan *ms = dev_to_ztchan(dev);#else	hdlc_device *hdlc = dev_to_hdlc(dev);	struct zt_chan *ms = hdlc_to_ztchan(hdlc);	int res = hdlc_open(hdlc);#endif		                                                                                                                             /*	if (!dev->hard_start_xmit) return res; is this really necessary? --byg */	if (res) /* this is necessary to avoid kernel panic when UNSPEC link encap, proven --byg */		return res;#elsestatic int zt_net_open(hdlc_device *hdlc){	struct zt_chan *ms = hdlc_to_ztchan(hdlc);	int res;#endif	if (!ms) {		printk("zt_net_open: nothing??\n");		return -EINVAL;	}	if (ms->flags & ZT_FLAG_OPEN) {		printk("%s is already open!\n", ms->name);		return -EBUSY;	}	if (!(ms->flags & ZT_FLAG_NETDEV)) {		printk("%s is not a net device!\n", ms->name);		return -EINVAL;	}	ms->txbufpolicy = ZT_POLICY_IMMEDIATE;	ms->rxbufpolicy = ZT_POLICY_IMMEDIATE;	res = zt_reallocbufs(ms, ZT_DEFAULT_MTU_MRU, ZT_DEFAULT_NUM_BUFS);	if (res) 		return res;	fasthdlc_init(&ms->rxhdlc);	fasthdlc_init(&ms->txhdlc);	ms->infcs = PPP_INITFCS;#ifndef LINUX26	MOD_INC_USE_COUNT;#endif	#if CONFIG_ZAPATA_DEBUG	printk("ZAPNET: Opened channel %d name %s\n", ms->channo, ms->name);#endif	return 0;}#ifdef NEW_HDLC_INTERFACEstatic int zt_net_stop(struct net_device *dev){	hdlc_device *hdlc = dev_to_hdlc(dev);#elsestatic void zt_net_close(hdlc_device *hdlc){#endif	struct zt_chan *ms = hdlc_to_ztchan(hdlc);	if (!ms) {#ifdef NEW_HDLC_INTERFACE		printk("zt_net_stop: nothing??\n");		return 0;#else		printk("zt_net_close: nothing??\n");		return;#endif	}	if (!(ms->flags & ZT_FLAG_NETDEV)) {#ifdef NEW_HDLC_INTERFACE		printk("zt_net_stop: %s is not a net device!\n", ms->name);		return 0;#else		printk("zt_net_close: %s is not a net device!\n", ms->name);		return;#endif	}	/* Not much to do here.  Just deallocate the buffers */	zt_reallocbufs(ms, 0, 0);#ifdef LINUX26	hdlc_close(dev);#else	hdlc_close(hdlc);#endif	#ifndef LINUX26	MOD_DEC_USE_COUNT;#endif	#ifdef NEW_HDLC_INTERFACE	return 0;#else	return;#endif}#ifdef NEW_HDLC_INTERFACE/* kernel 2.4.20+ has introduced attach function, dunno what to do, just copy sources from dscc4 to be sure and ready for further mastering, NOOP right now (i.e. really a stub)  --byg */#ifdef LINUX26static int zt_net_attach(struct net_device *dev, unsigned short encoding,        unsigned short parity)#else		static int zt_net_attach(hdlc_device *hdlc, unsigned short encoding,        unsigned short parity)#endif{/*        struct net_device *dev = hdlc_to_dev(hdlc);        struct dscc4_dev_priv *dpriv = dscc4_priv(dev);        if (encoding != ENCODING_NRZ &&            encoding != ENCODING_NRZI &&            encoding != ENCODING_FM_MARK &&            encoding != ENCODING_FM_SPACE &&            encoding != ENCODING_MANCHESTER)                return -EINVAL;        if (parity != PARITY_NONE &&            parity != PARITY_CRC16_PR0_CCITT &&            parity != PARITY_CRC16_PR1_CCITT &&            parity != PARITY_CRC32_PR0_CCITT &&            parity != PARITY_CRC32_PR1_CCITT)                return -EINVAL;        dpriv->encoding = encoding;        dpriv->parity = parity;*/        return 0;}#endif																								 static struct zt_hdlc *zt_hdlc_alloc(void){	struct zt_hdlc *tmp;	tmp = kmalloc(sizeof(struct zt_hdlc), GFP_KERNEL);	if (tmp) {		memset(tmp, 0, sizeof(struct zt_hdlc));	}	return tmp;}#ifdef NEW_HDLC_INTERFACEstatic int zt_xmit(struct sk_buff *skb, struct net_device *dev){	/* FIXME: this construction seems to be not very optimal for me but I could find nothing better at the moment (Friday, 10PM :( )  --byg *//*	struct zt_chan *ss = hdlc_to_ztchan(list_entry(dev, struct zt_hdlc, netdev.netdev));*/#ifdef LINUX26	struct zt_chan *ss = dev_to_ztchan(dev);	struct net_device_stats *stats = hdlc_stats(dev);#else	struct zt_chan *ss = (list_entry(dev, struct zt_hdlc, netdev.netdev)->chan);	struct net_device_stats *stats = &ss->hdlcnetdev->netdev.stats;#endif	#elsestatic int zt_xmit(hdlc_device *hdlc, struct sk_buff *skb){	struct zt_chan *ss = hdlc_to_ztchan(hdlc);	struct net_device *dev = &ss->hdlcnetdev->netdev.netdev;	struct net_device_stats *stats = &ss->hdlcnetdev->netdev.stats;#endif	int retval = 1;	int x,oldbuf;	unsigned int fcs;	unsigned char *data;	unsigned long flags;	/* See if we have any buffers */	spin_lock_irqsave(&ss->lock, flags);	if (skb->len > ss->blocksize - 2) {		printk(KERN_ERR "zt_xmit(%s): skb is too large (%d > %d)\n", dev->name, skb->len, ss->blocksize -2);		stats->tx_dropped++;		retval = 0;	} else if (ss->inwritebuf >= 0) {		/* We have a place to put this packet */		/* XXX We should keep the SKB and avoid the memcpy XXX */		data = ss->writebuf[ss->inwritebuf];		memcpy(data, skb->data, skb->len);		ss->writen[ss->inwritebuf] = skb->len;		ss->writeidx[ss->inwritebuf] = 0;		/* Calculate the FCS */		fcs = PPP_INITFCS;		for (x=0;x<skb->len;x++)			fcs = PPP_FCS(fcs, data[x]);		/* Invert it */		fcs ^= 0xffff;		/* Send it out LSB first */		data[ss->writen[ss->inwritebuf]++] = (fcs & 0xff);		data[ss->writen[ss->inwritebuf]++] = (fcs >> 8) & 0xff;		/* 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;		}		dev->trans_start = jiffies;		stats->tx_packets++;		stats->tx_bytes += ss->writen[oldbuf];#if CONFIG_ZAPATA_DEBUG		printk("Buffered %d bytes to go out in buffer %d\n", ss->writen[oldbuf], oldbuf);		for (x=0;x<ss->writen[oldbuf];x++)		     printk("%02x ", ss->writebuf[oldbuf][x]);		printk("\n");#endif		retval = 0;		/* Free the SKB */		dev_kfree_skb_any(skb);	}	spin_unlock_irqrestore(&ss->lock, flags);	return retval;}#ifdef NEW_HDLC_INTERFACEstatic int zt_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	return hdlc_ioctl(dev, ifr, cmd);}#elsestatic int zt_net_ioctl(hdlc_device *hdlc, struct ifreq *ifr, int cmd){	return -EIO;}#endif#endif#ifdef CONFIG_ZAPATA_PPPstatic int zt_ppp_xmit(struct ppp_channel *ppp, struct sk_buff *skb){	/* 	 * If we can't handle the packet right now, return 0.  If we	 * we handle or drop it, return 1.  Always free if we return	 * 1 and never if we return 0         */	struct zt_chan *ss = ppp->private;	int x,oldbuf;	unsigned int fcs;	unsigned char *data;	long flags;	int retval = 0;	/* See if we have any buffers */	spin_lock_irqsave(&ss->lock, flags);	if (!(ss->flags & ZT_FLAG_OPEN)) {		printk("Can't transmit on closed channel\n");		retval = 1;	} else if (skb->len > ss->blocksize - 4) {		printk(KERN_ERR "zt_ppp_xmit(%s): skb is too large (%d > %d)\n", ss->name, skb->len, ss->blocksize -2);		retval = 1;	} else if (ss->inwritebuf >= 0) {		/* We have a place to put this packet */		/* XXX We should keep the SKB and avoid the memcpy XXX */		data = ss->writebuf[ss->inwritebuf];		/* Start with header of two bytes */		/* Add "ALL STATIONS" and "UNNUMBERED" */		data[0] = 0xff;		data[1] = 0x03;		ss->writen[ss->inwritebuf] = 2;		/* Copy real data and increment amount written */		memcpy(data + 2, skb->data, skb->len);		ss->writen[ss->inwritebuf] += skb->len;		/* Re-set index back to zero */		ss->writeidx[ss->inwritebuf] = 0;		/* Calculate the FCS */		fcs = PPP_INITFCS;		for (x=0;x<skb->len + 2;x++)			fcs = PPP_FCS(fcs, data[x]);		/* Invert it */		fcs ^= 0xffff;		/* Point past the real data now */		data += (skb->len + 2);		/* Send FCS out LSB first */

⌨️ 快捷键说明

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