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

📄 demo.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
字号:
/* * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * Copyright (C) 2007, 2010 fengGuojin(fgjnew@163.com) */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/moduleparam.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/slab.h>	#include <linux/fs.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/seq_file.h>#include <linux/cdev.h>#include <linux/version.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/ctype.h>#include <linux/sched.h>#include <linux/kernel.h> /* printk() */#include <linux/slab.h> /* kmalloc() */#include <linux/types.h>  /* size_t */#include <linux/interrupt.h> /* mark_bh */#include <linux/in.h>#include <linux/netdevice.h>   /* struct device, and other headers */#include <linux/etherdevice.h> /* eth_type_trans */#include <linux/ip.h>          /* struct iphdr */#include <linux/tcp.h>         /* struct tcphdr */#include <linux/skbuff.h>#include <linux/in6.h>#include <asm/checksum.h>#include "demo.h"MODULE_AUTHOR("fgj");MODULE_LICENSE("Dual BSD/GPL");int demo_open(struct net_device *dev){    memcpy(dev->dev_addr, "\0ED000", ETH_ALEN);                         netif_start_queue(dev);    return 0;}int demo_release(struct net_device *dev){    netif_stop_queue(dev);              return 0;}int demo_config(struct net_device *dev, struct ifmap *map){    if (dev->flags & IFF_UP)         return -EBUSY;    /* change the io_base addr */    if (map->base_addr != dev->base_addr) {        printk(KERN_WARNING "demo: Can't change I/O address\n");        return -EOPNOTSUPP;    }    /* can change the irq */    if (map->irq != dev->irq) {        dev->irq = map->irq;            }    return 0;}/* * demo_rx,recieves a network packet and put the packet into TCP/IP up * layer,netif_rx() is the kernel API to do such thing. The recieving * procedure must alloc the sk_buff structure to store the data, * and the sk_buff will be freed in the up layer. */void demo_rx(struct net_device *dev, int len, unsigned char *buf){    struct sk_buff *skb;    struct demo_priv *priv = (struct demo_priv *) dev->priv;    skb = dev_alloc_skb(len+2);    if (!skb) {        printk("demo_rx can not allocate more memory to store the packet. drop the packet\n");        priv->stats.rx_dropped++;        return;    }    skb_reserve(skb, 2);    memcpy(skb_put(skb, len), buf, len);    skb->dev = dev;    skb->protocol = eth_type_trans(skb, dev);    /* We need not check the checksum */    skb->ip_summed = CHECKSUM_UNNECESSARY;     priv->stats.rx_packets++;                                  netif_rx(skb);    return;}/* * pseudo network hareware transmit,it just put the data into the  * ed_tx device. */void demo_hw_tx(char *buf, int len, struct net_device *dev){    struct demo_priv *priv;       /* check the ip packet length,it must more then 34 octets */    if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {        printk("Bad packet! It's size is less then 34!\n");                return;    }    	printk("%s\n",buf);        /* record the transmitted packet status */    priv = (struct demo_priv *) dev->priv;    priv->stats.tx_packets++;    priv->stats.rx_bytes += len;        /* remember to free the sk_buffer allocated in upper layer. */    dev_kfree_skb(priv->skb);}/* * Transmit the packet,called by the kernel when there is an * application wants to transmit a packet. */int demo_tx(struct sk_buff *skb, struct net_device *dev){    int len;    char *data;    struct demo_priv *priv = (struct demo_priv *) dev->priv;    len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;    data = skb->data;    /* stamp the time stamp */    dev->trans_start = jiffies;    /* remember the skb and free it in demo_hw_tx */    priv->skb = skb;        /* pseudo transmit the packet,hehe */    demo_hw_tx(data, len, dev);    return 0; }/* * Deal with a transmit timeout. */void demo_tx_timeout (struct net_device *dev){    struct demo_priv *priv = (struct demo_priv *) dev->priv;    priv->stats.tx_errors++;    netif_wake_queue(dev);    return;}/* * When we need some ioctls. */int demo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){     return 0;}/* * ifconfig to get the packet transmitting status. */struct net_device_stats *demo_stats(struct net_device *dev){    struct demo_priv *priv = (struct demo_priv *) dev->priv;    return &priv->stats;}/* * TCP/IP handshake will call this function, if it need. */int demo_change_mtu(struct net_device *dev, int new_mtu){    unsigned long flags;    spinlock_t *lock = &((struct demo_priv *) dev->priv)->lock;        /* en, the mtu CANNOT LESS THEN 68 OR MORE THEN 1500. */    if (new_mtu < 68)        return -EINVAL;       spin_lock_irqsave(lock, flags);    dev->mtu = new_mtu;    spin_unlock_irqrestore(lock, flags);    return 0; }int demo_header(struct sk_buff *skb,                 struct net_device *dev,                 unsigned short type,                 void *daddr,                 void *saddr,                 unsigned int len){    struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);    eth->h_proto = htons(type);    memcpy(eth->h_source,saddr? saddr : dev->dev_addr,dev->addr_len);    memcpy(eth->h_dest,   daddr? daddr : dev->dev_addr, dev->addr_len);    return (dev->hard_header_len);}int demo_rebuild_header(struct sk_buff *skb){    struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);    struct net_device *dev = skb->dev;    memcpy(eth->h_source, dev->dev_addr ,dev->addr_len);    memcpy(eth->h_dest,   dev->dev_addr , dev->addr_len);    return 0;}void demo_init(struct net_device *dev){	struct demo_priv *priv;	ether_setup(dev); /* assign some of the fields */	dev->open            = demo_open;	dev->stop            = demo_release;	dev->set_config      = demo_config;	dev->hard_start_xmit = demo_tx;	dev->do_ioctl        = demo_ioctl;	dev->get_stats       = demo_stats;	dev->change_mtu      = demo_change_mtu;  	dev->rebuild_header  = demo_rebuild_header;	dev->hard_header     = demo_header;	dev->tx_timeout      = demo_tx_timeout;	/* keep the default flags, just add NOARP */	dev->flags           |= IFF_NOARP;	dev->features        |= NETIF_F_NO_CSUM;	dev->hard_header_cache = NULL;      /* Disable caching */	/*	 * Then, initialize the priv field. This encloses the statistics	 * and a few private fields.	 */	priv = netdev_priv(dev);	memset(priv, 0, sizeof(struct demo_priv));	spin_lock_init(&priv->lock);}struct net_device *demo_devs;void demo_cleanup(void){	if (demo_devs) 	{		unregister_netdev(demo_devs);		free_netdev(demo_devs);	}	return;}int demo_init_module(void){	int result,ret = -ENOMEM;	/* Allocate the devices */	demo_devs=alloc_netdev(sizeof(struct demo_priv), "fgj%d",			demo_init);	if (demo_devs == NULL)		goto out;	ret = -ENODEV;	if ((result = register_netdev(demo_devs)))		printk("demo: error %i registering device \"%s\"\n",result, demo_devs->name);	else		ret = 0;   out:	if (ret) 		demo_cleanup();	return ret;}module_init(demo_init_module);module_exit(demo_cleanup);

⌨️ 快捷键说明

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