结合之前对Linux内核的platform总线与input子系统的分析 ,本文将编写基于platform总线和input子系统的Button设备的实例代码并对其进行分析。

platform总线的分析,详见Linux platform驱动模型。

input子系统的分析,详见Linux字符设备驱动框架(四):Linux内核的input子系统。

硬件接口:

  CPU:s5pv210;

  Button的GPIO:GPIO_H0_2,EINT2;

  LED的工作方式:按键弹起,低电平;按键按下,高电平。

1. device

在/kernel/arch/arm/mach-s5pv210/include/mach目录下,建立一个buttons_gpio.h文件,并填充如下内容。

#ifndef __ASM_ARCH_BUTTONSGPIO_H
#define __ASM_ARCH_BUTTONSGPIO_H "buttons-gpio.h"//定义一个Button设备的数据结构
struct s5pv210_button_platdata
{char            *name;unsigned int    gpio;unsigned int    irqnum;unsigned int    flags;
};#endif

在/kernel/arch/arm/mach-s5pv210/mach-x210.c下,添加如下内容,并添加对buttons_gpio.h的包含。

/*Buttons*/static struct s5pv210_button_platdata s5pv210_button_pdata = {.name        = "button1",.gpio        = S5PV210_GPH0(2),.irqnum      = IRQ_EINT2,//中断号.flags       = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,//上升沿触发+下降沿触发
};static struct platform_device s5pv210_button = {.name   = "s5pv210_button",.id     = 1,.dev    = {.platform_data  = &s5pv210_button_pdata,},
};

将LED设备信息集成至smdkc110_devices,内核初始化时smdkc110_devices中的设备将被注册进内核。

static struct platform_device *smdkc110_devices[] __initdata =
{......&s5pv210_button,};

2. driver

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/input.h> #include <mach/buttons_gpio.h>
#include <mach/hardware.h>
#include <mach/regs-gpio.h>
#include <mach/irqs.h>
#include <linux/interrupt.h>static struct s5pv210_button_platdata *pdata;
static struct input_dev *button_dev = NULL;static irqreturn_t button_interrupt(int irq, void *dummy)
{ int flag;s3c_gpio_cfgpin(pdata->gpio, S3C_GPIO_SFN(0x0)); //设置GPIO为input模式flag = gpio_get_value(pdata->gpio);              //读取GPIO的值s3c_gpio_cfgpin(pdata->gpio, S3C_GPIO_SFN(0x0f));//设置GPIO为eint2模式
input_report_key(button_dev, KEY_LEFT, !flag);   //上报事件input_sync(button_dev);                          //同步事件return IRQ_HANDLED;
}static int s5pv210_button_remove(struct platform_device *dev)
{input_free_device(button_dev);            //释放button_dev内存free_irq(pdata->irqnum, button_interrupt);//释放中断资源gpio_free(pdata->gpio);                   //释放GPIOreturn 0;
}static int s5pv210_button_probe(struct platform_device *dev)
{int ret;pdata = dev->dev.platform_data;/*****************************申请资源******************************///申请GPIOret = gpio_request(pdata->gpio, pdata->name);if (ret) {printk(KERN_ERR "gpio_request failed, ret = %d.\n", ret);return -EBUSY;} //申请IRQif (request_irq(pdata->irqnum, button_interrupt, pdata->flags, pdata->name, NULL)) { printk(KERN_ERR "key-s5pv210.c: Can't allocate irq %d\n", pdata->irqnum);ret = -EBUSY;goto ERR_STER0;}/************************初始化GPIO资源*************************/s3c_gpio_setpull(pdata->gpio, S3C_GPIO_PULL_UP); //设置GPIO为上拉模式s3c_gpio_cfgpin(pdata->gpio, S3C_GPIO_SFN(0x0f));//设置GPIO为eint模式/*******************************创建接口*******************************///申请button_dev内存空间button_dev = input_allocate_device();if(!button_dev){ret = -ENOMEM;goto ERR_STER1;}//初始化button_devset_bit(EV_KEY, button_dev->evbit);    //支持EV_KEY事件set_bit(KEY_LEFT, button_dev->keybit); //支持KEY_LEFT子事件//注册button_devif(input_register_device(button_dev) != 0){printk("s5pv210-button input register device fail!!\n");ret = -ENODEV;goto ERR_STER2;}return 0;/****************************倒映式错误处理****************************/
ERR_STER2:input_free_device(button_dev);ERR_STER1:free_irq(pdata->irqnum, button_interrupt);ERR_STER0:gpio_free(pdata->gpio);return ret;
}//定义并初始化驱动信息
static struct platform_driver s5pv210_button_driver =
{.probe        = s5pv210_button_probe,.remove        = s5pv210_button_remove,.driver        = {.name    = "s5pv210_button",.owner    = THIS_MODULE,},
};//注册驱动
static int __init s5pv210_button_init(void)
{return platform_driver_register(&s5pv210_button_driver);
}//注销驱动
static void __exit s5pv210_button_exit(void)
{platform_driver_unregister(&s5pv210_button_driver);
}module_init(s5pv210_button_init);
module_exit(s5pv210_button_exit);MODULE_AUTHOR("Lin");
MODULE_DESCRIPTION("S5PV210 BUTTON driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:s5pv210_button");

3. 测试

编写一个简易的应用程序,来测试上述驱动程序。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <string.h>#define X210_KEY            "/dev/input/event1"int main(void)
{int fd = -1, ret = -1;struct input_event ev;//打开设备文件fd = open(X210_KEY, O_RDONLY);if (fd < 0){perror("open");return -1;}while (1){//读取一个event事件包memset(&ev, 0, sizeof(struct input_event));ret = read(fd, &ev, sizeof(struct input_event));if (ret != sizeof(struct input_event)){perror("read");close(fd);return -1;}//解析event包printf("-------------------------\n");printf("type: %hd\n", ev.type);printf("code: %hd\n", ev.code);printf("value: %d\n", ev.value);printf("\n");}//关闭设备
    close(fd);return 0;
}

装载驱动模块后,在Linux终端运行该应用程序。在一次按键按下并弹起的过程中,终端中将打印出如下的信息,表明驱动程序工作正常。

-------------------------//按键按下
type: 1
code: 105
value: 1-------------------------//同步事件
type: 0
code: 0
value: 0-------------------------//按键弹起
type: 1
code: 105
value: 0-------------------------//同步事件
type: 0
code: 0
value: 0

转载于:https://www.cnblogs.com/linfeng-learning/p/9468018.html

驱动程序实例(四):按键驱动程序(platform + input子系统 + 外部中断方式)相关推荐

  1. CC2530学习(四)休眠模式配置及外部中断/睡眠时钟唤醒

    文章目录 一.硬件连接 二.寄存器描述(外部中断) (一).睡眠模式设置 (二).电源模式控制设置 三.示例代码(外部中断) 四.实验现象(外部中断) 五.寄存器描述(睡眠时钟中断) (一).睡眠模式 ...

  2. platform框架--Linux MISC杂项框架--Linux INPUT子系统框架--串行集成电路总线I2C设备驱动框架--串行外设接口SPI 设备驱动框架---通用异步收发器UART驱动框架

    platform框架 input. pinctrl. gpio 子系统都是 Linux 内核针对某一类设备而创建的框架, input子系统是管理输入的子系统 pinctrl 子系统重点是设置 PIN( ...

  3. Linux 驱动开发 四十八:Linux INPUT 子系统实验

    一.input 子系统简介 input 就是输入的意思,因此 input 子系统就是管理输入的子系统,是 Linux 内核针对某一类设备而创建的框架. 比如按键输入.键盘.鼠标.触摸屏等等这些都属于输 ...

  4. 三个子系统_「正点原子Linux连载」第五十八章Linux INPUT子系统实验(一)

    1)实验平台:正点原子Linux开发板 2)摘自<正点原子I.MX6U嵌入式Linux驱动开发指南> 关注官方微信号公众号,获取更多资料:正点原子 第五十八章Linux INPUT子系统实 ...

  5. input type类型_设备树下的input子系统

    更多文章请关注公众号 :麻瓜技术闲谈 input 就是输入的意思,因此 input 子系统就是管理输入的子系统,和 pinctrl 和 gpio 子系统一样,都是 Linux 内核针对某一类设备而 ...

  6. Linux Input子系统

    1. Input子系统 按键.鼠标.键盘.触摸屏等都属于输入(input)设备,Linux 内核为此专门做了一个叫做 input子系统的框架来处理输入事件.输入设备本质上还是字符设备,只是在此基础上套 ...

  7. (五)DSP28335基础教程——外部中断控制(按键触发)

    0 前言 本期实验目标:采用外部中断方式响应按键触发,实现LED电平反转. 外部中断是DSP十分常用的功能,通常用来响应一些控制操作,比如判断按键是否按下,传感器是否接收到信号等等.那么通过该例程,大 ...

  8. STM32按键消抖的几种实现方式-STM32 Button Debouncing

    一.按键抖动的现象 按键按下和松开的时候,按键金属片之间的贴合.分离有一个过程.给STM32输入的信号并不是理想的0和1切换的过程.而是如下图所示的,按下和松开的一小段时间内按键信号出现抖动(jitt ...

  9. 嵌入式linux设备驱动程序是,嵌入式Linux设备驱动开发之:按键驱动程序实例-嵌入式系统-与非网...

    11.6  按键驱动程序实例 11.6.1  按键工作原理 LED和蜂鸣器是最简单的GPIO的应用,都不需要任何外部输入或控制.按键同样使用GPIO接口,但按键本身需要外部的输入,即在驱动程序中要处理 ...

最新文章

  1. CCNP-22 路由重发布2(BSCI)
  2. ATG中的定时Job处理
  3. 北大教授:到底什么才是有效的教育?
  4. 图论学习四之Disjoint set union并查集
  5. Maven多模块打包遇到的问题详解
  6. iscsi-target
  7. 输入URL经历的过程
  8. linux浮动ip添加 手动,在Linux 双机下自己手动实现浮动ip技术
  9. Atitit 提升开发效率 通道化驱动化数据操作与查询 目录 1. xiaoguo 1 1.1. Atitit mybatis 简化开发与提升开发效率法 1 2. Code 1 3. ref 4
  10. 国内著名高校飞跃手册整理
  11. 初识DNA甲基化芯片
  12. phpcms修改了配置文件之后出现Warning: date() expects parameter 2 to be long..错误
  13. 国产CAD_谁说国产系统没有CAD软件可以用?
  14. 认识Http协议(超文本传输协议)
  15. tesseract的使用
  16. QCustomPlot 连续快速地调用replot()改善速度
  17. UE4贴图自适应屏幕大小
  18. Android开发踩坑之旅
  19. AD中的机械尺寸定位的使用
  20. 安卓图像更新学习总结

热门文章

  1. 鸿蒙os首批适配机型,鸿蒙OS正式版首批名单曝光,适配速度让人意外,8款机型恭喜了...
  2. mysql 分表 sphinx_sphinx(coreseek)处理分表的方案
  3. 更新json文件_忽略packagelock.json?
  4. 李宏毅老师机器学习和深度学习
  5. scala不使用new关键字创建对象实例
  6. 人工神经网络模型与分类
  7. GraphQL及元数据驱动架构在后端BFF中的实践
  8. 精益软件过程中七大浪费的应对之道
  9. java InputStream的使用
  10. Hive自定义UDF UDAF UDTF