抑郁症健康,内容丰富有趣,生活中的好帮手!
抑郁症健康 > Linux驱动_按键输入

Linux驱动_按键输入

时间:2018-08-29 07:12:13

相关推荐

一、修改设备树文件

(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驱动_按键输入》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。