字符设备驱动第十九课---platform3
来源:互联网 发布:rsync指定ssh端口 编辑:程序博客网 时间:2024/06/06 13:11
概述
设备信息来自于设备树的platform驱动
范例
#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/of.h>#include <linux/of_irq.h>#include <linux/platform_device.h>#include <linux/interrupt.h>#include <linux/cdev.h>#include <linux/fs.h>#include <linux/errno.h>#include <asm/current.h>#include <linux/sched.h>#include <linux/uaccess.h>#include <linux/poll.h>#include <asm/atomic.h>#include <linux/mutex.h>#include <linux/wait.h>#include <linux/device.h>static struct class *cls = NULL;static int major = 0;static int minor = 0;const int count = 1;#define DEVNAME "fskey"static struct cdev *fskeyp = NULL;static unsigned long irqflags;static int irq;static atomic_t tv;#if 0/{ key@26{ compatible = "fs4412,key"; interrupt-parent = <&gpx1>; interrupts = <2 2>; };};#endifstatic irqreturn_t handler_t(int irq, void *dev_id){ printk(KERN_INFO "%s : %s : %d\n", __FILE__, __func__, __LINE__); return IRQ_HANDLED;}//打开设备static int fskey_open(struct inode *inode, struct file *filp){ //get major and minor from inode printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n", imajor(inode), iminor(inode), __FILE__, __func__, __LINE__); if(!atomic_dec_and_test(&tv)){ atomic_inc(&tv); return -EBUSY; } return request_irq(irq, handler_t, irqflags, DEVNAME, NULL);}//关闭设备static int fskey_release(struct inode *inode, struct file *filp){ //get major and minor from irqflagsinode printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n", imajor(inode), iminor(inode), __FILE__, __func__, __LINE__); free_irq(irq, NULL); atomic_inc(&tv); return 0;}static struct file_operations fops = { .owner = THIS_MODULE, .open = fskey_open, .release= fskey_release,};static int fskey_init(void){ dev_t devnum; int ret, i; struct device *devp = NULL; //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n", current->comm, current->pid, __FILE__, __func__, __LINE__); //1. alloc cdev objfskey_init fskeyp = cdev_alloc(); if(NULL == fskeyp){ return -ENOMEM; } //2. init cdev obj cdev_init(fskeyp, &fops); ret = alloc_chrdev_region(&devnum, minor, count, DEVNAME); if(ret){ goto ERR_STEP; } major = MAJOR(devnum); //3. register cdev obj ret = cdev_add(fskeyp, devnum, count); if(ret){ goto ERR_STEP1; } cls = class_create(THIS_MODULE, DEVNAME); if(IS_ERR(cls)){ ret = PTR_ERR(cls); goto ERR_STEP1; } for(i = minor; i < (count+minor); i++){ devp = device_create(cls, NULL, MKDEV(major, i), NULL, "%s%d", DEVNAME, i); if(IS_ERR(devp)){ ret = PTR_ERR(devp); goto ERR_STEP2; } } // init atomic_t atomic_set(&tv, 1); //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - ok.\n", current->comm, current->pid, __FILE__, __func__, __LINE__); return 0;ERR_STEP2: for(--i; i >= minor; i--){ device_destroy(cls, MKDEV(major, i)); } class_destroy(cls);ERR_STEP1: unregister_chrdev_region(devnum, count);ERR_STEP: cdev_del(fskeyp); //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - fail.\n", current->comm, current->pid, __FILE__, __func__, __LINE__); return ret;}static void fskey_exit(void){ int i; //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - leave.\n", current->comm, current->pid, __FILE__, __func__, __LINE__); for(i=minor; i < (count+minor); i++){ device_destroy(cls, MKDEV(major, i)); } class_destroy(cls); unregister_chrdev_region(MKDEV(major, minor), count); cdev_del(fskeyp);}static int fskey_probe(struct platform_device *pdev){ struct resource *irq_res; irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if(irq_res){ irq = irq_res->start; irqflags = irq_res->flags & IRQF_TRIGGER_MASK; }else{ printk(KERN_INFO "No 0 irq\n"); return -EINVAL; } return fskey_init();}static int fskey_remove(struct platform_device *pdev){ printk(KERN_INFO "%s : %s : %d - leave.\n", __FILE__, __func__, __LINE__); fskey_exit(); return 0;}#ifdef CONFIG_OFstruct of_device_id of_tbl[] = {//设备树中设备ID匹配表 {.compatible = "fs4412,key",}, {},//为空表结束符};MODULE_DEVICE_TABLE(of, of_tbl);#endif//1. alloc objstatic struct platform_driver fskeydrv = { .probe = fskey_probe, .remove = fskey_remove, .driver = { .name = DEVNAME,#ifdef CONFIG_OF .of_match_table = of_tbl,//因为用的设备信息不是来自于C代码中, //而是来自于设备树,所以要定义此匹配表#endif },};//3. register objmodule_platform_driver(fskeydrv);MODULE_LICENSE("GPL");MODULE_AUTHOR("Farsight");MODULE_DESCRIPTION("Demo for kernel module");
0 0
- 字符设备驱动第十九课---platform3
- 字符设备驱动第十一课----设备树
- 字符设备驱动第三课---私有数据
- 字符设备驱动第五课----读写
- 字符设备驱动第六课---ioctl
- 字符设备驱动第八课------读写锁
- 字符设备驱动第九课---等待队列
- 字符设备驱动第十二课-----中断
- 字符设备驱动第十三课---内存分配
- 字符设备驱动第十四课----IO读写
- 字符设备驱动第十五课-----LED点灯
- 字符设备驱动第八课----自旋锁
- 字符设备驱动第八课----互斥锁
- 字符设备驱动第八课----信号量
- 字符设备驱动第十七课----platform
- 字符设备驱动第十八课---platform2
- 字符设备驱动--- 设备操作
- 字符设备驱动更新
- 经验人生
- android界面activity的生命周期
- thinkphp volist循环数组的key名
- 下拉多选
- Linux常用命令
- 字符设备驱动第十九课---platform3
- 20161210计算机科学导论04_磁盘
- 折半查找算法
- Android 5.x常用控件(一)
- IM基础概念和原理
- ORACLE SQL 语句
- 行人检测综述
- php+nginx做下载服务器配置
- Using Dagger 2 for dependency injection in Android - Tutorial