平台总线是一种实现设备信息与驱动方法相分离的方法,利用这种方法,我们可以写出一个更像样一点的字符设备驱动,即使用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. NSArray与NSString、NSData,NSDictionary与NSString、NSData 相互转化

    NSArray *array = @[ @1, @2, @3, @4, @5, @3 ]; // 1. NSArray与NSData相互转化 // NSArray to NSData NSError ...

  2. Java全栈程序员之02:Ubuntu下Java环境安装、配置、测试

    在上文讲完之后,我们手里的ubuntu只能算是一个上网机,什么也干不了,本篇我们将折腾它为开发机. 这里,我们这里假定你对linux体系是初级选手,所以本篇会讲的啰嗦一点,高手就出门左转吧. 1.安装 ...

  3. C++中extern “C”含义及extern、static关键字浅析

    https://blog.csdn.net/bzhxuexi/article/details/31782445 1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C ...

  4. CDH:cdh5环境搭建

    安装环境三台centos7 vmw: cdh- 192.168.0.141 [主节点] cdh- 192.168.0.142 [从节点] cdh- 192.168.0.143 [从节点] 1)[各节点 ...

  5. 虚拟机下CentOS7开启SSH连接

    在虚拟机(Vmware Workstation)下,安装了CentOS7,现在想通过SSH工具连接虚拟机中的CentOS7 1.  首先,要确保CentOS7安装了  openssh-server,在 ...

  6. CentOS 7安装nVIDIA显卡驱动程序

    1. 到http://www.geforce.cn/drivers,根据显卡的型号,选择下载相应的驱动程序,一般是.run文件: 2. 运行下载的.run文件,会提示X Server正在运行,不能安装 ...

  7. C# System.Collections.SortedList

    using System; using System.Collections; public class SamplesSortedList { public static void Main() { ...

  8. MySql之存储过程的使用

    一:创建存储过程 1:简单存储过程 CREATE PROCEDURE 存储过程名() BEGIN SQL操作 END; 2:使用参数的存储过程 CREATE PROCEDURE 存储过程名(IN in ...

  9. C#中Post请求的两种方式发送参数链和Body的

    POST请求 有两种方式 一种是组装key=value这种参数对的方式 一种是直接把一个字符串发送过去 作为body的方式 我们在postman中可以看到 sfdsafd sdfsdfds publi ...

  10. Dive into Python

    写这篇文章的原因完全是为了督促自己每天晚上看完两章<Dive Into Python>这本书,因此,很多内容都是摘抄自原书的翻译版或者是自己瞎想,于是就顺带着记录了下来.此前已经看完前两章 ...