C语言开源软件Triggerhappy

想学习单片机的同学可以关注、私信我或者在评论区回复我要入门。每个刚入门的嵌入式的朋友都想多找一些功能小巧、代码质量高,可读性好的开放性的小项目进行观看和学习,主要的目的是锤炼自己的知识,提高编程语言水平。

Triggerhappy (简称 thd)是一个轻量级的热键守护程序 ( lightweight hotkey daemon )。它比较适合小型的嵌入式系统,例如基于 Linux的路由器。

Triggerhappy提供了系统级的热键处理功能。它会监控指定的输入设备文件,解析接收到的事件数据并根据配置文件执行用户指定的操作 (user command)。例如你的设备的 UI是由 2个不同的程序分别处理前后端的,那么你可以使用 Triggerhappy来处理 Home键以返回到前端 UI。

它会根据配置文件的内容,监测 /dev/input/event*设备,然后执行用户预先配置的命令。

例如你的板子上有一个红外接收器,你可以很轻松地使用 Triggerhappy来实现响应红外遥控器的按键事件。

Triggerhappy非常的小巧,大约只有 80K,非常适合嵌入式场景。

Triggerhappy的代码特点:

Triggerhappy的整体代码风格和 Linux设备驱动的代码风格很像,会用一个结构体来描述对象,然后用一个链表将多个对象管理起来。

功能划分很清晰,大约有7、8个功能模块,每一个模块的实现都非常的干净利索,代码一般情况下不超过 300行,而且比较统一。

综合来看,符合 UNIX的设计哲学:简单实用,且内容丰富,是一个非常适合练习 Linux应用编程的开源项目。

Triggerhappy怎么用?

Triggerhappy的用法很简单。

$ thd --dump /dev/input/event2

EV_KEY KEY_A 1 /dev/input/event2

EV_KEY KEY_A 0 /dev/input/event2

EV_KEY KEY_B 1 /dev/input/event2

EV_KEY KEY_B 0 /dev/input/event2

上面的命令会从 /dev/input/event2中读取输入事件,并打印出来。

另外,还可以通过配置文件设置事件处理器:

$ cat /etc/triggerhappy.d/triggerhappy.conf#

KEY_VOLUMEUP 1 /usr/bin/amixer set Master 5%+

KEY_VOLUMEUP 2 /usr/bin/amixer set Master 5%+

KEY_VOLUMEDOWN 1 /usr/bin/amixer set Master 5%-

KEY_VOLUMEDOWN 2 /usr/bin/amixer set Master 5%-

1表示 pressing,2表示 holding。

$ thd --triggers /etc/triggerhappy.d/triggerhappy.conf /dev/input/event*

这样运行后,我们就可以通过 KEY_VOLUMEUP、KEY_VOLUMEDOWN控制音量了。

最后,Triggerhappy还支持通过 socket通讯进行命令行控制:

$ thd --socket /var/run/triggerhappy.socket --triggers /etc/triggerhappy.d/ /dev/input/event*

#动态添加或移除设备

$ th-cmd --socket /var/run/triggerhappy.socket --add /dev/input/event0

th-cmd --socket /var/run/triggerhappy.socket --remove /dev/input/event3

这是一种很实用的设计,工作里,很多时候我发现自己都需要在不重新启动程序的情况动态地通知程序做某些事情。

Triggerhappy怎么实现?

Triggerhappy大致做了下面这些事情。

1、解析配置文件。

根据配置文件创建相应的 trigger,一个 1 trigger代表一条事件触发规则,trigger都挂在链表 trigger_list上:

typedefstructtrigger{

inttype;//类型intcode;//键码intvalue;//键值[...]

char*action;//事件发生时应执行的命令structtrigger*next;}trigger;

解析过程大致是使用 getline()读取一行数据,然后用 strdup()复制出来,最后再用 strtok_r切割出按键、键值、执行命令。

2、创建 socket通讯、信号处理等辅助设施。

这些都是非核心功能,只是让 Triggerhappy变得更易用。

intbind_cmdsocket(char*name);structcommand*read_command(intcmd_fd);intsend_command(intcmd_fd,enumcommand_typetype,char*param,intpassfd,intexclusive,char*tag);intconnect_cmdsocket(char*name);

Triggherhappy包含 2个可执行程序:后台服务程序 thd,命令行工具 thd-cmd。

thd会调用 bind_cmdsocket()创建一个 local socket,thd-cmd通过 connect_cmdsocket()连接它。接着 thd-cmd可以通过 send_command()发送命令,thd则通过 read_command()接收命令。

3、根据命令行参数创建 devices。

1个 device代表 1个输入设备,所有的 device都会挂在链表 device_list上。

typedefstructdevice{

intfd;

char*devname;

structdevice*next;}device;

voidadd_device(char*dev,intfd,intexcl,char*tag);intremove_device(char*dev);voidclear_devices(void);

add_device()会构造一个 device,并且 open()设备以得到文件描述符 fd。

4、不断循环从所有 devices中读取数据。

这个步骤是 Triggerhappy的核心功能,是一个基于 select()的eventloop。

这个 eventloop很简单,就是用 select()检测所有 devices,当有数据可读时,对所有 devices都调用 read_event()读取数据:

读到数据后,会根据键值找到相应的 trigger,并执行 trigger对应的命令,实现方法就是 fork() + system():

到这里Triggerhappy的核心部分我们就说完了。

本期先分享到这里,想要进群学习单片机编程的同学可以私信我,回复“我要入门”,与我们一起成长,喜欢的可以点个赞关注我们!综合来看,Triggerhappy符合 UNIX的设计哲学。它简单实用,内容丰富,代码清晰,是一个非常适合刚入门的嵌入式开发人员练习 Linux应用编程的开源项目。