From d92b84fbc3202bfc9c60d230850a8967fb50fe4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Mon, 4 Apr 2022 17:15:59 +0200 Subject: [PATCH] pc_wifi_drv: add RFKILL support This commits hooks up a RFKILL management to the driver. The 'README' contains instructions on how to use it. Fixes #4506. --- repos/pc/lib/mk/wifi.inc | 5 ++ repos/pc/run/wifi.run | 2 +- repos/pc/src/drivers/wifi/pc/main.cc | 11 ++- repos/pc/src/include/lx_emul/initcall_order.h | 3 +- repos/pc/src/lib/wifi/dep.list | 2 + repos/pc/src/lib/wifi/lx_emul.c | 74 +++++++++++++++++++ repos/pc/src/lib/wifi/lx_emul.h | 2 + repos/pc/src/lib/wifi/lx_user.c | 1 + repos/pc/src/lib/wifi/lx_user.h | 3 + repos/pc/src/lib/wifi/spec/x86_32/source.list | 1 + repos/pc/src/lib/wifi/spec/x86_64/source.list | 1 + repos/pc/src/lib/wifi/wlan.cc | 50 ++++++++++--- repos/pc/src/pc_linux/target.inc | 1 + 13 files changed, 137 insertions(+), 19 deletions(-) diff --git a/repos/pc/lib/mk/wifi.inc b/repos/pc/lib/mk/wifi.inc index 52f50331e0..0db265de1a 100644 --- a/repos/pc/lib/mk/wifi.inc +++ b/repos/pc/lib/mk/wifi.inc @@ -32,6 +32,11 @@ CC_C_OPT += -I$(LX_SRC_DIR)/include/linux CC_C_OPT += -Wno-address-of-packed-member +# need net/rfkill/rfkill.h +CC_OPT_lx_emul += -I$(LX_SRC_DIR) + +CC_C_OPT += -DCONFIG_RFKILL_INPUT + #CC_OPT += -DCONFIG_IWLWIFI_DEBUG diff --git a/repos/pc/run/wifi.run b/repos/pc/run/wifi.run index 65bb545e68..2955fce6cf 100644 --- a/repos/pc/run/wifi.run +++ b/repos/pc/run/wifi.run @@ -155,7 +155,7 @@ append config { } [wifi_config 30 5 no [list "[wifi_ssid] WPA2 [wifi_psk] yes"]] { - + } [wifi_config 30 5 yes [list "[wifi_ssid] WPA2 [wifi_psk] yes"]] { diff --git a/repos/pc/src/drivers/wifi/pc/main.cc b/repos/pc/src/drivers/wifi/pc/main.cc index dc7a09a581..05f78c00fe 100644 --- a/repos/pc/src/drivers/wifi/pc/main.cc +++ b/repos/pc/src/drivers/wifi/pc/main.cc @@ -85,10 +85,9 @@ void wifi_notify_event(void) /* exported by wifi.lib.so */ -extern void wifi_init(Genode::Env&, - Genode::Blockade&, - bool, - Genode::Signal_context_capability); +extern void wifi_init(Genode::Env&, Genode::Blockade&, bool); +extern void wifi_set_rfkill_sigh(Genode::Signal_context_capability); + struct Main { @@ -103,8 +102,7 @@ struct Main { _wpa.construct(env, _wpa_startup_blockade); - wifi_init(env, _wpa_startup_blockade, false, - Genode::Signal_context_capability()); + wifi_init(env, _wpa_startup_blockade, false); } }; @@ -132,6 +130,7 @@ void *wifi_get_buffer(void) _main->_frontend.construct(_main->env); _wifi_frontend = &*_main->_frontend; + wifi_set_rfkill_sigh(_wifi_frontend->rfkill_sigh()); }); return &_wifi_frontend->msg_buffer(); diff --git a/repos/pc/src/include/lx_emul/initcall_order.h b/repos/pc/src/include/lx_emul/initcall_order.h index fcb38449c2..eff6274450 100644 --- a/repos/pc/src/include/lx_emul/initcall_order.h +++ b/repos/pc/src/include/lx_emul/initcall_order.h @@ -1,7 +1,7 @@ /* * \brief Array defining order of Linux Kernel initcalls * \author Automatically generated file - do no edit - * \date 2022-05-03 + * \date 2022-05-13 */ #pragma once @@ -103,6 +103,7 @@ static const char * lx_emul_initcall_order[] = { "__initcall_fib_notifier_init4", "__initcall_ethnl_init4", "__initcall_ieee80211_init4", + "__initcall_rfkill_init4", "__initcall_pci_subsys_init4", "__initcall_nmi_warning_debugfs5", "__initcall_hpet_late_init5", diff --git a/repos/pc/src/lib/wifi/dep.list b/repos/pc/src/lib/wifi/dep.list index be46d3ac29..75ff76de22 100644 --- a/repos/pc/src/lib/wifi/dep.list +++ b/repos/pc/src/lib/wifi/dep.list @@ -154,6 +154,7 @@ include/linux/ip.h include/linux/ipv6_route.h include/linux/kcov.h include/linux/leds.h +include/linux/miscdevice.h include/linux/mpls.h include/linux/netfilter.h include/linux/netfilter_ingress.h @@ -309,6 +310,7 @@ net/mac80211/wme.h net/mac80211/wpa.h net/netlink/af_netlink.h net/packet/internal.h +net/rfkill/rfkill.h net/wireless/core.h net/wireless/debugfs.h net/wireless/nl80211.h diff --git a/repos/pc/src/lib/wifi/lx_emul.c b/repos/pc/src/lib/wifi/lx_emul.c index 10448c1ca2..813b771e2f 100644 --- a/repos/pc/src/lib/wifi/lx_emul.c +++ b/repos/pc/src/lib/wifi/lx_emul.c @@ -510,3 +510,77 @@ void page_frag_free(void * addr) __free_pages(page, 0ul); } + + +#include + +int misc_register(struct miscdevice *misc) +{ + return 0; +} + +void misc_deregister(struct miscdevice *misc) +{ +} + + +/* rfkill support */ + +#include +#include + +int __init rfkill_handler_init(void) +{ + return 0; +} + +static struct +{ + int rfkilled; + int blocked; +} _rfkill_state; + + +struct task_struct *rfkill_task_struct_ptr; + + +int lx_emul_rfkill_get_any(void) +{ + return _rfkill_state.rfkilled; +} + + +void lx_emul_rfkill_switch_all(int blocked) +{ + _rfkill_state.blocked = blocked; +} + + +static int rfkill_task_function(void *arg) +{ + (void)arg; + + for (;;) { + + bool rfkilled = !!rfkill_get_global_sw_state(RFKILL_TYPE_WLAN); + + if (rfkilled != _rfkill_state.blocked) + rfkill_switch_all(RFKILL_TYPE_WLAN, !!_rfkill_state.blocked); + + _rfkill_state.rfkilled = rfkilled; + + lx_emul_task_schedule(true); + } + + return 0; +} + + +void rfkill_init(void) +{ + pid_t pid; + + pid = kernel_thread(rfkill_task_function, NULL, CLONE_FS | CLONE_FILES); + + rfkill_task_struct_ptr = find_task_by_pid_ns(pid, NULL); +} diff --git a/repos/pc/src/lib/wifi/lx_emul.h b/repos/pc/src/lib/wifi/lx_emul.h index b2cf5ffb06..86c5220732 100644 --- a/repos/pc/src/lib/wifi/lx_emul.h +++ b/repos/pc/src/lib/wifi/lx_emul.h @@ -31,6 +31,8 @@ void lx_emul_time_udelay(unsigned long usec); void lx_emul_get_random_bytes(void *buf, unsigned long nbytes); unsigned int lx_emul_get_random_u32(void); +int lx_emul_rfkill_get_any(void); +void lx_emul_rfkill_switch_all(int blocked); #ifdef __cplusplus } diff --git a/repos/pc/src/lib/wifi/lx_user.c b/repos/pc/src/lib/wifi/lx_user.c index 139ef130f6..e16982d508 100644 --- a/repos/pc/src/lib/wifi/lx_user.c +++ b/repos/pc/src/lib/wifi/lx_user.c @@ -21,6 +21,7 @@ void lx_user_init(void) { uplink_init(); + rfkill_init(); socketcall_init(); } diff --git a/repos/pc/src/lib/wifi/lx_user.h b/repos/pc/src/lib/wifi/lx_user.h index 4e12b2fcb4..18ca2f5a55 100644 --- a/repos/pc/src/lib/wifi/lx_user.h +++ b/repos/pc/src/lib/wifi/lx_user.h @@ -23,6 +23,9 @@ void uplink_init(void); extern struct task_struct *socketcall_task_struct_ptr; void socketcall_init(void); +extern struct task_struct *rfkill_task_struct_ptr; +void rfkill_init(void); + #ifdef __cplusplus } #endif diff --git a/repos/pc/src/lib/wifi/spec/x86_32/source.list b/repos/pc/src/lib/wifi/spec/x86_32/source.list index c634ca6e18..3f964700a6 100644 --- a/repos/pc/src/lib/wifi/spec/x86_32/source.list +++ b/repos/pc/src/lib/wifi/spec/x86_32/source.list @@ -250,6 +250,7 @@ net/netlink/af_netlink.c net/netlink/genetlink.c net/netlink/policy.c net/packet/af_packet.c +net/rfkill/core.c net/sched/sch_generic.c net/sched/sch_mq.c net/socket.c diff --git a/repos/pc/src/lib/wifi/spec/x86_64/source.list b/repos/pc/src/lib/wifi/spec/x86_64/source.list index 71778a4f6e..ff3657be71 100644 --- a/repos/pc/src/lib/wifi/spec/x86_64/source.list +++ b/repos/pc/src/lib/wifi/spec/x86_64/source.list @@ -250,6 +250,7 @@ net/netlink/af_netlink.c net/netlink/genetlink.c net/netlink/policy.c net/packet/af_packet.c +net/rfkill/core.c net/sched/sch_generic.c net/sched/sch_mq.c net/socket.c diff --git a/repos/pc/src/lib/wifi/wlan.cc b/repos/pc/src/lib/wifi/wlan.cc index 77a89f9066..4dd9a7820a 100644 --- a/repos/pc/src/lib/wifi/wlan.cc +++ b/repos/pc/src/lib/wifi/wlan.cc @@ -28,19 +28,46 @@ /* local includes */ #include "lx_user.h" - using namespace Genode; +extern "C" int lx_emul_rfkill_get_any(void); +extern "C" void lx_emul_rfkill_switch_all(int blocked); + +static Genode::Signal_context_capability _rfkill_sigh_cap; + bool wifi_get_rfkill(void) { - return false; + if (!rfkill_task_struct_ptr) + return false; + + lx_emul_task_unblock(rfkill_task_struct_ptr); + Lx_kit::env().scheduler.schedule(); + + return lx_emul_rfkill_get_any(); } void wifi_set_rfkill(bool blocked) { - (void)blocked; + if (!rfkill_task_struct_ptr) + return; + + lx_emul_rfkill_switch_all(blocked); + + lx_emul_task_unblock(rfkill_task_struct_ptr); + Lx_kit::env().scheduler.schedule(); + + /* + * We have to open the device again after unblocking + * as otherwise we will get ENETDOWN. So unblock the uplink + * task _afterwards_ because there we call * 'dev_open()' + * unconditionally and that will bring the netdevice UP again. + */ + lx_emul_task_unblock(uplink_task_struct_ptr); + Lx_kit::env().scheduler.schedule(); + + Genode::Signal_transmitter(_rfkill_sigh_cap).submit(); } @@ -57,9 +84,6 @@ extern "C" char const *wifi_ifname(void) return "wlan0"; } - -extern "C" struct task_struct *uplink_task_struct_ptr; - struct Wlan { Env &_env; @@ -90,15 +114,19 @@ struct Wlan Genode::Blockade *wpa_blockade; -void wifi_init(Genode::Env &env, - Genode::Blockade &blockade, - bool disable_11n, - Genode::Signal_context_capability rfkill) +void wifi_init(Genode::Env &env, + Genode::Blockade &blockade, + bool disable_11n) { (void)disable_11n; - (void)rfkill; wpa_blockade = &blockade; static Wlan wlan(env); } + + +void wifi_set_rfkill_sigh(Genode::Signal_context_capability cap) +{ + _rfkill_sigh_cap = cap; +} diff --git a/repos/pc/src/pc_linux/target.inc b/repos/pc/src/pc_linux/target.inc index 12f84eb54d..2851bf457b 100644 --- a/repos/pc/src/pc_linux/target.inc +++ b/repos/pc/src/pc_linux/target.inc @@ -20,6 +20,7 @@ LX_ENABLE += ACPI # general network and WLAN support LX_ENABLE += NET NETDEVICES PACKET LX_ENABLE += WLAN CFG80211 MAC80211 +LX_ENABLE += RFKILL # iwlwifi LX_ENABLE += WLAN_VENDOR_INTEL IWLWIFI IWLDVM IWLMVM