?? dvb_net.c
字號:
dvb_net_feed_stop(dev); priv->rx_mode = RX_MODE_UNI; 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); } } dvb_net_feed_start(dev); }static void dvb_net_set_multicast_list (struct net_device *dev){ struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; schedule_work(&priv->set_multicast_list_wq);}static int dvb_net_set_config(struct net_device *dev, struct ifmap *map){ if (netif_running(dev)) return -EBUSY; return 0;}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 = (struct dvb_net_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 = (struct dvb_net_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 = (struct dvb_net_priv*) dev->priv; priv->in_use--; dvb_net_feed_stop(dev); return 0;}static struct net_device_stats * dvb_net_get_stats(struct net_device *dev){ return &((struct dvb_net_priv*) dev->priv)->stats;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static int dvb_net_init_dev (struct net_device *dev)#elsestatic void dvb_net_setup(struct net_device *dev)#endif{ 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_config = dvb_net_set_config; dev->set_mac_address = dvb_net_set_mac; dev->mtu = 4096; dev->mc_count = 0; dev->hard_header_cache = NULL; dev->flags |= IFF_NOARP;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) return 0;#endif}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;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid){ struct net_device *net; struct dmx_demux *demux; struct dvb_net_priv *priv; int result; int if_num; if ((if_num = get_if(dvbnet)) < 0) return -EINVAL; net = &dvbnet->device[if_num]; demux = dvbnet->demux; memset(net, 0, sizeof(struct net_device)); memcpy(net->name, "dvb0_0", 7); net->name[3] = dvbnet->dvbdev->adapter->num + '0'; net->name[5] = if_num + '0'; net->addr_len = 6; memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6); net->next = NULL; net->init = dvb_net_init_dev; if (!(net->priv = kmalloc(sizeof(struct dvb_net_priv), GFP_KERNEL))) return -ENOMEM; priv = net->priv; memset(priv, 0, sizeof(struct dvb_net_priv)); priv->demux = demux; priv->pid = pid; priv->rx_mode = RX_MODE_UNI; INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net); INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net); net->base_addr = pid; if ((result = register_netdev(net)) < 0) { return result; } return if_num;}#elsestatic int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid){ struct net_device *net; struct dvb_net_priv *priv; int result; int if_num; 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; sprintf(net->name, "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; INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net); INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net); net->base_addr = pid; if ((result = register_netdev(net)) < 0) { dvbnet->device[if_num] = NULL; free_netdev(net); return result; } return if_num;}#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static int dvb_net_remove_if(struct dvb_net *dvbnet, int num){ struct dvb_net_priv *priv = dvbnet->device[num].priv; if (!dvbnet->state[num]) return -EINVAL; if (priv->in_use) return -EBUSY; dvb_net_stop(&dvbnet->device[num]); flush_scheduled_work(); kfree(priv); unregister_netdev(&dvbnet->device[num]); dvbnet->state[num]=0; return 0;}#elsestatic int dvb_net_remove_if(struct dvb_net *dvbnet, int num){ struct net_device *net = dvbnet->device[num]; struct dvb_net_priv *priv = net->priv; if (!dvbnet->state[num]) return -EINVAL; if (priv->in_use) return -EBUSY; dvb_net_stop(net); flush_scheduled_work(); unregister_netdev(net); dvbnet->state[num]=0; dvbnet->device[num] = NULL; free_netdev(net); return 0;}#endifstatic int dvb_net_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg){ struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct dvb_net *dvbnet = (struct dvb_net *) dvbdev->priv; if (((file->f_flags&O_ACCMODE)==O_RDONLY)) return -EPERM; switch (cmd) { case NET_ADD_IF: { struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg; int result; if (!capable(CAP_SYS_ADMIN)) return -EPERM; result=dvb_net_add_if(dvbnet, dvbnetif->pid); if (result<0) 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=(struct dvb_net_if *)parg; if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || !dvbnet->state[dvbnetif->if_num]) return -EINVAL;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) netdev = &dvbnet->device[dvbnetif->if_num];#else netdev = dvbnet->device[dvbnetif->if_num];#endif priv_data=(struct dvb_net_priv*)netdev->priv; dvbnetif->pid=priv_data->pid; break; } case NET_REMOVE_IF: if (!capable(CAP_SYS_ADMIN)) return -EPERM; return dvb_net_remove_if(dvbnet, (int) (long) parg); 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, .read = 0, .write = 0, .ioctl = dvb_net_ioctl, .open = dvb_generic_open, .release = dvb_generic_release, .poll = 0,};static struct dvb_device dvbdev_net = { .priv = 0, .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); }}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;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -