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

📄 dvb_net.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
					       mac_allmulti, mask_allmulti);			break;		case RX_MODE_PROMISC:			priv->multi_num=0;			dprintk("%s: set secfilter\n", __FUNCTION__);			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);			break;		}		dprintk("%s: start filtering\n", __FUNCTION__);		priv->secfeed->start_filtering(priv->secfeed);	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {		struct timespec timeout = { 0, 30000000 }; // 30 msec		/* we have payloads encapsulated in TS */		dprintk("%s: alloc tsfeed\n", __FUNCTION__);		ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);		if (ret < 0) {			printk("%s: could not allocate ts feed\n", dev->name);			goto error;		}		/* Set netdevice pointer for ts decaps callback. */		priv->tsfeed->priv = (void *)dev;		ret = priv->tsfeed->set(priv->tsfeed, priv->pid,					TS_PACKET, DMX_TS_PES_OTHER,					32768,     /* circular buffer size */					timeout);		if (ret < 0) {			printk("%s: could not set ts feed\n", dev->name);			priv->demux->release_ts_feed(priv->demux, priv->tsfeed);			priv->tsfeed = NULL;			goto error;		}		dprintk("%s: start filtering\n", __FUNCTION__);		priv->tsfeed->start_filtering(priv->tsfeed);	} else		ret = -EINVAL;error:	up(&priv->mutex);	return ret;}static int dvb_net_feed_stop(struct net_device *dev){	struct dvb_net_priv *priv = dev->priv;	int i, ret = 0;	dprintk("%s\n", __FUNCTION__);	down(&priv->mutex);	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {		if (priv->secfeed) {			if (priv->secfeed->is_filtering) {				dprintk("%s: stop secfeed\n", __FUNCTION__);				priv->secfeed->stop_filtering(priv->secfeed);			}			if (priv->secfilter) {				dprintk("%s: release secfilter\n", __FUNCTION__);				priv->secfeed->release_filter(priv->secfeed,							      priv->secfilter);				priv->secfilter=NULL;			}			for (i=0; i<priv->multi_num; i++) {				if (priv->multi_secfilter[i]) {					dprintk("%s: release multi_filter[%d]\n",						__FUNCTION__, i);					priv->secfeed->release_filter(priv->secfeed,								      priv->multi_secfilter[i]);					priv->multi_secfilter[i] = NULL;				}			}			priv->demux->release_section_feed(priv->demux, priv->secfeed);			priv->secfeed = NULL;		} else			printk("%s: no feed to stop\n", dev->name);	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {		if (priv->tsfeed) {			if (priv->tsfeed->is_filtering) {				dprintk("%s: stop tsfeed\n", __FUNCTION__);				priv->tsfeed->stop_filtering(priv->tsfeed);			}			priv->demux->release_ts_feed(priv->demux, priv->tsfeed);			priv->tsfeed = NULL;		}		else			printk("%s: no ts feed to stop\n", dev->name);	} else		ret = -EINVAL;	up(&priv->mutex);	return ret;}static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc){	struct dvb_net_priv *priv = dev->priv;	if (priv->multi_num == DVB_NET_MULTICAST_MAX)		return -ENOMEM;	memcpy(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6);	priv->multi_num++;	return 0;}static void wq_set_multicast_list (void *data){	struct net_device *dev = data;	struct dvb_net_priv *priv = dev->priv;	dvb_net_feed_stop(dev);	priv->rx_mode = RX_MODE_UNI;	spin_lock_bh(&dev->xmit_lock);	if (dev->flags & IFF_PROMISC) {		dprintk("%s: promiscuous mode\n", dev->name);		priv->rx_mode = RX_MODE_PROMISC;	} else if ((dev->flags & IFF_ALLMULTI)) {		dprintk("%s: allmulti mode\n", dev->name);		priv->rx_mode = RX_MODE_ALL_MULTI;	} else if (dev->mc_count) {		int mci;		struct dev_mc_list *mc;		dprintk("%s: set_mc_list, %d entries\n",			dev->name, dev->mc_count);		priv->rx_mode = RX_MODE_MULTI;		priv->multi_num = 0;		for (mci = 0, mc=dev->mc_list;		     mci < dev->mc_count;		     mc = mc->next, mci++) {			dvb_set_mc_filter(dev, mc);		}	}	spin_unlock_bh(&dev->xmit_lock);	dvb_net_feed_start(dev);}static void dvb_net_set_multicast_list (struct net_device *dev){	struct dvb_net_priv *priv = dev->priv;	schedule_work(&priv->set_multicast_list_wq);}static void wq_restart_net_feed (void *data){	struct net_device *dev = data;	if (netif_running(dev)) {		dvb_net_feed_stop(dev);		dvb_net_feed_start(dev);	}}static int dvb_net_set_mac (struct net_device *dev, void *p){	struct dvb_net_priv *priv = dev->priv;	struct sockaddr *addr=p;	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);	if (netif_running(dev))		schedule_work(&priv->restart_net_feed_wq);	return 0;}static int dvb_net_open(struct net_device *dev){	struct dvb_net_priv *priv = dev->priv;	priv->in_use++;	dvb_net_feed_start(dev);	return 0;}static int dvb_net_stop(struct net_device *dev){	struct dvb_net_priv *priv = dev->priv;	priv->in_use--;	return dvb_net_feed_stop(dev);}static struct net_device_stats * dvb_net_get_stats(struct net_device *dev){	return &((struct dvb_net_priv*) dev->priv)->stats;}static void dvb_net_setup(struct net_device *dev){	ether_setup(dev);	dev->open		= dvb_net_open;	dev->stop		= dvb_net_stop;	dev->hard_start_xmit	= dvb_net_tx;	dev->get_stats		= dvb_net_get_stats;	dev->set_multicast_list = dvb_net_set_multicast_list;	dev->set_mac_address    = dvb_net_set_mac;	dev->mtu		= 4096;	dev->mc_count           = 0;	dev->hard_header_cache  = NULL;	dev->flags |= IFF_NOARP;}static int get_if(struct dvb_net *dvbnet){	int i;	for (i=0; i<DVB_NET_DEVICES_MAX; i++)		if (!dvbnet->state[i])			break;	if (i == DVB_NET_DEVICES_MAX)		return -1;	dvbnet->state[i]=1;	return i;}static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype){	struct net_device *net;	struct dvb_net_priv *priv;	int result;	int if_num;	if (feedtype != DVB_NET_FEEDTYPE_MPE && feedtype != DVB_NET_FEEDTYPE_ULE)		return -EINVAL;	if ((if_num = get_if(dvbnet)) < 0)		return -EINVAL;	net = alloc_netdev(sizeof(struct dvb_net_priv), "dvb", dvb_net_setup);	if (!net)		return -ENOMEM;	if (dvbnet->dvbdev->id)		snprintf(net->name, IFNAMSIZ, "dvb%d%u%d",			 dvbnet->dvbdev->adapter->num, dvbnet->dvbdev->id, if_num);	else		/* compatibility fix to keep dvb0_0 format */		snprintf(net->name, IFNAMSIZ, "dvb%d_%d",			 dvbnet->dvbdev->adapter->num, if_num);	net->addr_len = 6;	memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6);	dvbnet->device[if_num] = net;	priv = net->priv;	priv->demux = dvbnet->demux;	priv->pid = pid;	priv->rx_mode = RX_MODE_UNI;	priv->need_pusi = 1;	priv->tscc = 0;	priv->feedtype = feedtype;	reset_ule(priv);	INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net);	INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net);	init_MUTEX(&priv->mutex);	net->base_addr = pid;	if ((result = register_netdev(net)) < 0) {		dvbnet->device[if_num] = NULL;		free_netdev(net);		return result;	}	printk("dvb_net: created network interface %s\n", net->name);	return if_num;}static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num){	struct net_device *net = dvbnet->device[num];	struct dvb_net_priv *priv;	if (!dvbnet->state[num])		return -EINVAL;	priv = net->priv;	if (priv->in_use)		return -EBUSY;	dvb_net_stop(net);	flush_scheduled_work();	printk("dvb_net: removed network interface %s\n", net->name);	unregister_netdev(net);	dvbnet->state[num]=0;	dvbnet->device[num] = NULL;	free_netdev(net);	return 0;}static int dvb_net_do_ioctl(struct inode *inode, struct file *file,		  unsigned int cmd, void *parg){	struct dvb_device *dvbdev = file->private_data;	struct dvb_net *dvbnet = dvbdev->priv;	if (((file->f_flags&O_ACCMODE)==O_RDONLY))		return -EPERM;	switch (cmd) {	case NET_ADD_IF:	{		struct dvb_net_if *dvbnetif = parg;		int result;		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		if (!try_module_get(dvbdev->adapter->module))			return -EPERM;		result=dvb_net_add_if(dvbnet, dvbnetif->pid, dvbnetif->feedtype);		if (result<0) {			module_put(dvbdev->adapter->module);			return result;		}		dvbnetif->if_num=result;		break;	}	case NET_GET_IF:	{		struct net_device *netdev;		struct dvb_net_priv *priv_data;		struct dvb_net_if *dvbnetif = parg;		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||		    !dvbnet->state[dvbnetif->if_num])			return -EINVAL;		netdev = dvbnet->device[dvbnetif->if_num];		priv_data = netdev->priv;		dvbnetif->pid=priv_data->pid;		dvbnetif->feedtype=priv_data->feedtype;		break;	}	case NET_REMOVE_IF:	{		int ret;		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		if ((unsigned int) parg >= DVB_NET_DEVICES_MAX)			return -EINVAL;		ret = dvb_net_remove_if(dvbnet, (unsigned int) parg);		if (!ret)			module_put(dvbdev->adapter->module);		return ret;	}	/* binary compatiblity cruft */	case __NET_ADD_IF_OLD:	{		struct __dvb_net_if_old *dvbnetif = parg;		int result;		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		if (!try_module_get(dvbdev->adapter->module))			return -EPERM;		result=dvb_net_add_if(dvbnet, dvbnetif->pid, DVB_NET_FEEDTYPE_MPE);		if (result<0) {			module_put(dvbdev->adapter->module);			return result;		}		dvbnetif->if_num=result;		break;	}	case __NET_GET_IF_OLD:	{		struct net_device *netdev;		struct dvb_net_priv *priv_data;		struct __dvb_net_if_old *dvbnetif = parg;		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||		    !dvbnet->state[dvbnetif->if_num])			return -EINVAL;		netdev = dvbnet->device[dvbnetif->if_num];		priv_data = netdev->priv;		dvbnetif->pid=priv_data->pid;		break;	}	default:		return -ENOTTY;	}	return 0;}static int dvb_net_ioctl(struct inode *inode, struct file *file,	      unsigned int cmd, unsigned long arg){	return dvb_usercopy(inode, file, cmd, arg, dvb_net_do_ioctl);}static struct file_operations dvb_net_fops = {	.owner = THIS_MODULE,	.ioctl = dvb_net_ioctl,	.open =	dvb_generic_open,	.release = dvb_generic_release,};static struct dvb_device dvbdev_net = {	.priv = NULL,	.users = 1,	.writers = 1,	.fops = &dvb_net_fops,};void dvb_net_release (struct dvb_net *dvbnet){	int i;	dvb_unregister_device(dvbnet->dvbdev);	for (i=0; i<DVB_NET_DEVICES_MAX; i++) {		if (!dvbnet->state[i])			continue;		dvb_net_remove_if(dvbnet, i);	}}EXPORT_SYMBOL(dvb_net_release);int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,		  struct dmx_demux *dmx){	int i;	dvbnet->demux = dmx;	for (i=0; i<DVB_NET_DEVICES_MAX; i++)		dvbnet->state[i] = 0;	dvb_register_device (adap, &dvbnet->dvbdev, &dvbdev_net,			     dvbnet, DVB_DEVICE_NET);	return 0;}EXPORT_SYMBOL(dvb_net_init);

⌨️ 快捷键说明

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