咨询了一下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注册为按键
1 2 3 4 5 6 7 8 9 10 11 12 | #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[]对应,具体如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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函数注册按键
1 2 3 | 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内容匹配条件,定位到对应的执行函数,具体为:
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | [ [ "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/下的脚本。自己也可以添加对应的脚本。