diff --git a/11_key/.vscode/c_cpp_properties.json b/11_key/.vscode/c_cpp_properties.json new file mode 100644 index 0000000000000000000000000000000000000000..7ee3d5b701c1010964e824eea25d2856aa3e67b5 --- /dev/null +++ b/11_key/.vscode/c_cpp_properties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "/home/youxiu/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga/include/**", + "/home/youxiu/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include/**", + "/home/youxiu/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include/generated/**", + "/home/youxiu/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga/drivers/**" + ], + "defines": [], + "compilerPath": "/usr/bin/clang", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "clang-x64" + } + ], + "version": 4 +} + diff --git a/11_key/.vscode/settings.json b/11_key/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..1a2a04ac7a2d6b080404235adcd34b94bc581cb4 --- /dev/null +++ b/11_key/.vscode/settings.json @@ -0,0 +1,21 @@ +{ + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/*.o":true, + "**/*.su":true, + "**/*.cmd":true, + "Documentation":true, + }, + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/*.o":true, + "**/*.su":true, + "**/*.cmd":true, + "Documentation":true, + } +} \ No newline at end of file diff --git a/11_key/11_key.code-workspace b/11_key/11_key.code-workspace new file mode 100644 index 0000000000000000000000000000000000000000..f5bceea103bfd144b4918ccc83b822ec90b9f86d --- /dev/null +++ b/11_key/11_key.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings":{ + + } +} \ No newline at end of file diff --git a/11_key/Makefile b/11_key/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c8ee05b84cf33c1e3a000ec7207f0049e91a91cb --- /dev/null +++ b/11_key/Makefile @@ -0,0 +1,13 @@ +KERNELDIR := /home/youxiu/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga +CURRENT_PATH := $(shell pwd) +obj-m := key.o + +build: kernel_modules + +kernel_modules: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean + + diff --git a/11_key/key.c b/11_key/key.c new file mode 100644 index 0000000000000000000000000000000000000000..d8dc4c438628a483b731b0b42816a288bbdd72a3 --- /dev/null +++ b/11_key/key.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KEY_CNT 1 /* 设备号个数 */ +#define KEY_NAME "key" /* 名字 */ + +/* 定义按键值 */ +#define KEY0VALUE 0xF0 /* 按键值*/ +#define INVAKEY 0x00 /* 无效的按键值 */ + + +/* key设备结构体 */ +struct key_dev{ + dev_t devid; /* 设备号 */ + struct cdev cdev; /* cdev */ + struct class *class; /* 类 */ + struct device *device; /* 设备 */ + int major; /* 主设备号 */ + int minor; /* 次设备号 */ + struct device_node *nd; /* 设备节点 */ + int key_gpio; + atomic_t keyvalue; /* 按键值*/ +}; + +struct key_dev keydev; + +static int key_open(struct inode *inode, struct file *filp) +{ + filp->private_data = &keydev; + keydev.nd = of_find_node_by_path("/key"); + if(keydev.nd == NULL){ + return -EINVAL; + } + + keydev.key_gpio = of_get_named_gpio(keydev.nd, "key-gpio",0); + if(keydev.key_gpio < 0) { + printk("can't get key0\r\n"); + return -EINVAL; + } + printk("key_gpio = %d\r\n", keydev.key_gpio); + /* 初始化key所使用的IO */ + gpio_request(keydev.key_gpio, "key0"); + gpio_direction_input(keydev.key_gpio); + + 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){ + while(!gpio_get_value(dev->key_gpio)) + ; + atomic_set(&dev->keyvalue,KEY0VALUE); + }else{ + atomic_set(&dev->keyvalue,INVAKEY); + } + value = atomic_long_read(&dev->keyvalue); + ret = copy_to_user(buf,&value,sizeof(value)); + return ret; +} + +static struct file_operations key_fops = { + .owner = THIS_MODULE, + .open = key_open, + .read = key_read, +}; + +static __init mykey_init(void) +{ + /* 初始化源自变量 */ + atomic_set(&keydev.keyvalue,INVAKEY); + /* 注册字符设备驱动 */ + /* 1、创建设备号 */ + if(keydev.major){ /* 如果定义了设备号 */ + keydev.devid = MKDEV(keydev.major,0); + register_chrdev_region(keydev.devid,KEY_CNT,KEY_NAME); + }else { /* 没有定义设备号 */ + alloc_chrdev_region(&keydev.devid,0,KEY_CNT,KEY_NAME); + keydev.major = MAJOR(keydev.devid); /* 获取分配的主设备号 */ + keydev.minor = MINOR(keydev.devid); /* 获取分配的次设备号 */ + } + + /* 2、初始化cdev */ + keydev.cdev.owner = THIS_MODULE; + cdev_init(&keydev.cdev,&key_fops); + + /* 3、添加一个cdev */ + cdev_add(&keydev.cdev,keydev.devid,KEY_CNT); + /* 4、创建类 */ + keydev.class = class_create(THIS_MODULE,KEY_NAME); + if(IS_ERR(keydev.class)){ + return PTR_ERR(keydev.class); + } + + /* 5、创建设备 */ + keydev.device = device_create(keydev.class,NULL,keydev.devid,NULL,KEY_NAME); + if(IS_ERR(keydev.device)){ + return PTR_ERR(keydev.device); + } + + return 0; +} + +static __exit mykey_exit(void) +{ + //注销字符设备驱动 + gpio_free(keydev.key_gpio); + cdev_del(&keydev.cdev); + unregister_chrdev_region(keydev.devid,KEY_CNT); + + device_destroy(keydev.class,keydev.devid); + class_destroy(keydev.class); +} + +module_init(mykey_init); +module_exit(mykey_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("zhangchaoliang"); diff --git a/11_key/keyApp.c b/11_key/keyApp.c new file mode 100644 index 0000000000000000000000000000000000000000..52d7b5a163238c822a576ce89cb314644efa510d --- /dev/null +++ b/11_key/keyApp.c @@ -0,0 +1,49 @@ +#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 0x00 + + +/* + +*/ +int 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]; + 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) { + printf("KEY0 Press,value = %#x\r\n",keyvalue);// 按下 + } + } + + ret = close(fd); // close文件 + if(ret <0){ + printf("file %s close failed\r\n",argv[1]); + return -1; + } + + return 0; +}