前言
之前学习过linux下的输入子系统,这次想总结下,顺便在orangepi上实现一个简单的遥控器识别功能。本文主题介绍如何编写一个遥控器的驱动,以及如何使用。
驱动
驱动这块其实在这篇文章大幅度提到OrangePIPC2—红外模块(一),其中有提到,ir控制器的驱动只是将一摞红外数据收集到。进而转到rc_dev去处理。rc_dev进而解码,表核对找对应的code,又进行event的report。
所以他的类型结构是ir_dev 包含了rc_dev 包含了input_dev。
其中有块表的查询,这里详细记录下,我这里用的遥控器是正点原子的遥器
网上搜一搜就能知道这个键值排布
static struct rc_map_list nec_alientek_map = {
.map = {
.scan = nec_alientek,
.size = ARRAY_SIZE(nec_alientek),
.rc_proto = RC_PROTO_NEC,
.name = RC_MAP_NEC_ALIENTEK,
}
};
static int __init init_rc_map_nec_alientek(void)
{
return rc_map_register(&nec_alientek_map);
}
static void __exit exit_rc_map_nec_alientek(void)
{
rc_map_unregister(&nec_alientek_map);
}
module_init(init_rc_map_nec_alientek)
module_exit(exit_rc_map_nec_alientek)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AK");
源码解析
rc_map_register: 其实就放到了rc_map_list里面去
int rc_map_register(struct rc_map_list *map)
{
spin_lock(&rc_map_lock);
list_add_tail(&map->list, &rc_map_list);
spin_unlock(&rc_map_lock);
return 0;
}
在键值解析的时候会有个code查找的过程,这里展开下
u32 keycode = rc_g_keycode_from_table(dev, scancode);
u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode)
{
struct rc_map *rc_map = &dev->rc_map;//这个就是匹配好的指向nec_alientek_map
unsigned int keycode;
unsigned int index;
unsigned long flags;
spin_lock_irqsave(&rc_map->lock, flags);
index = ir_lookup_by_scancode(rc_map, scancode);
keycode = index < rc_map->len ?
rc_map->scan[index].keycode : KEY_RESERVED;
spin_unlock_irqrestore(&rc_map->lock, flags);
if (keycode != KEY_RESERVED)
dev_dbg(&dev->dev, "%s: scancode 0x%04x keycode 0x%02x\n",
dev->device_name, scancode, keycode);
printk("code:0X%X,keycode:0X%X\n",scancode,keycode);
return keycode;
}
这里可以看到执行了rc_map->scan就是那个数组里面的东西了。
只不过先更具码值先找index,然后返回scan[index].的值。其实后面的KEY_UP,KEY_VOLUMEUP,KEY_VOLUMEDOWN
这种我们在input里面叫code,代表这个是什么意思。在linux里面统一了这些key的code,方便应用层的使用,屏蔽掉一些不需要的信息。
试试效果
注意你这个是依赖sunxi-ir驱动的,可以在cat /proc/interrupts 下看看有没有sunxi-ir的中断,没有的话那就是没加载ir驱动编译下insmod吧
我这里设置成ko了,需要make module下。才能出现
ir-nec-decoder.ko sunxi-cir.ko
可以看到解码出来的code和表中一直,后面的是keycode统一的值