📄 dvb_net.c
字号:
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 + -