确定要使用的GPIO,这里需要使用带外部中断的引脚,否则驱动注册失败 request:-22
这是我的设备树配置
ir_gpio {
compatible = "gpio-ir-receiver";
gpios = <&pio 1 5 GPIO_ACTIVE_LOW>; /* PB5 */
/*active_low = <1>;*/
linux,rc-map-name = "rc-tevii-nec";
status = "okay";
};
内核里修改
Device Drivers > Remote Controller support >
[*] LIRC user interface
[*] Remote controller decoders --->
[*] Remote Controller devices --->
<*> GPIO IR remote control
驱动成功加载会有如下输出
[ 1.223257] IR NEC protocol handler initialized
[ 1.227806] IR RC5(x/sz) protocol handler initialized
[ 1.232985] IR RC6 protocol handler initialized
[ 1.237517] IR JVC protocol handler initialized
[ 1.242080] IR Sony protocol handler initialized
[ 1.246693] IR SANYO protocol handler initialized
[ 1.251406] IR Sharp protocol handler initialized
[ 1.256104] IR RCMM protocol handler initialized
[ 1.261050] Registered IR keymap rc-tevii-nec
[ 1.265477] rc rc0: gpio_ir_recv as /devices/platform/ir_gpio/rc/rc0
[ 1.272194] rc rc0: lirc_dev: driver gpio_ir_recv registered at minor = 0, raw IR receiver, no transmitter
[ 1.282144] input: gpio_ir_recv as /devices/platform/ir_gpio/rc/rc0/input3
此时查看/dev/input目录下,会有如下显示:
# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: 1c22800.lradc
/dev/input/event1: rotary@0
/dev/input/event2: ns2009_ts
/dev/input/event3: gpio_ir_recv
此时如果用evtest测试按键是没有任何反应的,需要修改对应的驱动,此问题先留在这里
不影响后续操作
后来查资料,发现可以用lirc里的工具去测试硬件是否OK,测试之前要先修改默认配置文件,不修改的话,同样没反应
# vi /etc/lirc/lirc_options.conf
driver = default
device = /dev/lric0
修改这2行就可以,里边driver默认是uinput,device默认是auto
再次测试就有反应了
# mode2 -m -d /dev/lirc0
Using driver default on device /dev/lirc0
Trying device: /dev/lirc0
Using device: /dev/lirc0
Warning: Running as root.
9043 4402 626 497 656 499
624 499 656 499 624 499
656 499 624 499 624 531
624 1630 619 1624 655 1624
624 1624 624 1634 646 1624
624 1624 655 1624 593 1656
624 501 654 1624 593 534
652 1624 624 499 625 1624
656 504 619 499 655 1625
624 499 656 1625 593 531
624 1633 648 498 624 1624
624 40035
9060 2184 624 143451-pulse 483450-space
从这结果上可以明显的看出这些数值代表脉冲宽度,单位是us
使用irrecod -f -d /dev/lirc0 –disable-namespace来录制配置文件
录制完成后放到 /etc/lric/liricd.conf.d/下边
!注意,这里录制的结果不准确,需要借助上边的命令来获取每一个按键的值,这里只是借用一下配置文件的格式,里边的数字是右对齐
示例:
# Please take the time to finish this file as described in
# https://sourceforge.net/p/lirc-remotes/wiki/Checklist/
# and make it available to others by sending it to
# <lirc@bartelmus.de>
#
# This config file was automatically generated
# using lirc-0.10.1(default) on Thu Jan 1 01:37:06 1970
# Command line used: -f -d /dev/lirc0 --disable-namespace
# Kernel version (uname -r): 5.10.19
#
# Remote name (as of config file): elac
# Brand of remote device, the thing you hold in your hand:
# Remote device model nr:
# Remote device info url:
# Does remote device has a bundled capture device e. g., a
# usb dongle? :
# For bundled USB devices: usb vendor id, product id
# and device string (use dmesg or lsusb):
# Type of device controlled
# (TV, VCR, Audio, DVD, Satellite, Cable, HTPC, ...) :
# Device(s) controlled by this remote:
begin remote
name elac
flags RAW_CODES|CONST_LENGTH
eps 30
aeps 100
gap 108533
begin raw_codes
name Power
9043 4403 623 531 593 531
624 531 593 531 624 531
593 531 624 531 593 536
594 1680 592 1656 593 1656
625 1655 593 1666 582 1656
624 1656 593 1655 625 530
593 534 621 530 593 1656
624 1624 624 531 593 530
624 531 595 1655 623 1655
593 1656 593 530 624 531
593 1664 616 1656 593 1656
593
name BT
9041 4407 622 531 593 531
593 562 593 531 593 531
625 533 596 525 624 530
593 1656 624 1656 593 1655
593 1664 616 1655 593 1656
593 1656 624 1658 591 530
624 1656 593 531 624 531
593 531 593 531 624 1661
587 530 624 1656 593 531
593 1687 593 1656 601 1648
624 1656 593 531 593 1656
624
name Vol+
9013 4437 592 530 593 562
593 531 624 531 593 531
594 565 589 530 593 531
624 1656 593 1656 624 1665
590 1651 591 1656 624 1655
593 1656 593 1667 613 531
593 1656 624 1656 593 531
593 562 595 528 593 1656
624 531 593 1656 624 531
593 530 593 1659 621 1655
593 1656 593 562 593 1656
593
name Vol-
9044 4436 592 531 624 531
593 533 622 530 593 531
593 531 624 531 593 530
624 1656 593 1661 595 1679
593 1655 593 1656 624 1656
593 1667 582 1659 620 530
593 1656 624 1656 600 524
624 1656 593 531 593 531
624 531 593 1656 624 531
598 530 620 1654 593 531
624 1625 624 1656 593 1666
614
name Pre
9048 4403 592 562 593 530
593 562 593 530 593 531
624 531 593 531 624 531
593 1661 593 1680 592 1656
593 1656 624 1656 603 1650
588 1656 623 1656 593 1656
624 1662 587 1655 593 531
624 531 593 531 624 1656
593 531 631 524 593 530
593 562 593 1656 593 1656
624 1663 586 530 624 1624
624
name Next
9022 4425 593 530 624 531
593 531 624 531 597 527
623 531 593 531 593 562
593 1656 593 1656 624 1663
585 1655 624 1656 593 1656
593 1656 633 1646 593 1656
593 562 593 1656 593 530
624 1658 591 531 593 562
593 531 624 531 593 1656
624 499 624 1659 591 530
624 1656 593 1656 593 1687
601
name Play
9027 4431 592 531 624 531
593 531 624 531 593 531
593 562 593 531 624 531
598 1652 592 1655 624 1656
593 1656 624 1633 616 1656
593 1656 624 1624 624 1656
595 529 624 1656 593 531
593 1687 593 531 593 1665
620 526 592 530 624 1656
593 531 594 1655 624 531
593 1665 615 531 593 1656
624
name Ana1
9044 4408 621 530 593 530
624 531 593 531 593 562
593 531 593 562 593 531
593 1655 624 1656 593 1655
597 1654 621 1655 593 1655
624 1624 624 1665 584 530
625 530 593 1656 593 562
593 531 624 499 624 531
599 525 624 1655 593 1656
593 562 593 1656 593 1659
621 1655 593 1656 593 1656
624
name Ana2
9040 4402 656 500 624 499
656 499 624 499 624 531
624 499 624 531 624 499
624 1632 655 1628 589 1650
593 1655 624 1655 593 1670
610 1656 593 1656 593 531
624 1656 596 1655 590 562
593 531 624 500 624 531
593 531 624 1656 599 529
620 530 593 1656 624 1625
624 1656 593 1662 619 1656
593
name Opt1
9016 4435 624 530 593 531
624 533 591 531 624 531
593 531 593 562 593 531
593 1656 624 1685 564 1655
624 1624 624 1656 593 1656
637 1643 593 1656 593 531
624 531 593 1656 624 531
596 1653 624 531 593 531
593 562 593 1656 593 1656
630 526 591 1656 624 531
593 1656 593 1656 624 1664
585
name Opt2
9043 4403 655 499 624 499
656 499 627 497 656 499
624 499 625 530 624 502
628 1618 655 1654 601 1619
623 1624 656 1624 624 1624
656 1636 613 1625 624 499
656 499 624 499 656 499
624 1626 622 531 624 499
624 531 624 1624 624 1624
624 1662 618 1624 624 499
656 1624 624 1624 624 1665
615
name Coax
9015 4439 591 531 624 531
593 530 624 531 593 531
593 562 593 531 593 531
624 1656 593 1656 624 1656
611 1642 589 1655 624 1656
593 1656 593 1668 613 1655
593 1656 593 1656 624 531
593 1658 622 531 593 530
593 562 593 531 624 531
656 468 593 1656 630 525
592 1655 593 1687 593 1656
593
name USB
9050 4433 593 531 594 561
593 531 593 531 624 531
593 531 624 530 593 531
624 1656 603 1645 593 1656
624 1656 593 1655 624 1659
590 1655 593 1656 624 531
593 531 624 531 593 537
618 530 593 531 624 1656
593 531 624 1624 624 1662
587 1655 624 1655 593 1656
593 1656 632 523 593 1656
624
end raw_codes
end remote
接下来使用irw来验证刚才录制的是否正确
# irw
lircd-0.10.1[432]: Notice: accepted new client on /var/run/lirc/lircd
lircd-0.10.1[432]: Info: [lirc] protocol is enabled
0000000000000001 00 Power elac
0000000000000002 00 BT elac
0000000000000003 00 Vol+ elac
0000000000000004 00 Vol- elac
0000000000000008 00 Ana1 elac
000000000000000a 00 Opt1 elac
000000000000000b 00 Opt2 elac
然后在/etc/lirc/目录下创建lircrc配置文件或~/.lircrc
格式如下
begin
prog = irexec
button = Power
repeat = 0
config = echo "power"
end
begin
prog = irexec
button = Vol+
repeat = 1
config = amixer -M -c 0 sset 'Headphone',0 1%+ > /dev/null
end
begin
prog = irexec
button = Vol-
repeat = 1
config = amixer -M -c 0 sset 'Headphone',0 1%- > /dev/null
end
保存
最后就是使用irexec来进行各种操作了,无需编程,到这里可以自由发挥了,想要集成到代码里也很简单,看下图
# irexec
lircd-0.10.1[448]: Notice: accepted new client on /var/run/lirc/lircd
lircd-0.10.1[448]: Info: [lirc] protocol is enabled
power
Simple mixer control 'Headphone',0
Capabilities: pvolume pvolume-joined pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 63
Mono:
Front Left: Playback 47 [54%] [-16.00dB] [on]
Front Right: Playback 47 [54%] [-16.00dB] [on]
Simple mixer control 'Headphone',0
Capabilities: pvolume pvolume-joined pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 63
Mono:
Front Left: Playback 45 [50%] [-18.00dB] [on]
Front Right: Playback 45 [50%] [-18.00dB] [on]
power
LIRC处理流程
+--------+ +-------------+ +--------+
| | | Linux input | | Appli- |
--->---| kernel |---->----| layer |---------->----------| cation |
| | | | /dev/input/eventX | |
+--------+ +-------------+ +--------+
+--------+ +-------------+
| | | Linux input |
--->---| kernel |---->----| layer |
| | | |
+--------+ +-------------+
|
v
|
| +--------+
+-------------+ | Appli- |
| lirc |---------->----------| cation |-+
| | lirc socket | | |
+-------------+ +--------+ |-+
| | |
+--------+ |
| |
+--------+
+--------+ +-------------+ +--------+
| | | | | Appli- |
--->---| kernel |---->----| lirc |---------->----------| cation |-+
| | | | lirc socket | | |
+--------+ +-------------+ +--------+ |-+
| | |
+--------+ |
| |
+--------+
通过socket使用lirc,不需要引入任何文件,可以方便的集成到代码里,就是上述第三种方式
struct sigaction act;
char buf[128];
struct sockaddr_un addr;
typedef struct
{
char addr[32];
char code[8];
char type[16];
char name[16];
} IRW_DATA;
IRW_DATA irw_data;
act.sa_handler = sigusr1;
sigfillset(&act.sa_mask);
act.sa_flags = SA_RESTART; /* don't fiddle with EINTR */
sigaction(SIGUSR1, &act, NULL);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/var/run/lirc/lircd");
fd_lircd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
if (fd_lircd == -1)
{
printf("Create socket failed\n");
}
if (connect(fd_lircd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
printf("Cannot connect to socket %s\n", addr.sun_path);
}
while (1)
{
// lircd
if (read(fd_lircd, buf, 128) > 0)
{
LOG_D("%s\n", buf);
char *p = strtok(buf, " ");
int i = 0;
while (p)
{
// LOG_D("%s\n", p);
if (i == 0)
strcpy(irw_data.addr, p);
else if (i == 1)
strcpy(irw_data.code, p);
else if (i == 2)
strcpy(irw_data.type, p);
else if (i == 3)
strcpy(irw_data.name, p);
p = strtok(NULL, " ");
i++;
}
LOG_D("%s\n", irw_data.type);
switch ((uint8_t)strtol(irw_data.addr, NULL, 10))
{
case Vol_up:
rotary_encoder_handler(&u8g2, -1);
break;
case Vol_down:
rotary_encoder_handler(&u8g2, 1);
break;
case Play:
rotary_encoder_button_handler(&u8g2);
break;
case Bt:
printf("BT button\n");
break;
}
}
}
测试的硬件
离线