咨询了一下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/下的脚本。自己也可以添加对应的脚本。