一、修改设备树文件

(1)添加pinctrl节点

打开imx6ull-alientek-emmc.dts文件,在 iomuxc 节点的 imx6ul-evk 子节点下创建一个名为“pinctrl_key”的子节点,节点内容如下所示:        ##该节点的作用是设置电气属性

(2)添加Key设备节点

在根节点“/”下创建 Key按键节点,节点内容如下:

(3)启动系统

Linux系统启动成功以后进入“/proc/device-tree”目录中查看“Key”节点是否存在,如果存在的话就说明设备树基本修改成功。

 二、完整驱动程序


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/slab.h>#define KEY_CNT 1
#define KEY_NAME "key"/* 定义按键值 */
#define KEY0VALUE 0XF0 /* 按键值 */
#define INVAKEY 0X00 /* 无效的按键值 */struct key_dev{dev_t devid;    /*设备号*/int major;  /*主设备号*/int minor;  /*次设备号*/struct cdev cdev;   /*字符设备*/struct class *class;    /*创建类*/struct device *device;  /*创建设备*/struct device_node *node; /*设备节点*/int key_gpio;   /*定义keygpio号*/atomic_t keyvalue;    //利用原子变量保存按键值
};struct key_dev key; /*定义key结构体*/static int keyio_init(void){int ret = 0;key.node = of_find_node_by_path("/key");    /*通过路径找到节点*/if(key.node == NULL){ret = -EINVAL;goto failed_findnode;}key.key_gpio = of_get_named_gpio(key.node, "key-gpios", 0);if(key.key_gpio < 0){printk("can't gey gpio\r\n");ret = -EINVAL;goto failed_findnode;}printk("key_gpio=%d\r\n", key.key_gpio);/* 初始化 key 所使用的 IO *//*申请gpio*/ret = gpio_request(key.key_gpio, "key-gpios");if(ret){printk("Failed to request gpio \r\n");ret = -EINVAL;goto failed_findnode;}ret = gpio_direction_input(key.key_gpio); /* 设置为输入 */if(ret < 0){goto failed_setinput;}return 0;failed_setinput:gpio_free(key.key_gpio);
failed_findnode:return ret;
}static int key_open(struct inode *inode, struct file *filp){int ret = 0;filp->private_data = &key; /* 设置私有数据 */ret = keyio_init(); /* 初始化按键 IO */if (ret < 0) {return ret;}return 0;
}static ssize_t key_read(struct file *filp, char __user *buf,size_t cnt, loff_t *offt){int ret = 0;unsigned char value;struct key_dev *dev = filp->private_data;if (gpio_get_value(dev->key_gpio) == 0) { /* key0 按下 */while(!gpio_get_value(dev->key_gpio)); /* 等待按键释放 */atomic_set(&dev->keyvalue, KEY0VALUE);} else { /* 无效的按键值 */atomic_set(&dev->keyvalue, INVAKEY);}value = atomic_read(&dev->keyvalue); /* 保存按键值 */ret = copy_to_user(buf, &value, sizeof(value));return ret;
}/*定义字符操作集*/
static const struct file_operations key_fops = {.owner = THIS_MODULE,.open = key_open,.read = key_read,
};/*驱动加载函数*/
static int __init key_init(void){int ret = 0;/*字符设备数注册*//*创建设备号*/key.major = 0;  /*linux自动申请设备号*/if(key.major){  /*如果给定了主设备号*/key.devid = MKDEV(key.major, 0);    /*获取设备号*/ret = register_chrdev_region(key.devid, KEY_CNT, KEY_NAME);}else{   /*否则自动申请设备号*/ret = alloc_chrdev_region(&key.devid, 0, KEY_CNT, KEY_NAME);key.major = MAJOR(key.devid);key.minor = MINOR(key.devid);   /*获取主次设备号*/}if(ret < 0){goto failed_devid;}printk("keydev major = %d,minor = %d \r\n",key.major,key.minor);/*初始化cdev*/key.cdev.owner = THIS_MODULE;cdev_init(&key.cdev, &key_fops);/*添加cdev*/ret = cdev_add(&key.cdev, key.devid, KEY_CNT);if(ret < 0){goto failed_cdev;}/*自动创建设备节点*//*创建类*/key.class = class_create(THIS_MODULE, KEY_NAME);if(IS_ERR(key.class)){  /*判断是否创建类成功*/ret = PTR_ERR(key.class);goto failed_class;}/*创建设备*/key.device = device_create(key.class, NULL, key.devid, NULL, KEY_NAME);    if(IS_ERR(key.device)){  /*判断是否创建类成功*/ret = PTR_ERR(key.device);goto failed_device;}return 0;failed_device:class_destroy(key.class);
failed_class:cdev_del(&key.cdev);
failed_cdev:unregister_chrdev_region(key.devid, KEY_CNT);
failed_devid:return ret;
}/*驱动卸载函数*/
static void __exit key_exit(void){/*注销字符设备*/cdev_del(&key.cdev);unregister_chrdev_region(key.devid, KEY_CNT);device_destroy(key.class, key.devid);class_destroy(key.class);gpio_free(key.key_gpio);
}/*模块入口和出口*/
module_init(key_init);
module_exit(key_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZYC");

三、完整应用程序

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"/* 定义按键值 */
#define KEY0VALUE 0XF0
#define INVAKEY 0X00int main(int argc, char *argv[])
{int fd, ret;char *filename;unsigned char keyvalue;if(argc != 2){printf("Error Usage!\r\n");return -1;}filename = argv[1];/* 打开 key 驱动 */fd = open(filename, O_RDWR);if(fd < 0){printf("file %s open failed!\r\n", argv[1]);return -1;}/* 循环读取按键值数据! */while(1) {read(fd, &keyvalue, sizeof(keyvalue));if (keyvalue == KEY0VALUE) { /* KEY0 */printf("KEY0 Press, value = %#X\r\n", keyvalue);/* 按下 */}}ret= close(fd); /* 关闭文件 */if(ret < 0){printf("file %s close failed!\r\n", argv[1]);return -1;
}return 0;
}

四、测试

 加载驱动:

  测试按键输入功能: 

Linux驱动_按键输入相关推荐

  1. Linux驱动中按键消抖原理

    为什么要用定时器来做按键消抖? 用到按键就要处理因为机械结构带来的按键抖动问题,也就是按键消抖.前面的实验中都是直接使用了延时函数来实现消抖,因为简单,但是直接用延时函数来实现消抖会浪费 CPU 性能 ...

  2. Linux下的按键输入驱动开发

    之前的文章中,介绍了各种各样的花式点灯方法,其本质都是通过操作GPIO输出高低电平,控制灯的亮灭.按键驱动也是要操作GPIO,只不过是要读取GPIO的高低电平.在驱动程序中使用一个整形变量来表示按键值 ...

  3. linux按键检测程序,Tiny4412 Linux驱动之按键(使用查询方式) | 技术部落

    前几天在TIny4412开发板上做了LED点灯的Linux驱动,其实挺简单,GPIO驱动,今天再看一下按键的驱动,毕竟按键用的还是比较广泛的,本文使用查询的方式获取按键值,后面会有文章使用中断的方式进 ...

  4. Linux驱动分析——input输入子系统

    stm32mp157  盘古开发板  Linux内核版本4.19 目录 1.朱有鹏老师的视频课程笔记和应用测试代码: 2.input子系统架构分析 2.1.输入核心层源码分析 2.1.1.首先是核心模 ...

  5. Linux驱动之按键驱动长按检测

    现在发现一个问题,Linux下的按键驱动,增加了长按检测.但是在长按的时候不往应用层上报长按的值,很奇怪先做个记录待以后分析.现在的模式是,周一到周五发现问题,到周末才会专心写博客填坑了. ===== ...

  6. linux 内核按键抖动,Tiny4412 Linux驱动之按键(定时器防抖动) | 技术部落

    按键抖动示意图 我们平常所用的按键为机械弹性开关,由于触点的弹性作用,按键在闭合时不会马上稳定的接通,而是有一段时间的抖动,在断开时也不会立即断开.抖动时间由按键的机械特性所决定,一般为5ms~10m ...

  7. ac3165 linux驱动_一文读懂Linux系统启动流程

    Linux启动管理 11.1 CentOS 6.x系统启动过程详解 CentOS 6.x系统启动过程发生了较大的变化,使用Upstart启动服务取代了原先的System V init启动服务.Upst ...

  8. Linux驱动:input输入子系统

    input输入子系统 1.input输入子系统 1.1 简介 1.2 相关API函数 1.3 使用流程(驱动框架) 2.驱动示例 3.测试程序 4.测试结果 5.内核自带的input按键驱动 附:对应 ...

  9. exfat linux 驱动_(实例)Linux 内核添加exfat驱动

    背景: 由于exfat是常用的文件系统格式,而Linux由于版权的问题,没有在官方中添加有关的驱动. 但是 微软也同意开源了,所以比较新的 Linux 会支持这一块. 为了支持exfat的驱动,我们需 ...

最新文章

  1. Hadmard product(哈达玛积)
  2. Java基础概念(一)
  3. How Vmware snapshots works
  4. 多重if,嵌套if和switch case如何区别使用
  5. memcache 基础原理
  6. 带有谓词的Java中的函数样式-第2部分
  7. UE4 Material Properties
  8. ★LeetCode(1025)——除数博弈(JavaScript)
  9. ROS与Matlab协同进行运动控制
  10. OpenGL基础55:文字渲染
  11. 主题模型TopicModel:PLSA模型及PLSA的EM推导
  12. 框架设计知识点纵览(笔记)
  13. vb 计算机cot,VB编程中运算sin、cos、tan、cot的程序怎么写?
  14. 第二十九节 MT-iBeacon基站关于LightBlue软件的使用
  15. 二工大计算机专业,两电一邮与哈工大:计算机专业哪所实力最强?看完就知道...
  16. Java中submit的方法,线程池中 submit()和 execute()方法区别
  17. B站国外大学公开课(持续更新)
  18. Autojs在线云更新教程
  19. Unc0ver 8.0.0 更新:支持 iOS 14.6-14.8、A12-A13 iPhone 越狱
  20. ASP.NET计算机类专业毕业设计(课程设计)题目大全

热门文章

  1. 单目视觉ADAS的技术与体验升级之路|硬创公开课
  2. android仿支付宝收款播报,【iOS】实现类似支付宝收钱语音播报功能
  3. ios全局点击空白隐藏keyboard
  4. android classes2.dex,原创??近乎完美解决AndroidKiller不提取classes2+.dex JAVA源码的问题...
  5. Mac上的ps插件安装教程:苹果电脑ps插件怎么安装
  6. core java文献翻译_外文翻译--Java技术介绍(适用于毕业论文外文翻译+中英文对照).doc...
  7. 网络结构拓扑图(3层交换机)
  8. CRC 的简介和应用(转载)
  9. 四月二日服务器维护到什么时候,4月4日服务器例行维护公告(已完成)
  10. Spark ALS recommendForAll源码解析实战之Spark1.x vs Spark2.x