9. 红外

本章节旨在让用户自定义红外遥控功能,需要有板载红外接收的板卡。

9.1. 获取红外遥控键值

由于不同遥控器厂家定义的按键键值不一样,所以配置不通用,需要获取实际按键对应的键值。

1
2
3
4
5
6
#设置输出等级
echo '7 4 1 7'> /proc/sys/kernel/printk
#开启打印
echo 1 > /sys/module/rockchip_pwm_remotectl/parameters/code_print

#此时按下按键串口终端就会有打印USERCODE和键值

提示

如果是ssh或者桌面终端不会直接打印信息到终端,需要执行 dmesg 命令进行查看

以野火红外遥控器为例:

遥控器资料链接: 野火【红外遥控_1838】模块

../../_images/telecontroller_0.jpg

对着板卡按下按键,每按下一个按键就会打印USERCODE和键值到串口终端。

../../_images/telecontroller_1.jpg

记录USERCODE值和按键对应的RMC_GETDATA值,后续需要修改键值对应的事件。

9.2. 修改设备树红外按键事件

需要修改内核源码板卡对应的设备树,如果不确定设备树是哪个的,可以执行 ls -l /boot 看 rk-kernel.dtb软连接到哪个dtb,改对应的dts即可。

以鲁班猫3的dts为例,默认已经修改过:

../../_images/telecontroller_2.jpg

找到红外对应的pwm ir节点,鲁班猫1对应的是pwm3,修改ir_key_lubancat部分

  • 将实际的USERCODE值改到 rockchip,usercode = <0xff00>;

  • 将键值和需要配置事件改到rockchip,key_table表里面。

对应的事件可以从 内核源码/include/dt-bindings/input/linux-event-codes.h 中取。linux-event-codes.h文件定义了输入事件的类型和代码,用于描述和标识各种输入设备(如键盘、鼠标、触摸屏等)生成的事件。

例如,遥控器上面的电源按键需要配置为板卡的电源开关机键,那么可以从linux-event-codes.h找到的事件KEY_POWER。

例如,遥控器上面的按键1要对应键盘上的1,那么可以从linux-event-codes.h找到的事件KEY_1。

依次从linux-event-codes.h中找到按键对应的事件后,将按键值和实际一一对应,修改得到以下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
     ir_key_lubancat{
     rockchip,usercode = <0xff00>;
     rockchip,key_table =
             <0xba   KEY_POWER>,   //电源按键
             <0xb8   KEY_MENU>,     //菜单按键
             <0xbc   KEY_BACK>,      //返回按键
             <0xbb   KEY_HOME>,      //home键按键
             <0xea   KEY_PLAY>,      //播放按键
             <0xbf   KEY_VOLUMEUP>,  //音量加按键
             <0xe6   KEY_VOLUMEDOWN>,   //音量键按键
             <0xf6   KEY_FASTFORWARD>,  //快进按键
             <0xf8   KEY_FASTREVERSE>,  //快退按键
             <0xf2   KEY_BACKSPACE>,    //BaskSpace按键
             <0xf3   KEY_1>,            //按键1
             <0xe7   KEY_2>,
             <0xa1   KEY_3>,
             <0xf7   KEY_4>,
             <0xe3   KEY_5>,
             <0xa5   KEY_6>,
             <0xbd   KEY_7>,
             <0xad   KEY_8>,
             <0xb5   KEY_9>,
             <0xe9   KEY_0>;            //按键0
     };

注意

按键对应的事件是自定义的,事件可根据实际需求确定

9.3. 修改设备树事件头文件

默认使用了rk定义的事件头文件,该文件不全面,使用内核通用的事件头文件linux-event-codes.h,如果不注释rk的头文件会报重复定义的警告。

1
2
//#include <dt-bindings/input/rk-input.h>
#include <dt-bindings/input/linux-event-codes.h>
../../_images/telecontroller_3.jpg

9.4. 编译并替换设备树

参考驱动篇: 编译设备树章节

9.5. 测试

编译并替换设备树后,可进行测试,按下电源按键就会弹出关机窗口,打开桌面终端,按下按键1、2等数字按键,命令行也会同步输入相应数字,与键盘无异。

../../_images/telecontroller_4.jpg

因为驱动使用的是输入子系统,可以检测输入事件的方法检测按键事件。

1
2
#确认红外对应的事件
ls /dev/input/by-path/ -l
../../_images/telecontroller_5.jpg

找到pwm-event对应的事件就是红外的事件。

可以通过以下程序监测输入事件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>

int main(int argc, char *argv[])
{
   struct input_event in_ev = {0};
   int fd = -1;
   int pulse_count=0;

   /* 校验传参 */
   if (2 != argc) {
      fprintf(stderr, "usage: %s <input-dev>\n", argv[0]);
      exit(-1);
   }

   /* 打开文件 */
   if (0 > (fd = open(argv[1], O_RDONLY))) {
      perror("open error");
      exit(-1);
   }

   for ( ; ; ) {

      /* 循环读取数据 */
      if (sizeof(struct input_event) !=
            read(fd, &in_ev, sizeof(struct input_event))) {
            perror("read error");
            exit(-1);
      }

      printf("type:%d code:%d value:%d\n",
               in_ev.type, in_ev.code, in_ev.value);
   }
}

创建buttons.c并将以上内容添加buttons.c,编译并运行

1
2
3
4
5
#编译
gcc buttons.c -o buttons

#运行,需要指定实际的pwm-event
sudo ./buttons /dev/input/event0

以下是按下按键1的情况,对应事件KEY_1。

../../_images/telecontroller_6.jpg

可见,打印的code值为2,对应linux-event-codes.h中的 “#define KEY_1 2”,也即可以通过code值区分事件,value可确定按键是否按下。