当前位置:网站首页>i. Mx6ull driver development | 21 - key driver reports events using input subsystem
i. Mx6ull driver development | 21 - key driver reports events using input subsystem
2022-04-22 21:53:00 【Mculover666】
The driver source code warehouse written in this series of articles , welcome Star:https://github.com/Mculover666/linux_driver_study.
One 、 Write driver
1. Writing module
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>
#include <linux/timer.h>
struct key_dev {
struct device_node *node; /*!< Device tree node */
int gpio; /*!< key The use of gpio Number */
int debounce_interval; /*!< How long does it take to shake */
struct timer_list timer; /*!< Used for software anti chattering */
struct input_dev *input; /*!< input device */
int irq; /*!< Interrupt number */
};
static struct key_dev key;
static irqreturn_t key0_handler(int irq, void *dev_id)
{
struct key_dev *dev = (struct key_dev *)dev_id;
// Start the software timer , Read after buffeting time
mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->debounce_interval));
dev->timer.data = (volatile long)dev_id;
return IRQ_RETVAL(IRQ_HANDLED);
}
static void timer_handler(unsigned long arg)
{
int val;
struct key_dev *dev = (struct key_dev *)arg;
val = gpio_get_value(dev->gpio);
if (val == 0) {
} else {
}
}
static int key_init(void)
{
int ret;
uint32_t debounce_interval = 0;
// Get the device tree node
key.node = of_find_node_by_name(NULL, "key0");
if (!key.node) {
printk("key0 node find fail!\n");
return -1;
}
// extract gpio
key.gpio = of_get_named_gpio(key.node, "key-gpio", 0);
if (key.gpio < 0) {
printk("find key-gpio propname fail!\n");
return -1;
}
// initialization gpio
ret = gpio_request(key.gpio, "key-gpio");
if (ret < 0) {
printk("gpio request fail!\n");
return -1;
}
gpio_direction_input(key.gpio);
// Parsing device tree , Get the duration of de buffeting
if (of_property_read_u32(key.node, "debounce-interval", &debounce_interval) < 0) {
printk("find debounce-interval fail!\n");
goto error;
}
// Set the duration of debounce
if (debounce_interval) {
ret = gpio_set_debounce(key.gpio, key.debounce_interval * 1000);
if (ret < 0) {
printk("gpio_set_debounce not support, use soft timer!\n");
// Set the software timer to eliminate chattering
init_timer(&key.timer);
key.timer.function = timer_handler;
key.debounce_interval = debounce_interval;
}
}
// Get interrupt number
key.irq = gpio_to_irq(key.gpio);
if (key.irq < 0) {
printk("gpio_to_irq fail!\n");
goto error;
}
// Application interruption
ret = request_irq(key.irq, key0_handler, IRQF_TRIGGER_FALLING, "key_irq", &key);
if (ret < 0) {
printk("irq request fail, ret is %d!\n", ret);
goto error;
}
return 0;
error:
gpio_free(key.gpio);
return -1;
}
static void key_deinit(void)
{
// Release interrupt
free_irq(key.irq, &key);
// Release gpio
gpio_free(key.gpio);
// Delete timer
del_timer(&key.timer);
}
static int __init key_module_init(void)
{
return key_init();
}
static void __exit key_module_exit(void)
{
key_deinit();
}
module_init(key_module_init);
module_exit(key_module_exit);
MODULE_AUTHOR("Mculover666");
MODULE_LICENSE("GPL");
2. input device
Import header file :
#include <linux/input.h>
(1) Add global variable :
struct key_dev {
struct device_node *node; /*!< Device tree node */
int gpio; /*!< key The use of gpio Number */
int debounce_interval; /*!< How long does it take to shake */
struct timer_list timer; /*!< Used for software anti chattering */
struct input_dev *input; /*!< input device */
int irq; /*!< Interrupt number */
};
(2) Distribute / Register input device
In the key initialization function , Write the following code .
// Assign input devices
key.input = input_allocate_device();
if (!key.input) {
printk("irq input_allocate_device fail!\n");
goto error;
}
In order to use setbit function , Import header file :
#include <asm/bitops.h>
Write the code to initialize the input device :
// Initialize input device
key.input->name = "keyinput";
set_bit(EV_KEY, key.input->evbit); // Key events
set_bit(EV_REP, key.input->evbit); // Repeat events
set_bit(KEY_0, key.input->keybit); // Set which buttons to generate
Register input device :
// Register input device
ret = input_register_device(key.input);
if (ret < 0) {
printk("input_register_device fail!\n");
goto error;
}
(3) Cancellation / Release the input device
In the key de initialization function , Add logoff and release of input device .
static void key_deinit(void)
{
// Log off the input device
input_unregister_device(key.input);
// Release the input device
input_free_device(key.input);
// Release interrupt
free_irq(key.irq, &key);
// Release gpio
gpio_free(key.gpio);
// Delete timer
del_timer(&key.timer);
}
3. Report the incident
After the anti shake timer times out , Reported event value :
static void timer_handler(unsigned long arg)
{
int val;
struct key_dev *dev = (struct key_dev *)arg;
static int i = 0;
// Report input events
val = gpio_get_value(dev->gpio);
printk("--->report, i = %d\n", i++);
if (val == 0) {
input_report_key(dev->input, KEY_0, 1);
input_sync(dev->input);
input_report_key(dev->input, KEY_0, 0);
input_sync(dev->input);
}
}
After the report button is pressed , To report again, press and release the button , Otherwise Linux The kernel will always think that the key is pressed !
4. Compiler module
KERNEL_DIR = /home/mculover666/imx6ull/kernel/linux-imx6ull
obj-m = input_key.o
build: kernel_module
kernel_module:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean
Two 、 Write applications
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <linux/input.h>
#include <string.h>
static struct input_event event;
int main(int argc, char *argv[])
{
int fd;
int ret;
if (argc != 2) {
printf("usage: ./test_input_key [device]\n");
return -1;
}
fd = open(argv[1], O_RDWR);
if (fd < 0) {
printf("open file %s fail!", argv[1]);
return -1;
}
while (1) {
memset(&event, 0, sizeof(event));
ret = read(fd, &event, sizeof(event));
switch (event.type) {
case EV_SYN:
break;
case EV_KEY:
if (event.code < BTN_MISC) {
// Keyboard key value
printf("key %d %s\n", event.code, event.value ? "press" : "release");
} else {
printf("btn %d %s\n", event.code, event.value ? "press" : "release");
}
break;
case EV_REL:
break;
case EV_ABS:
break;
case EV_MSC:
break;
case EV_SW:
break;
}
}
}
3、 ... and 、 test
1. Load module , View the input device node
Before loading the module , View device nodes , After loading the module, check the device node again :

You can see that the new device is /dev/event4.
2. Running the application

版权声明
本文为[Mculover666]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204221623046124.html
边栏推荐
- Suggestions for improving C program 4: implementation of standard dispose mode in C
- ES6 object extension chain judgment operator and null judgment operator
- MySQL deadlock analysis and solution caused by index merging!
- How to realize guessing numbers games in C language
- 1251 - client does not support authentication protocol error in MySQL running in Navicat for MySQL connection docker
- Noise problem at the end of alsa playback
- Mailbox format test
- How to write word reading and color games based on JS
- 使用Pytorch对模型进行训练以及使用保存好的模型进行预测
- Oplg: new generation cloud primary observable best practices
猜你喜欢

Experiment 3

Penetration test & Network & CTF interview questions sorting

为什么我们需要做企业成长性评价分析?

ES6 reflect object

在线YAML转XML工具

基于JS怎么编写看字说颜色小游戏
Browser HTTP cache related knowledge

Understanding of EMMC erasure group

Enterprise appraisers build a decision support platform for the government

Brief introduction of Microsoft testers
随机推荐
MySQL configuration parameters and commands
Thread communication mechanism: shared memory VS message passing
unbelievable! The chief architect of Netease used 500 pages of notes to talk about the network protocol
Linux MySQL compilation and installation
[network protocol] switch and VLAN
短视频内容理解与生成技术在美团的创新实践
c语言怎么实现猜数字小游戏
Online yaml to XML tool
paho.mqtt.c简单介绍
Suggestions for improving C program 4: implementation of standard dispose mode in C
在线YAML转XML工具
Noise problem at the end of alsa playback
项目经理值得一试的思维方式:项目成功方程式
Pytoch note57 pytoch visual network structure
Drop down options under playwright operation select
Interface test mock practice (II) | complete batch manual mock in combination with JQ
BACKBONE,NECK,HEAD
IM即时通讯开发如何设计能支撑百万并发的数据库
Comprehensive practice of linear regression and logical regression of user portrait
改善C#程序的建议5:引用类型赋值为null与加速垃圾回收