平台总线是一种实现设备信息与驱动方法相分离的方法,利用这种方法,我们可以写出一个更像样一点的字符设备驱动,即使用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. AngularJS中转换响应内容

    从远程API获取到的响应内容,通常是json格式的,有时候需要对获取到的内容进行转换,比如去除某些不需要的字段,给字段取别名,等等. 本篇就来体验在AngualrJS中如何实现. 在主页面,还是从co ...

  2. ASP.NET Web API中通过URI显示实体中的部分字段

    有时候我们可能不想显示某个实体中的所有字段.比如客户端发出如下请求: locaohost:43321/api/groups/1/items?fields=idlocaohost:43321/api/g ...

  3. JSTL标签 使用总结,foreach

    最近开发一个网站,经常使用JSTL,这种语法与以前的不同,开始用着非常吃力,今天总结一下,供大家参考. 一.前言 JSTL全名为JavaServer Pages Standard Tag Librar ...

  4. maven本地库与私服比对,查找缺失jar包

    项目中遇到的一个问题,因为要切换开发环境(新环境不能联网,且私服上的jar包信息不全),需要将本地仓库(项目使用本地仓库能够正常编译)中有而私服上没有的jar包整理出来(名称.版本号等),提供给第三方 ...

  5. 查看修改添加环境变量的工具——Rapid Environment Editor

    工欲善其事,必先利其器! 特别是公司或者有其他限制的时候,更需要一个比较简单.实用.强大的工具了! 原来的公司都是小公司,给电脑安装系统.软件等都是自己直接上手,现在在一个大点的公司了,电脑运维有单独 ...

  6. 微信小程序--兼容

    小程序的功能不断的增加,但是旧版本的微信客户端并不支持新功能,所以在使用这些新能力的时候需要做兼容. 文档会在组件,API等页面描述中带上各个功能所支持的版本号. 可以通过 wx.getSystemI ...

  7. RelativeLayout 布局参数

    今天调布局的时候 想把界面做成横屏竖屏都可以的 突然发现之前理解的android:布局参数都是有问题的 今天贴出来 下次自己也记得 以下大部为用在RelativeLayout中的一些参数: andro ...

  8. 20款最好的jQuery文件上传插件

    当它是关于开发网络应用程序和网页的时候,文件上传功能的重要性是不容忽视的.一个文件上传功能可以让你上传所有类型的文件在网站上,包括视频,图像,文件和更多.创建一个文件上传功能,对你的网站是不是很难,有 ...

  9. NodeJS的url验证库模块url-valid

    这是我10月份做的项目其中的一个部件,主要用于url检验的. 我们知道Javascript做url检验,通常是使用正则表达式来判定,其格式是否正确,例如: /^https?:\/\//.test(ur ...

  10. Linux初始化init系统-Sysvinit、Upstart、Systemd

    首先了解以下Ubuntu运行级别(init)对应工具的变化历史: 1.Ubuntu 6.10及以前版本使用Sysvinit. 2.Ubuntu 14.10及以前版本使用Upstart但是还留着Sysv ...