1、总线设备驱动模型

Linux 总线设备驱动模型_第1张图片

2、实现一个平台总线设备驱动(也称虚拟总线)

1)demo_dev

#include 
#include 
#include 
#include 
#include 
#include 
#include 


/* 分配/设置/注册一个platform_device */

static struct resource demo_resource[] = {
    [0] = {
        .start = 0xffffffee,
        .end   = 0xffffffff,
        .flags = IORESOURCE_MEM,
    },
    [1] = {
        .start = 1,
        .end   = 1,
        .flags = IORESOURCE_IRQ,
    }

};
static void demo_release(struct device * dev)
{
}
static struct platform_device demo_dev = {
    .name         = "mydemo",
    .id       = -1,
    .num_resources    = ARRAY_SIZE(demo_resource),
    .resource     = demo_resource,
    .dev = { 
    	.release = demo_release, 
	},
};
static int demo_dev_init(void)
{
	printk("[%s %d]\n",__func__,__LINE__);
	platform_device_register(&demo_dev);
	return 0;
}

static void demo_dev_exit(void)
{
	printk("[%s %d]\n",__func__,__LINE__);
	platform_device_unregister(&demo_dev);
}
module_init(demo_dev_init);
module_exit(demo_dev_exit);

MODULE_LICENSE("GPL");

2)demo_drv

/* 分配/设置/注册一个platform_driver */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
static int major;
static struct class *cls;

static int demo_open(struct inode *inode, struct file *file)
{
	printk("[%s %d],open!!!\n",__func__,__LINE__);
	return 0;	
}

static ssize_t demo_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
	int val = 0;

	printk("[%s %d],write!!!\n",__func__,__LINE__);
	copy_from_user(&val, buf, count); // 从用户空间到内核空间;

	printk("[%s %d],write value = %d\n",__func__,__LINE__,val);
	
	return 0;
}

static struct file_operations demo_fops = {
    .owner  =   THIS_MODULE,    // 这是一个宏,推向编译模块时自动创建的__this_module变量 
    .open   =   demo_open,     
	.write	=	demo_write,	   
};

static int demo_probe(struct platform_device *pdev)
{
	struct resource		*res;
    printk("into [%s %d]\n",__func__,__LINE__);
	/* 获取platform_device的资源 */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);//这里获取到的地址是物理地址,需要使用ioremap映射
	printk("[%s %d] io res->start = %x,res->end = %x\n",__func__,__LINE__,res->start,res->end);

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	printk("[%s %d] irq res->start = %d\n",__func__,__LINE__,res->start);

	/* 注册字符设备驱动程序 */
	major = register_chrdev(0, "mydemo", &demo_fops);

	cls = class_create(THIS_MODULE, "mydemo");

	device_create(cls, NULL, MKDEV(major, 0), NULL, "demo"); /* /dev/demo */
	
	return 0;
}

static int demo_remove(struct platform_device *pdev)
{
	/* 卸载字符设备驱动程序 */
	printk("[%s %d] remove demo\n",__func__,__LINE__);
	device_destroy(cls, MKDEV(major, 0));
	class_destroy(cls);
	unregister_chrdev(major, "mydemo");
	return 0;
}

struct platform_driver demo_drv = {
	.probe		= demo_probe,
	.remove		= demo_remove,
	.driver		= {
		.name	= "mydemo",
	}
};

static int demo_drv_init(void)
{
	platform_driver_register(&demo_drv);
	return 0;
}

static void demo_drv_exit(void)
{
	platform_driver_unregister(&demo_drv);
}

module_init(demo_drv_init);
module_exit(demo_drv_exit);

MODULE_LICENSE("GPL");

3)Makefile

KERN_DIR = /usr/src/linux-3.10.62
obj-m	+= demo_drv.o
obj-m	+= demo_dev.o
all:
	make -C $(KERN_DIR) M=`pwd` modules 

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

3、装载设备和驱动模块

Linux 总线设备驱动模型_第2张图片

4、查看设备并卸载模块

Linux 总线设备驱动模型_第3张图片

5、编写测试应用程序demo_test.c

#include 
#include 
#include 
#include 
int main(int argc, char **argv)
{
	int fd;
	int val = 0;
	fd = open("/dev/demo", O_RDWR);
	if (fd < 0)
	{
		printf("can't open!\n");
	}
	if (argc != 2)
	{
		return 0;
	}
	val = atoi(argv[1]);	
	write(fd, &val, 4);
	return 0;
}

查看执行结果:

Linux 总线设备驱动模型_第4张图片