// cat /proc/bus/input/devices 列出当前系统下注册的所有输入设备
/* 测试方法,将当前终端的标准输入重定向到驱动框架所产生的tty设备上
* exec 0 */
#include
#include
#include
#include
#include
#include
#include
#include
// cat /proc/bus/input/devices 列出当前系统下注册的所有输入设备
/* 测试方法,将当前终端的标准输入重定向到驱动框架所产生的tty设备上
* exec 0reg);//从内存映射的 I/O 空间读取数据,readl 从 I/O 读取 32 位数据 ( 4 字节 )
return data & pkey->ctrlbit;
}
static struct key_info key[] = {
{"KEY_L", KEY_L, stat, (unsigned long)GPX3DAT, 1 << 2, IRQ_EINT(26)},
{"KEY_S", KEY_S, stat, (unsigned long)GPX3DAT, 1 << 3, IRQ_EINT(27)},
{"KEY_ENTER", KEY_ENTER, stat, (unsigned long)GPX3DAT, 1 << 4, IRQ_EINT(28)},
{"KEY_BACKSPACE", KEY_BACKSPACE, stat, (unsigned long)GPX3DAT, 1 << 5, IRQ_EINT(29)},
};
static irqreturn_t key_handler(int irqno, void *arg)
{
struct key_info *pkey = (struct key_info *)arg;
//读出触发中断的当前按键的状态
if (pkey->read_stat(pkey)) { //抬起
//value=1表示按下,=0表示抬起,硬件状态应根据寄存器反应的电平状态来判断
input_report_key(ldm.dev, pkey->code, 0);
} else { //按下
input_report_key(ldm.dev, pkey->code, 1);
}
//哨兵event
input_sync(ldm.dev);
return IRQ_HANDLED;
}
static int __init ldm_init(void)
{
printk("%s %s\n", __FUNCTION__, __FILE__);
int ret = 0;
//1 创建输入设备对象
ldm.dev = input_allocate_device();
if (!ldm.dev) {
printk("input_allocate_device failed\n");
ret = -ENOMEM;
goto err_input_allocate_device;
}
//2 对象初始化
ldm.dev->name = "ldm_key";
//2.1 定义输入设备的输入类型
//有按键类型的操作
set_bit(EV_KEY, ldm.dev->evbit);
//支持连发
set_bit(EV_REP, ldm.dev->evbit);
//注册本设备所拥有的所有按键键值
ssize_t i = 0;
for (i = 0; i < ARRAY_SIZE(key); ++i) {
set_bit(key[i].code, ldm.dev->keybit);
}
//3 硬件初始化,中断申请,按下抬起都触发中断
for (i = 0; i < ARRAY_SIZE(key); ++i) {
ret = request_irq(key[i].irqno, key_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, key[i].name, (void*)(key + i));
if (ret < 0) {
printk("request_irq %d faild\n", i);
goto err_request_irq;
}
}
//4 注册输入设备
ret = input_register_device(ldm.dev);
if (ret < 0) {
printk("input_register_device failed\n");
goto err_input_register_device;
}
return 0;
err_input_register_device:
err_request_irq:
for (i = i - 1; i >= 0; --i) {
free_irq(key[i].irqno, (void*)(key + i));
}
input_free_device(ldm.dev);
err_input_allocate_device:
return ret;
}
static void __exit ldm_exit(void)
{
printk(KERN_DEBUG "%s %s\n", __FUNCTION__, __FILE__);
input_unregister_device(ldm.dev);
ssize_t i = ARRAY_SIZE(key);//ARRAY_SIZE求设备结构体中设备的个数
for (i = i - 1; i >= 0; --i) {
free_irq(key[i].irqno, (void*)(key + i));
}
input_free_device(ldm.dev);
}
module_init(ldm_init);
module_exit(ldm_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xiangtan da xue chenhaipan");
MODULE_VERSION("2017.5.4");