平台总线是一种实现设备信息与驱动方法相分离的方法,利用这种方法,我们可以写出一个更像样一点的字符设备驱动,即使用cdev作为接口,平台总线作为分离方式:

xjkeydrv_init():模块加载函数

└──platform_driver_register()将驱动对象模块注册到平台总线

        └──platform_driver.probe()探测函数,提取相应的信息

                └──xjkey_init():初始化cdev对象,创建设备文件等关于cdev接口创建的工作

                        └──cdev_init():将cdev结构与fops绑定到一起,在fops实现操作接口与控制硬件的逻辑

static struct class *cls = NULL;

static int major = 0;
static int minor = 0;
const int count = 1; #define DEVNAME "xjkey" static struct cdev *xjkeyp = NULL; static unsigned long irqflags;
static int irq; static atomic_t tv; #if 0
/{
key@26{
compatible = "xj4412,key";
interrupt-parent = <&gpx1>;
interrupts = <2 2>;
};
};
#endif static irqreturn_t handler_t(int irq, void *dev_id)
{
printk(KERN_INFO "%s : %s : %d\n", __FILE__, __func__, __LINE__);
return IRQ_HANDLED;
} //打开设备
static int xjkey_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 xjkey_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 = xjkey_open,
.release= xjkey_release,
}; static int xjkey_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 objxjkey_init
xjkeyp = cdev_alloc();
if(NULL == xjkeyp){
return -ENOMEM;
} //2. init cdev obj
cdev_init(xjkeyp, &fops); ret = alloc_chrdev_region(&devnum, minor, count, DEVNAME);
if(ret){
goto ERR_STEP;
}
major = MAJOR(devnum); //3. register cdev obj
ret = cdev_add(xjkeyp, 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(xjkeyp); //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 xjkey_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(xjkeyp);
} static int xjkey_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 xjkey_init();
} static int xjkey_remove(struct platform_device *pdev)
{
printk(KERN_INFO "%s : %s : %d - leave.\n", __FILE__, __func__, __LINE__);
xjkey_exit();
return 0;
} struct of_device_id of_tbl[] = {
{.compatible = "xj4412,key",},
{},
};
MODULE_DEVICE_TABLE(of, of_tbl); //1. alloc obj
static struct platform_driver xjkeydrv = {
.probe = xjkey_probe,
.remove = xjkey_remove, .driver = {
.name = DEVNAME,
.of_match_table = of_tbl,
},
}; //3. register obj
module_platform_driver(xjkeydrv); MODULE_LICENSE("GPL");

Linux Platform驱动模型(三) _platform+cdev的更多相关文章

  1. Linux Platform驱动模型(二) _驱动方法

    在Linux设备树语法详解和Linux Platform驱动模型(一) _设备信息中我们讨论了设备信息的写法,本文主要讨论平台总线中另外一部分-驱动方法,将试图回答下面几个问题: 如何填充platfo ...

  2. Linux Platform驱动模型(二) _驱动方法【转】

    转自:http://www.cnblogs.com/xiaojiang1025/archive/2017/02/06/6367910.html 在Linux设备树语法详解和Linux Platform ...

  3. Linux Platform驱动模型(一)-设备信息

    我在Linux字符设备驱动框架一文中简单介绍了Linux字符设备编程模型,在那个模型中,只要应用程序open()了相应的设备文件,就可以使用ioctl通过驱动程序来控制我们的硬件,这种模型直观,但是从 ...

  4. Linux Platform驱动模型(一) _设备信息

    我在Linux字符设备驱动框架一文中简单介绍了Linux字符设备编程模型,在那个模型中,只要应用程序open()了相应的设备文件,就可以使用ioctl通过驱动程序来控制我们的硬件,这种模型直观,但是从 ...

  5. 探究linux设备驱动模型之——platform虚拟总线(一)

    说在前面的话 :      设备驱动模型系列的文章主要依据的内核版本是2.6.32的,因为我装的Linux系统差不多就是这个版本的(实际上我用的fedora 14的内核版本是2.6.35.13的.) ...

  6. Linux设备驱动模型之platform(平台)总线详解

    /********************************************************/ 内核版本:2.6.35.7 运行平台:三星s5pv210 /*********** ...

  7. linux设备驱动模型之Kobject、kobj_type、kset【转】

    本文转载自:http://blog.csdn.net/fengyuwuzu0519/article/details/74838165 版权声明:本文为博主原创文章,转载请注明http://blog.c ...

  8. Linux设备驱动模型底层架构及组织方式

    1.什么是设备驱动模型? 设备驱动模型,说实话这个概念真的不好解释,他是一个比较抽象的概念,我在网上也是没有找到关于设备驱动模型的一个定义,那么今天就我所学.所了解 到的,我对设备驱动模型的一个理解: ...

  9. Linux 设备驱动模型

    Linux系统将设备和驱动归一到设备驱动模型中了来管理 设备驱动程序功能: 1,对硬件设备初始化和释放 2,对设备进行管理,包括实参设置,以及提供对设备的统一操作接口 3,读取应用程序传递给设备文件的 ...

随机推荐

  1. getOutputStream() has already been called for this response解释以及解决方法

    异常:getOutputStream() has already been called for this response 的解决方法 今天在第一次接触使用“验证码”功能时,在执行时出现了异常信息: ...

  2. 在iOS端如何使用Charles用作http调试

    转:http://blog.csdn.net/messageloop3/article/details/9966727 在iOS端如何使用Charles用作http调试 After noticing ...

  3. SharePoint Online 自定义Modern UI表单

    前言 用过SharePoint Online 版本的朋友们,应该很熟悉SharePoint为我们带来的Modern UI,而这个页面的订制,也跟原来的表单定制方式不同了,而且更加简单了. 而且,试了一 ...

  4. .net里Release的pdb文件有什么用 是否可以删除

    程序数据库 (PDB) 文件保存着调试和项目状态信息,使用这些信息可以对程序的调试配置进行增量链接. 在使用 /debug 生成时,会创建一个 PDB 文件. 可以使用 /debug:full 或 / ...

  5. Mysql高效插入/更新数据

    从tushare抓取到的财务数据,最开始只是想存下来,用的办法想简单点,是:插入--报错-update 但发现这个方法太蠢,异常会导致大量无效连接,改为: for idx,row in d2.iter ...

  6. 【T02】理解子网和CIDR的概念

    1.IP地址分为5类,A.B.C.D.E,它们的前缀分别是: A:0 网络个数2^7,主机个数2^24,大概1千6百万 B:10 网络个数2^14,大概1万6千,主机个数2^16,大概6万5千 C:1 ...

  7. Facebook在代码里下毒,百度身受重伤。。。

    白首相知犹按剑     前两天看到有朋友分享说,WordPress停用了react.今天,在逛知乎时看到了另一个问题别细看这图,我赌你看不懂... 嗯...用人话来说就是百度内部要求他们的程序猿不要再 ...

  8. Android属性allowBackup安全风险浅析

    1.allowBackup安全风险描述 Android API Level 8及其以上Android系统提供了为应用程序数据的备份和恢复功能,此功能的开关决定于该应用程序中AndroidManifes ...

  9. SpringBoot集成Redis分布式锁以及Redis缓存

    https://blog.csdn.net/qq_26525215/article/details/79182687 集成Redis 首先在pom.xml中加入需要的redis依赖和缓存依赖 < ...

  10. 屌丝也用按位与(&),按位或(|) (二)

    上篇讲到了,用按位操作进行配置,下边来讲一个大神也在用的例子 linux的权限系统 我们知道一个文件,如果是777,那么是最高的权限,那这个七是咋构成的,我会告诉你是 4+2+1么? 我会告诉你,是1 ...