咨询了一下WRTnode开发的相关人员,以及参考网上资料,大致搞明白OpenWrt系统下的按键驱动是怎么回事。
涉及文件:
1、编译模块的文件
build_dir/target-mips_34kc_uClibc-0.9.33.2/Linux-ar71xx_generic/linux-3.18.29/arch/mips/ath79/mach-wrtnode2q.c
kernel/button-hotplug/src/button-hotplug.c
在mach-wrtnode2q.c中改变GPIO号,就可以将我们想要的GPIO注册为按键
#define WRTNODE2Q_GPIO_BTN_WPS 4 static struct gpio_keys_button wrtnode2q_gpio_keys[] __initdata = { { .desc = "WPS button", .type = EV_KEY, .code = KEY_WPS_BUTTON, .debounce_interval = WRTNODE2Q_KEYS_DEBOUNCE_INTERVAL, .gpio = WRTNODE2Q_GPIO_BTN_WPS, //可改为需要注册的GPIO引脚 .active_low = 1, }, };
关键项说明:
.type = EV_KEY 表示是一个 按键事件(linux input系统中持的数据类型中的一种)
.code = KEY_WPS_BUTTON 与 button-hotplug.c 中的button_map[]对应,具体如下
static struct bh_map button_map[] = { BH_MAP(BTN_0, "BTN_0"), BH_MAP(BTN_1, "BTN_1"), BH_MAP(BTN_2, "BTN_2"), BH_MAP(BTN_3, "BTN_3"), BH_MAP(BTN_4, "BTN_4"), BH_MAP(BTN_5, "BTN_5"), BH_MAP(BTN_6, "BTN_6"), BH_MAP(BTN_7, "BTN_7"), BH_MAP(BTN_8, "BTN_8"), BH_MAP(BTN_9, "BTN_9"), BH_MAP(KEY_RESTART, "reset"), BH_MAP(KEY_POWER, "power"), BH_MAP(KEY_RFKILL, "rfkill"), BH_MAP(KEY_WPS_BUTTON, "wps"), BH_MAP(KEY_WIMAX, "wwan"), };
reset、rfkill、power 对应于WRTnode2Q中/etc/rc.button/的脚本,下文具体解释。
然后调用ath79_register_gpio_keys_polled,关联到platform函数注册按键
ath79_register_gpio_keys_polled(-1, WRTNODE2Q_KEYS_POLL_INTERVAL, ARRAY_SIZE(wrtnode2q_gpio_keys), wrtnode2q_gpio_keys);
WRTnode2Q涉及的程序及文件:
/etc/hotplug.json
/etc/rc.button/*
当按键时,则触发驱动中button_hotplug_event函数(button-hotplug.c
):调用button_hotplug_create_event产生uevent事件,调用button_hotplug_fill_even填充事件(JSON格式),并最终调用button_hotplug_work发出uevent广播
上述广播,被procd进程中的hotplug_handler (procd/plug/hotplug.c) 收到,并根据etc/hotplug.json中预先定义的JSON内容匹配条件,定位到对应的执行函数,具体为:
[ [ "case", "ACTION", { "add": [ [ "if", [ "and", [ "has", "MAJOR" ], [ "has", "MINOR" ], ], [ [ "if", [ "or", [ "eq", "DEVNAME", [ "null", "full", "ptmx", "zero" ], ], [ "regex", "DEVNAME", [ "^gpio", "^hvc" ], ], ], [ [ "makedev", "/dev/%DEVNAME%", "0666" ], [ "return" ], ] ], [ "if", [ "or", [ "eq", "DEVNAME", "mapper/control" ], [ "regex", "DEVPATH", "^ppp" ], ], [ [ "makedev", "/dev/%DEVNAME%", "0600" ], [ "return" ], ], ], [ "if", [ "has", "DEVNAME" ], [ "makedev", "/dev/%DEVNAME%", "0644" ], ], ], ], [ "if", [ "has", "FIRMWARE" ], [ [ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ], [ "load-firmware", "/lib/firmware" ], [ "return" ] ] ], ], "remove" : [ [ "if", [ "and", [ "has", "DEVNAME" ], [ "has", "MAJOR" ], [ "has", "MINOR" ], ], [ "rm", "/dev/%DEVNAME%" ] ] ] } ], [ "if", [ "eq", "SUBSYSTEM", "platform" ], [ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ] ], [ "if", [ "and", [ "has", "BUTTON" ], [ "eq", "SUBSYSTEM", "button" ], ], [ "exec", "/etc/rc.button/%BUTTON%" ] ], [ "if", [ "eq", "SUBSYSTEM", [ "net", "input", "usb", "usbmisc", "ieee1394", "block", "atm", "zaptel", "tty", "button" ] ], [ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ] ], [ "if", [ "and", [ "eq", "SUBSYSTEM", "usb-serial" ], [ "regex", "DEVNAME", [ "^ttyUSB", "^ttyACM" ] ], ], [ "exec", "/sbin/hotplug-call", "tty" ] ], ]
即调用了 /ect/rc.button/下的脚本。自己也可以添加对应的脚本。