Hi3519v101输入输出子系统-key_input

一、步骤

1、分配input_dev

2、设置

3、注册

4、硬件相关操作

二、说明

struct input_dev {
	const char *name;
	const char *phys;
	const char *uniq;
	struct input_id id;

	unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];

	unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//能产生哪一类事件
	unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//能产生哪些按键
	unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//能产生哪些相对位移事件,x,y,滚轮
	unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//能产生哪些绝对位移事件,x,y
	unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
	unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
	unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
	unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
	unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
    ...
}

其中unsigned long evbit[BITS_TO_LONGS(EV_CNT)]可以设置如下时间:

#define EV_SYN 0x00 //表示设备支持所有的事件
#define EV_KEY 0x01 //键盘或者按键,表示一个键码
#define EV_REL 0x02 //鼠标设备,表示一个相对的光标位置结果
#define EV_ABS 0x03 //手写板产生的值,其是一个绝对整数值
#define EV_MSC 0x04 //其他类型
#define EV_LED 0x11 //LED灯设备
#define EV_SND 0x12 //蜂鸣器,输入声音
#define EV_REP 0x14 //允许重复按键类型
#define EV_PWR 0x16 //电源管理事件
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)

三、代码&测试

1、准备key_irq_input.c

#include <linux/module.h>

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/spinlock.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <linux/sched.h>

// 操作管脚为gpio14_2
// 该管脚采用boot_sel[1:0]硬件配置复用功能,现单板已经配置为gpio,默认高电平,按键按下为低电平
static void __iomem *key_base; //寄存器基地址

#define gpio_phy_base 0x1214E000   //key管脚物理地址
#define gpio_data key_base + 0x010 //GPIO 数据寄存器 ,0b00_0001_0000
#define gpio_dir key_base + 0x400  //GPIO 方向控制寄存器
#define gpio_is key_base + 0x404   //GPIO 中断触发寄存器
#define gpio_ibe key_base + 0x408  //GPIO 双沿触发中断寄存器
#define gpio_iev key_base + 0x40C  //GPIO 触发中断条件寄存器
#define gpio_ie key_base + 0x410   //GPIO 中断屏蔽寄存器
#define gpio_ris key_base + 0x414  //GPIO 原始中断状态寄存器
#define gpio_mis key_base + 0x418  //GPIO 屏蔽状态中断寄存器
#define gpio_ic key_base + 0x41C   //GPIO 中断清除寄存器

#define gpio_in 0x00 //配置为输入,1输出 0输入def
#define gpio_out_h 0xFF
#define gpio_out_l 0x00

struct pin_desc
{
    int irq;
    char *name;
    unsigned int pin;
    unsigned int key_val;
};

struct pin_desc pins_desc[] =
    {
        {76, "key_irq", 0x010, KEY_ENTER},
};

static struct input_dev *key_dev_input;
static struct timer_list key_timer;
static struct pin_desc *irq_pd;

static irqreturn_t key_irq(int irq, void *dev_id)
{
    //jiffies 为系统中断,10ms中断一次
    //HZ为100 (HZ / 100) = 1,jiffies + (HZ / 100) 表示10ms中断一下
    irq_pd = (struct pin_desc *)dev_id;
    mod_timer(&key_timer, jiffies + (HZ / 100)); //调整定时器时间
    iowrite8(0xFF, gpio_ic);                     //清除中断
    return IRQ_HANDLED;
}

static void key_timer_function(unsigned long data)
{
    static unsigned int cnt = 0;
    unsigned int key;
    struct pin_desc *pindesc = irq_pd;

    if (!pindesc)
        return;

    printk("cnt = %d\n", cnt++);

    key = ioread8(gpio_data);
    printk("key = %d\n", key);
    if (key)
    {
        /* 松开 : 最后一个参数: 0-松开, 1-按下 */
        input_event(key_dev_input, EV_KEY, pindesc->key_val, 0);
        input_sync(key_dev_input);
    }
    else
    {
        /* 按下 */
        input_event(key_dev_input, EV_KEY, pindesc->key_val, 1);
        input_sync(key_dev_input);
    }
}

static int key_irq_input_init(void)
{
    int error;

    //1、分配一个input_dev结构提
    key_dev_input = input_allocate_device();
    //2、设置
    //2.1能产生哪类事件
    set_bit(EV_KEY, key_dev_input->evbit); //按键类型
    set_bit(EV_REP, key_dev_input->evbit); //允许重复按键类型
    //2.2能产生这类操作的哪些时间
    set_bit(KEY_ENTER, key_dev_input->keybit);
    //3、注册
    error = input_register_device(key_dev_input);
    if (error)
    {
        printk("Unable to register input device, error: %d\n", error);
    }
    //4、硬件相关操作
    key_base = ioremap(gpio_phy_base, 0x1000);
    printk("key_data = 0x%x\n", (unsigned int)gpio_data);
    iowrite8(gpio_in, gpio_dir); //gpio14_2 配置为输入
    iowrite8(0x00, gpio_is);     //配置边沿触发
    iowrite8(0x00, gpio_iev);    //配置下降沿触发
    iowrite8(0x04, gpio_ibe);    //配置双沿触发
    iowrite8(0xFF, gpio_ic);     //清除中断
    iowrite8(0x04, gpio_ie);     //使能gpio14_2中断

    init_timer(&key_timer);
    key_timer.function = key_timer_function;
    add_timer(&key_timer);
    //申请按键中断
    request_irq(pins_desc[0].irq, key_irq, IRQF_SHARED, pins_desc[0].name, &pins_desc[0]);

    return 0;
}

static void key_irq_input_exit(void)
{
    free_irq(pins_desc[0].irq, &pins_desc);
    del_timer(&key_timer);
    input_unregister_device(key_dev_input);
    input_free_device(key_dev_input);
}

module_init(key_irq_input_init);
module_exit(key_irq_input_exit);
MODULE_LICENSE("GPL");

2、Makefile参考之前的

3、测试

加载驱动,查看新加模块的主次设备号

/ # insmod key_irq_input.ko
input: Unspecified device as /devices/virtual/input/input0
key_data = 0xfea4e010
/ # ls -l /dev/input/event0
crw-------    1 root     root       13,  64 Jan  1 00:05 /dev/input/event0

 

/ # hexdump /dev/input/event0
cnt = 16
key = 0
0000000 0551 0000 2e89 0009 0001 001c 0001 0000
0000010 0551 0000 2e89 0009 0000 0000 0000 0000
cnt = 17
key = 4
0000020 0551 0000 5149 000b 0001 001c 0000 0000
0000030 0551 0000 5149 000b 0000 0000 0000 0000

参数注解

        秒        微秒       类        value 
0000000 0551 0000 2e89 0009 0001 001c 0001 0000
0000010 0551 0000 2e89 0009 0000 0000 0000 0000

//KEY_ENTER = 0x1c = 28
//EV_KEY = 0x01 = 0001

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值