OrangePIPC2---红外模块(一)

前言

之前学习过linux下的输入子系统,这次想总结下,顺便在orangepi上实现一个简单的遥控器识别功能。本文主要介绍orangepi上的硬件相关部分,涉及红外模块,以及红外模块的驱动介绍。

硬件

在pipc2上集成了一个红外头,在系统模块中属于外设的CIR模块,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

配置

因为我的开发板是全志的orangepipc2 所以要使用这个硬件功能需要打开dts这部分的配置
在这里插入图片描述
在这里插入图片描述

驱动

在dts的配置中发现有个rc-map-name = “rc-nec-alientek”; 这个其实就是一个对应表,
比如我接收到的编码键值他代表什么意识,这样的一个对应表。
ir的驱动是这个allwinner,sun5i-a13-ir
在这里插入图片描述

static int sunxi_ir_probe(struct platform_device *pdev)
{
ir->rc->priv = ir;
	ir->rc->device_name = SUNXI_IR_DEV;
	ir->rc->input_phys = "sunxi-ir/input0";
	ir->rc->input_id.bustype = BUS_HOST;
	ir->rc->input_id.vendor = 0x0001;
	ir->rc->input_id.product = 0x0001;
	ir->rc->input_id.version = 0x0100;
	ir->map_name = of_get_property(dn, "linux,rc-map-name", NULL);//这个就是可以在dts里面配置
	ir->rc->map_name = ir->map_name ?: RC_MAP_EMPTY;
	ir->rc->dev.parent = dev;
	ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
	/* Frequency after IR internal divider with sample period in ns */
	ir->rc->rx_resolution = (1000000000ul / (b_clk_freq / 64));
	ir->rc->timeout = MS_TO_NS(SUNXI_IR_TIMEOUT);
	ir->rc->driver_name = SUNXI_IR_DEV;
	ret = rc_register_device(ir->rc);//这里会注册数据处理线程进行处理数据
	ret = devm_request_irq(dev, ir->irq, sunxi_ir_irq, 0, SUNXI_IR_DEV, ir);
}
//当收到红外信号后触发中断
static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id)
{
...
for (cnt = 0; cnt < rc; cnt++) {
			/* for each bit in fifo */
			dt = readb(ir->base + SUNXI_IR_RXFIFO_REG);
			rawir.pulse = (dt & 0x80) != 0;
			rawir.duration = ((dt & 0x7f) + 1) *
					 ir->rc->rx_resolution;
			ir_raw_event_store_with_filter(ir->rc, &rawir);
			//将寄存器的值放到rc_dev中的dev->raw->this_ev
		}
	ir_raw_event_handle(ir->rc);//这个里面会wake_up_process(dev->raw->thread);
}

而dev->raw->thread的注册在rc_register_device中被注册

int rc_register_device(struct rc_dev *dev)
{
if (dev->driver_type == RC_DRIVER_IR_RAW) {
rc = ir_raw_event_prepare(dev);
if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
rc = rc_prepare_rx_device(dev);//设置键值表这个就是将键值和input_dev的code对应起来
if (rc)
goto out_raw;
}
rc = device_add(&dev->dev);
if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
		rc = rc_setup_rx_device(dev); //这里就使用接口input_register_device注册input_dev 
		if (rc)
			goto out_dev;
	}
if (dev->driver_type == RC_DRIVER_IR_RAW) {
rc = ir_raw_event_register(dev);//这里有中断拿到键值后的处理线程 初始化
if (rc < 0)
goto out_lirc;
}
设置键值表这个就是将键值和input_dev的code对应起来
这里还出现了定义input_dey能力的地方,说明这就将要在创建一个输入设备
static int rc_prepare_rx_device(struct rc_dev *dev)
{
rc_map = rc_map_get(dev->map_name);
rc = ir_setkeytable(dev, rc_map);
set_bit(EV_KEY, dev->input_dev->evbit);//定义这个input_dev有EV_KEY type
set_bit(EV_REP, dev->input_dev->evbit);
set_bit(EV_MSC, dev->input_dev->evbit);
set_bit(MSC_SCAN, dev->input_dev->mscbit);
if (dev->open)
dev->input_dev->open = ir_open;
if (dev->close)
dev->input_dev->close = ir_close;
}
int ir_raw_event_register(struct rc_dev *dev)
{
	struct task_struct *thread;
	thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u", dev->minor);
	dev->raw->thread = thread;
...
	return 0;
}
/*
这个线程处理的东西也比较复杂,他会更具当前IR设备的编码格式选择某种编码格式的decode处理回调,
这里涉及一个知识点红外光滋溜一窜光过来,巴拉巴拉一段长数据,都是有编码格式的,只有符合相同格式的对应解码才能拿到对应的码值。这一块我们用的常用的nec编码。
*/
static int ir_raw_event_thread(void *data)
{
while (1) {
handler->decode(dev, ev);
...
}
在ir-nec-decoder.c
static int __init ir_nec_decode_init(void)
{
ir_raw_handler_register(&nec_handler);
}
static struct ir_raw_handler nec_handler = {
.protocols = RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX |
RC_PROTO_BIT_NEC32,
.decode = ir_nec_decode,
.encode = ir_nec_encode,
.carrier = 38000,
.min_timeout = NEC_TRAILER_SPACE,
};
状态机解码数据,重复码的实现也在软件实现
static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
{rc_keydown...
去按键表里获取值并上报input事件
void rc_keydown(struct rc_dev *dev, enum rc_proto protocol, u32 scancode,
u8 toggle)
{
u32 keycode = rc_g_keycode_from_table(dev, scancode);//根据码值去相对应的rc_map_tab中找code其实就想知道这个码值代表什么意识,是1 是开机键等
ir_do_keydown(dev, protocol, scancode, keycode, toggle);//->input_report_key(dev->input_dev, keycode, 1);
input_report_key-input_event(dev, EV_KEY, code, !!value);

这里就能发现其实ir模块接收到一窜数据后转给nec_handler去处理他解码出来后直接调用input_event上报,同时在rc_register_device注册的时候吧input_dev同时给注册了,其实从rc_dev的结构体类型上也能看出,他包含了一个input_dev。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值